<p><b>dwj07@fsu.edu</b> 2013-03-14 14:15:45 -0600 (Thu, 14 Mar 2013)</p><p><br>
        -- BRANCH COMMIT --<br>
<br>
        Updating Registry to read a XML based Registry file.<br>
        Adding the ezxml library for parsing the XML file.<br>
<br>
        The XML parser is in it's own function call in parse.c, as was the previous parser.<br>
        This way it could potentially be modified at a later point in time.<br>
<br>
        Adding the schema definition for Registry to src/registry/Registry.xsd.<br>
        This schema has comments to describe what each element/attribute is supposed to be used for.<br>
        It also describes which attributes are required, and which are optional. It should be useful for people just getting started with registry.<br>
        It can also allow people to validate Registry.xml files.<br>
<br>
        Adding a starter Registry.xml file for the ocean core. Using this Registry.xml file, results are bit-reproducible with the ocean core on the trunk.<br>
        And the same number of lines are written to the .inc files as compared with the old Registry file, and then .inc files generated from the old parser.<br>
</p><hr noshade><pre><font color="gray">Modified: branches/xml_registry/src/Makefile
===================================================================
--- branches/xml_registry/src/Makefile        2013-03-14 19:21:28 UTC (rev 2611)
+++ branches/xml_registry/src/Makefile        2013-03-14 20:15:45 UTC (rev 2612)
@@ -10,7 +10,6 @@
 
 all: mpas
 
-
 mpas: reg_includes externals frame ops dycore drver
         $(LINKER) $(LDFLAGS) -o $(CORE)_model.exe driver/*.o -L. -ldycore -lops -lframework $(LIBS) -I./external/esmf_time_f90 -L./external/esmf_time_f90 -lesmf_time
 
@@ -23,7 +22,7 @@
 
 reg_includes: 
         ( cd registry; $(MAKE) CC=&quot;$(SCC)&quot; )
-        ( cd inc; $(CPP) ../core_$(CORE)/Registry | ../registry/parse &gt; Registry.processed)
+        ( cd inc; $(CPP) ../core_$(CORE)/Registry.xml | ../registry/parse &gt; Registry.processed)
 
 frame: reg_includes externals
         ( cd framework; $(MAKE) CPPFLAGS=&quot;$(CPPFLAGS)&quot; CPPINCLUDES=&quot;$(CPPINCLUDES)&quot; all ) 

Added: branches/xml_registry/src/core_ocean/Registry.xml
===================================================================
--- branches/xml_registry/src/core_ocean/Registry.xml                                (rev 0)
+++ branches/xml_registry/src/core_ocean/Registry.xml        2013-03-14 20:15:45 UTC (rev 2612)
@@ -0,0 +1,364 @@
+&lt;?xml version=&quot;1.0&quot;?&gt;
+&lt;registry&gt;
+        &lt;dims&gt;
+                &lt;dim name=&quot;nCells&quot;/&gt;
+                &lt;dim name=&quot;nEdges&quot;/&gt;
+                &lt;dim name=&quot;maxEdges&quot;/&gt;
+                &lt;dim name=&quot;maxEdges2&quot;/&gt;
+                &lt;dim name=&quot;nAdvectionCells&quot;    definition=&quot;maxEdges2+0&quot;/&gt;
+                &lt;dim name=&quot;nVertices&quot;/&gt;
+                &lt;dim name=&quot;TWO&quot;                definition=&quot;2&quot;/&gt;
+                &lt;dim name=&quot;R3&quot;                 definition=&quot;3&quot;/&gt;
+                &lt;dim name=&quot;FIFTEEN&quot;            definition=&quot;15&quot;/&gt;
+                &lt;dim name=&quot;TWENTYONE&quot;          definition=&quot;21&quot;/&gt;
+                &lt;dim name=&quot;vertexDegree&quot;/&gt;
+                &lt;dim name=&quot;nVertLevels&quot;/&gt;
+                &lt;dim name=&quot;nVertLevelsP1&quot;      definition=&quot;nVertLevels+1&quot;/&gt;
+                &lt;dim name=&quot;nMonths&quot;/&gt;
+        &lt;/dims&gt;
+        &lt;nml_record name=&quot;time_management&quot;&gt;
+                &lt;nml_option name=&quot;config_do_restart&quot;                 type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_start_time&quot;                 type=&quot;character&quot;        default_value=&quot;'0000-01-01_00:00:00'&quot;/&gt;
+                &lt;nml_option name=&quot;config_stop_time&quot;                  type=&quot;character&quot;        default_value=&quot;'none'&quot;/&gt;
+                &lt;nml_option name=&quot;config_run_duration&quot;               type=&quot;character&quot;        default_value=&quot;'0_06:00:00'&quot;/&gt;
+                &lt;nml_option name=&quot;config_calendar_type&quot;              type=&quot;character&quot;        default_value=&quot;'360day'&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;io&quot;&gt;
+                &lt;nml_option name=&quot;config_input_name&quot;                 type=&quot;character&quot;        default_value=&quot;'grid.nc'&quot;/&gt;
+                &lt;nml_option name=&quot;config_output_name&quot;                type=&quot;character&quot;        default_value=&quot;'output.nc'&quot;/&gt;
+                &lt;nml_option name=&quot;config_restart_name&quot;               type=&quot;character&quot;        default_value=&quot;'restart.nc'&quot;/&gt;
+                &lt;nml_option name=&quot;config_restart_interval&quot;           type=&quot;character&quot;        default_value=&quot;'0_06:00:00'&quot;/&gt;
+                &lt;nml_option name=&quot;config_output_interval&quot;            type=&quot;character&quot;        default_value=&quot;'0_06:00:00'&quot;/&gt;
+                &lt;nml_option name=&quot;config_stats_interval&quot;             type=&quot;character&quot;        default_value=&quot;'0_01:00:00'&quot;/&gt;
+                &lt;nml_option name=&quot;config_write_stats_on_startup&quot;     type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_write_output_on_startup&quot;    type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_frames_per_outfile&quot;         type=&quot;integer&quot;       default_value=&quot;1000&quot;/&gt;
+                &lt;nml_option name=&quot;config_pio_num_iotasks&quot;            type=&quot;integer&quot;       default_value=&quot;0&quot;/&gt;
+                &lt;nml_option name=&quot;config_pio_stride&quot;                 type=&quot;integer&quot;       default_value=&quot;1&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;time_integration&quot;&gt;
+                &lt;nml_option name=&quot;config_dt&quot;                         type=&quot;real&quot;          default_value=&quot;3000.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_time_integrator&quot;            type=&quot;character&quot;        default_value=&quot;'split_explicit'&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;grid&quot;&gt;
+                &lt;nml_option name=&quot;config_num_halos&quot;                  type=&quot;integer&quot;       default_value=&quot;3&quot;/&gt;
+                &lt;nml_option name=&quot;config_vert_coord_movement&quot;        type=&quot;character&quot;        default_value=&quot;'uniform_stretching'&quot;/&gt;
+                &lt;nml_option name=&quot;config_alter_ICs_for_pbcs&quot;         type=&quot;character&quot;        default_value=&quot;'zlevel_pbcs_off'&quot;/&gt;
+                &lt;nml_option name=&quot;config_min_pbc_fraction&quot;           type=&quot;real&quot;          default_value=&quot;0.10&quot;/&gt;
+                &lt;nml_option name=&quot;config_check_ssh_consistency&quot;      type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;decomposition&quot;&gt;
+                &lt;nml_option name=&quot;config_block_decomp_file_prefix&quot;   type=&quot;character&quot;        default_value=&quot;'graph.info.part.'&quot;/&gt;
+                &lt;nml_option name=&quot;config_number_of_blocks&quot;           type=&quot;integer&quot;       default_value=&quot;0&quot;/&gt;
+                &lt;nml_option name=&quot;config_explicit_proc_decomp&quot;       type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_proc_decomp_file_prefix&quot;    type=&quot;character&quot;        default_value=&quot;'graph.info.part.'&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;hmix&quot;&gt;
+                &lt;nml_option name=&quot;config_hmix_ScaleWithMesh&quot;         type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_visc_vorticity_term&quot;        type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_apvm_scale_factor&quot;          type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;hmix_del2&quot;&gt;
+                &lt;nml_option name=&quot;config_use_mom_del2&quot;               type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_use_tracer_del2&quot;            type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_mom_del2&quot;                   type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_tracer_del2&quot;                type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_vorticity_del2_scale&quot;       type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;hmix_del4&quot;&gt;
+                &lt;nml_option name=&quot;config_use_mom_del4&quot;               type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_use_tracer_del4&quot;            type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_mom_del4&quot;                   type=&quot;real&quot;          default_value=&quot;5.0e13&quot;/&gt;
+                &lt;nml_option name=&quot;config_tracer_del4&quot;                type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_vorticity_del4_scale&quot;       type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;hmix_Leith&quot;&gt;
+                &lt;nml_option name=&quot;config_use_Leith_del2&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_Leith_parameter&quot;            type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_Leith_dx&quot;                   type=&quot;real&quot;          default_value=&quot;15000.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_Leith_visc2_max&quot;            type=&quot;real&quot;          default_value=&quot;2.5e3&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;standard_GM&quot;&gt;
+                &lt;nml_option name=&quot;config_h_kappa&quot;                    type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_h_kappa_q&quot;                  type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;Rayleigh_damping&quot;&gt;
+                &lt;nml_option name=&quot;config_Rayleigh_friction&quot;          type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_Rayleigh_damping_coeff&quot;     type=&quot;real&quot;          default_value=&quot;0.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;vmix&quot;&gt;
+                &lt;nml_option name=&quot;config_convective_visc&quot;            type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_convective_diff&quot;            type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;vmix_const&quot;&gt;
+                &lt;nml_option name=&quot;config_use_const_visc&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_use_const_diff&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_vert_visc&quot;                  type=&quot;real&quot;          default_value=&quot;2.5e-4&quot;/&gt;
+                &lt;nml_option name=&quot;config_vert_diff&quot;                  type=&quot;real&quot;          default_value=&quot;2.5e-5&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;vmix_rich&quot;&gt;
+                &lt;nml_option name=&quot;config_use_rich_visc&quot;              type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_use_rich_diff&quot;              type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_bkrd_vert_visc&quot;             type=&quot;real&quot;          default_value=&quot;1.0e-4&quot;/&gt;
+                &lt;nml_option name=&quot;config_bkrd_vert_diff&quot;             type=&quot;real&quot;          default_value=&quot;1.0e-5&quot;/&gt;
+                &lt;nml_option name=&quot;config_rich_mix&quot;                   type=&quot;real&quot;          default_value=&quot;0.005&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;vmix_tanh&quot;&gt;
+                &lt;nml_option name=&quot;config_use_tanh_visc&quot;              type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_use_tanh_diff&quot;              type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_max_visc_tanh&quot;              type=&quot;real&quot;          default_value=&quot;2.5e-1&quot;/&gt;
+                &lt;nml_option name=&quot;config_min_visc_tanh&quot;              type=&quot;real&quot;          default_value=&quot;1.0e-4&quot;/&gt;
+                &lt;nml_option name=&quot;config_max_diff_tanh&quot;              type=&quot;real&quot;          default_value=&quot;2.5e-2&quot;/&gt;
+                &lt;nml_option name=&quot;config_min_diff_tanh&quot;              type=&quot;real&quot;          default_value=&quot;1.0e-5&quot;/&gt;
+                &lt;nml_option name=&quot;config_zMid_tanh&quot;                  type=&quot;real&quot;          default_value=&quot;-100&quot;/&gt;
+                &lt;nml_option name=&quot;config_zWidth_tanh&quot;                type=&quot;real&quot;          default_value=&quot;100&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;forcing&quot;&gt;
+                &lt;nml_option name=&quot;config_use_monthly_forcing&quot;        type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_restoreTS&quot;                  type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_restoreT_timescale&quot;         type=&quot;real&quot;          default_value=&quot;90.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_restoreS_timescale&quot;         type=&quot;real&quot;          default_value=&quot;90.0&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;advection&quot;&gt;
+                &lt;nml_option name=&quot;config_vert_tracer_adv&quot;            type=&quot;character&quot;        default_value=&quot;'stencil'&quot;/&gt;
+                &lt;nml_option name=&quot;config_vert_tracer_adv_order&quot;      type=&quot;integer&quot;       default_value=&quot;3&quot;/&gt;
+                &lt;nml_option name=&quot;config_horiz_tracer_adv_order&quot;     type=&quot;integer&quot;       default_value=&quot;3&quot;/&gt;
+                &lt;nml_option name=&quot;config_coef_3rd_order&quot;             type=&quot;real&quot;          default_value=&quot;0.25&quot;/&gt;
+                &lt;nml_option name=&quot;config_monotonic&quot;                  type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;bottom_drag&quot;&gt;
+                &lt;nml_option name=&quot;config_bottom_drag_coeff&quot;          type=&quot;real&quot;          default_value=&quot;1.0e-3&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;pressure_gradient&quot;&gt;
+                &lt;nml_option name=&quot;config_pressure_gradient_type&quot;     type=&quot;character&quot;        default_value=&quot;'pressure_and_zmid'&quot;/&gt;
+                &lt;nml_option name=&quot;config_rho0&quot;                       type=&quot;real&quot;          default_value=&quot;1014.65&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;eos&quot;&gt;
+                &lt;nml_option name=&quot;config_eos_type&quot;                   type=&quot;character&quot;        default_value=&quot;'jm'&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;eos_linear&quot;&gt;
+                &lt;nml_option name=&quot;config_eos_linear_alpha&quot;           type=&quot;real&quot;          default_value=&quot;2.55e-1&quot;/&gt;
+                &lt;nml_option name=&quot;config_eos_linear_beta&quot;            type=&quot;real&quot;          default_value=&quot;7.64e-1&quot;/&gt;
+                &lt;nml_option name=&quot;config_eos_linear_Tref&quot;            type=&quot;real&quot;          default_value=&quot;19.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_eos_linear_Sref&quot;            type=&quot;real&quot;          default_value=&quot;35.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_eos_linear_rhoref&quot;          type=&quot;real&quot;          default_value=&quot;1025.022&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;split_explicit_ts&quot;&gt;
+                &lt;nml_option name=&quot;config_n_ts_iter&quot;                  type=&quot;integer&quot;       default_value=&quot;2&quot;/&gt;
+                &lt;nml_option name=&quot;config_n_bcl_iter_beg&quot;             type=&quot;integer&quot;       default_value=&quot;1&quot;/&gt;
+                &lt;nml_option name=&quot;config_n_bcl_iter_mid&quot;             type=&quot;integer&quot;       default_value=&quot;2&quot;/&gt;
+                &lt;nml_option name=&quot;config_n_bcl_iter_end&quot;             type=&quot;integer&quot;       default_value=&quot;2&quot;/&gt;
+                &lt;nml_option name=&quot;config_n_btr_subcycles&quot;            type=&quot;integer&quot;       default_value=&quot;20&quot;/&gt;
+                &lt;nml_option name=&quot;config_n_btr_cor_iter&quot;             type=&quot;integer&quot;       default_value=&quot;2&quot;/&gt;
+                &lt;nml_option name=&quot;config_u_correction&quot;               type=&quot;logical&quot;       default_value=&quot;.true.&quot;/&gt;
+                &lt;nml_option name=&quot;config_btr_subcycle_loop_factor&quot;   type=&quot;integer&quot;       default_value=&quot;2&quot;/&gt;
+                &lt;nml_option name=&quot;config_btr_gam1_uWt1&quot;              type=&quot;real&quot;          default_value=&quot;0.5&quot;/&gt;
+                &lt;nml_option name=&quot;config_btr_gam2_SSHWt1&quot;            type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_btr_gam3_uWt2&quot;              type=&quot;real&quot;          default_value=&quot;1.0&quot;/&gt;
+                &lt;nml_option name=&quot;config_btr_solve_SSH2&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;nml_record name=&quot;debug&quot;&gt;
+                &lt;nml_option name=&quot;config_check_zlevel_consistency&quot;   type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_filter_btr_mode&quot;            type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_prescribe_velocity&quot;         type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_prescribe_thickness&quot;        type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_include_KE_vertex&quot;          type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_check_tracer_monotonicity&quot;  type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_h_all_tend&quot;         type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_h_hadv&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_h_vadv&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_all_tend&quot;         type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_coriolis&quot;         type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_pgrad&quot;            type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_hmix&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_windstress&quot;       type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_vmix&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_u_vadv&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_tr_all_tend&quot;        type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_tr_adv&quot;             type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_tr_hmix&quot;            type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+                &lt;nml_option name=&quot;config_disable_tr_vmix&quot;            type=&quot;logical&quot;       default_value=&quot;.false.&quot;/&gt;
+        &lt;/nml_record&gt;
+        &lt;var_struct name=&quot;state&quot; time_levs=&quot;2&quot;&gt;
+                &lt;var_array name=&quot;tracers&quot; type=&quot;real&quot; dimensions=&quot;nVertLevels nCells Time&quot;&gt;
+                        &lt;var name=&quot;temperature&quot;        array_group=&quot;dynamics&quot;    streams=&quot;iro&quot;/&gt;
+                        &lt;var name=&quot;salinity&quot;           array_group=&quot;dynamics&quot;    streams=&quot;iro&quot;/&gt;
+                        &lt;var name=&quot;tracer1&quot;            array_group=&quot;testing&quot;     streams=&quot;iro&quot;/&gt;
+                &lt;/var_array&gt;
+                &lt;var name=&quot;xtime&quot;                             type=&quot;text&quot;     dimensions=&quot;Time&quot;                        streams=&quot;ro&quot;/&gt;
+                &lt;var name=&quot;u&quot;                                 type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;     streams=&quot;ir&quot; units=&quot;m/s&quot;
+                         description=&quot;Normal velocity at edge midpoints.&quot;
+                /&gt;
+                &lt;var name=&quot;h&quot;                                 type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;iro&quot; units=&quot;m&quot;
+                         description=&quot;Layer thickness at cell centers.&quot;
+                /&gt;
+                &lt;var name=&quot;rho&quot;                               type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;uBtr&quot;                              type=&quot;real&quot;     dimensions=&quot;nEdges Time&quot;                 streams=&quot;r&quot;/&gt;
+                &lt;var name=&quot;ssh&quot;                               type=&quot;real&quot;     dimensions=&quot;nCells Time&quot;                 streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;uBtrSubcycle&quot;                      type=&quot;real&quot;     dimensions=&quot;nEdges Time&quot;/&gt;
+                &lt;var name=&quot;sshSubcycle&quot;                       type=&quot;real&quot;     dimensions=&quot;nCells Time&quot;/&gt;
+                &lt;var name=&quot;FBtr&quot;                              type=&quot;real&quot;     dimensions=&quot;nEdges Time&quot;/&gt;
+                &lt;var name=&quot;GBtrForcing&quot;                       type=&quot;real&quot;     dimensions=&quot;nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uBcl&quot;                              type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;zMid&quot;                              type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;v&quot;                                 type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uTransport&quot;                        type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uBolusGM&quot;                          type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uBolusGMX&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uBolusGMY&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uBolusGMZ&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;uBolusGMZonal&quot;                     type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;uBolusGMMeridional&quot;                type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;hEddyFlux&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;h_kappa&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;h_kappa_q&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;divergence&quot;                        type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;vorticity&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nVertices Time&quot;  streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;Vor_edge&quot;                          type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;h_edge&quot;                            type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;h_vertex&quot;                          type=&quot;real&quot;     dimensions=&quot;nVertLevels nVertices Time&quot;/&gt;
+                &lt;var name=&quot;ke&quot;                                type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;kev&quot;                               type=&quot;real&quot;     dimensions=&quot;nVertLevels nVertices Time&quot;  streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;kevc&quot;                              type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;ke_edge&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;Vor_vertex&quot;                        type=&quot;real&quot;     dimensions=&quot;nVertLevels nVertices Time&quot;/&gt;
+                &lt;var name=&quot;Vor_cell&quot;                          type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;uReconstructX&quot;                     type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;uReconstructY&quot;                     type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;uReconstructZ&quot;                     type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;uReconstructZonal&quot;                 type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;uReconstructMeridional&quot;            type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;uSrcReconstructX&quot;                  type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;uSrcReconstructY&quot;                  type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;uSrcReconstructZ&quot;                  type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;uSrcReconstructZonal&quot;              type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;uSrcReconstructMeridional&quot;         type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;MontPot&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;pressure&quot;                          type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;wTop&quot;                              type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nCells Time&quot;/&gt;
+                &lt;var name=&quot;vertVelocityTop&quot;                   type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nCells Time&quot;/&gt;
+                &lt;var name=&quot;rhoDisplaced&quot;                      type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;BruntVaisalaFreqTop&quot;               type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;viscosity&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;vh&quot;                                type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;circulation&quot;                       type=&quot;real&quot;     dimensions=&quot;nVertLevels nVertices Time&quot;/&gt;
+                &lt;var name=&quot;gradVor_t&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;gradVor_n&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;areaCellGlobal&quot;                    type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;areaEdgeGlobal&quot;                    type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;areaTriangleGlobal&quot;                type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;volumeCellGlobal&quot;                  type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;volumeEdgeGlobal&quot;                  type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;CFLNumberGlobal&quot;                   type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;nAccumulate&quot;                       type=&quot;real&quot;     dimensions=&quot;Time&quot;                        streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_ssh&quot;                           type=&quot;real&quot;     dimensions=&quot;nCells Time&quot;                 streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_sshVar&quot;                        type=&quot;real&quot;     dimensions=&quot;nCells Time&quot;                 streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_uReconstructZonal&quot;             type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_uReconstructMeridional&quot;        type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_uReconstructZonalVar&quot;          type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_uReconstructMeridionalVar&quot;     type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_u&quot;                             type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_uVar&quot;                          type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;     streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;acc_vertVelocityTop&quot;               type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nCells Time&quot;   streams=&quot;o&quot;/&gt;
+        &lt;/var_struct&gt;
+        &lt;var_struct name=&quot;mesh&quot; time_levs=&quot;0&quot;&gt;
+                &lt;var name=&quot;latCell&quot;                           type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;lonCell&quot;                           type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;xCell&quot;                             type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;yCell&quot;                             type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;zCell&quot;                             type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;indexToCellID&quot;                     type=&quot;integer&quot;  dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;latEdge&quot;                           type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;lonEdge&quot;                           type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;xEdge&quot;                             type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;yEdge&quot;                             type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;zEdge&quot;                             type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;indexToEdgeID&quot;                     type=&quot;integer&quot;  dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;latVertex&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;lonVertex&quot;                         type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;xVertex&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;yVertex&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;zVertex&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;indexToVertexID&quot;                   type=&quot;integer&quot;  dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;meshDensity&quot;                       type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;meshScalingDel2&quot;                   type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;ro&quot;/&gt;
+                &lt;var name=&quot;meshScalingDel4&quot;                   type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;ro&quot;/&gt;
+                &lt;var name=&quot;meshScaling&quot;                       type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;ro&quot;/&gt;
+                &lt;var name=&quot;cellsOnEdge&quot;                       type=&quot;integer&quot;  dimensions=&quot;TWO nEdges&quot;                  streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;nEdgesOnCell&quot;                      type=&quot;integer&quot;  dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;nEdgesOnEdge&quot;                      type=&quot;integer&quot;  dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;edgesOnCell&quot;                       type=&quot;integer&quot;  dimensions=&quot;maxEdges nCells&quot;             streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;edgesOnEdge&quot;                       type=&quot;integer&quot;  dimensions=&quot;maxEdges2 nEdges&quot;            streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;weightsOnEdge&quot;                     type=&quot;real&quot;     dimensions=&quot;maxEdges2 nEdges&quot;            streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;dvEdge&quot;                            type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;dcEdge&quot;                            type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;angleEdge&quot;                         type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;areaCell&quot;                          type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;areaTriangle&quot;                      type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;edgeNormalVectors&quot;                 type=&quot;real&quot;     dimensions=&quot;R3 nEdges&quot;                   streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;localVerticalUnitVectors&quot;          type=&quot;real&quot;     dimensions=&quot;R3 nCells&quot;                   streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;cellTangentPlane&quot;                  type=&quot;real&quot;     dimensions=&quot;R3 TWO nCells&quot;               streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;cellsOnCell&quot;                       type=&quot;integer&quot;  dimensions=&quot;maxEdges nCells&quot;             streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;verticesOnCell&quot;                    type=&quot;integer&quot;  dimensions=&quot;maxEdges nCells&quot;             streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;verticesOnEdge&quot;                    type=&quot;integer&quot;  dimensions=&quot;TWO nEdges&quot;                  streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;edgesOnVertex&quot;                     type=&quot;integer&quot;  dimensions=&quot;vertexDegree nVertices&quot;      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;cellsOnVertex&quot;                     type=&quot;integer&quot;  dimensions=&quot;vertexDegree nVertices&quot;      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;kiteAreasOnVertex&quot;                 type=&quot;real&quot;     dimensions=&quot;vertexDegree nVertices&quot;      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;fEdge&quot;                             type=&quot;real&quot;     dimensions=&quot;nEdges&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;fVertex&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertices&quot;                   streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;bottomDepth&quot;                       type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;deriv_two&quot;                         type=&quot;real&quot;     dimensions=&quot;maxEdges2 TWO nEdges&quot;/&gt;
+                &lt;var name=&quot;adv_coefs&quot;                         type=&quot;real&quot;     dimensions=&quot;nAdvectionCells nEdges&quot;/&gt;
+                &lt;var name=&quot;adv_coefs_2nd&quot;                     type=&quot;real&quot;     dimensions=&quot;nAdvectionCells nEdges&quot;/&gt;
+                &lt;var name=&quot;adv_coefs_3rd&quot;                     type=&quot;real&quot;     dimensions=&quot;nAdvectionCells nEdges&quot;/&gt;
+                &lt;var name=&quot;advCellsForEdge&quot;                   type=&quot;integer&quot;  dimensions=&quot;nAdvectionCells nEdges&quot;/&gt;
+                &lt;var name=&quot;nAdvCellsForEdge&quot;                  type=&quot;integer&quot;  dimensions=&quot;nEdges&quot;/&gt;
+                &lt;var name=&quot;highOrderAdvectionMask&quot;            type=&quot;integer&quot;  dimensions=&quot;nVertLevels nEdges&quot;/&gt;
+                &lt;var name=&quot;lowOrderAdvectionMask&quot;             type=&quot;integer&quot;  dimensions=&quot;nVertLevels nEdges&quot;/&gt;
+                &lt;var name=&quot;defc_a&quot;                            type=&quot;real&quot;     dimensions=&quot;maxEdges nCells&quot;/&gt;
+                &lt;var name=&quot;defc_b&quot;                            type=&quot;real&quot;     dimensions=&quot;maxEdges nCells&quot;/&gt;
+                &lt;var name=&quot;kdiff&quot;                             type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;coeffs_reconstruct&quot;                type=&quot;real&quot;     dimensions=&quot;R3 maxEdges nCells&quot;/&gt;
+                &lt;var name=&quot;maxLevelCell&quot;                      type=&quot;integer&quot;  dimensions=&quot;nCells&quot;                      streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;maxLevelEdgeTop&quot;                   type=&quot;integer&quot;  dimensions=&quot;nEdges&quot;/&gt;
+                &lt;var name=&quot;maxLevelEdgeBot&quot;                   type=&quot;integer&quot;  dimensions=&quot;nEdges&quot;/&gt;
+                &lt;var name=&quot;maxLevelVertexTop&quot;                 type=&quot;integer&quot;  dimensions=&quot;nVertices&quot;/&gt;
+                &lt;var name=&quot;maxLevelVertexBot&quot;                 type=&quot;integer&quot;  dimensions=&quot;nVertices&quot;/&gt;
+                &lt;var name=&quot;refBottomDepth&quot;                    type=&quot;real&quot;     dimensions=&quot;nVertLevels&quot;                 streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;refBottomDepthTopOfCell&quot;           type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1&quot;/&gt;
+                &lt;var name=&quot;hZLevel&quot;                           type=&quot;real&quot;     dimensions=&quot;nVertLevels&quot;                 streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;vertCoordMovementWeights&quot;          type=&quot;real&quot;     dimensions=&quot;nVertLevels&quot;                 streams=&quot;iro&quot;/&gt;
+                &lt;var name=&quot;boundaryEdge&quot;                      type=&quot;integer&quot;  dimensions=&quot;nVertLevels nEdges&quot;/&gt;
+                &lt;var name=&quot;boundaryVertex&quot;                    type=&quot;integer&quot;  dimensions=&quot;nVertLevels nVertices&quot;/&gt;
+                &lt;var name=&quot;boundaryCell&quot;                      type=&quot;integer&quot;  dimensions=&quot;nVertLevels nCells&quot;/&gt;
+                &lt;var name=&quot;edgeMask&quot;                          type=&quot;integer&quot;  dimensions=&quot;nVertLevels nEdges&quot;          streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;vertexMask&quot;                        type=&quot;integer&quot;  dimensions=&quot;nVertLevels nVertices&quot;       streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;cellMask&quot;                          type=&quot;integer&quot;  dimensions=&quot;nVertLevels nCells&quot;          streams=&quot;o&quot;/&gt;
+                &lt;var name=&quot;u_src&quot;                             type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges&quot;          streams=&quot;ir&quot;/&gt;
+                &lt;var name=&quot;temperatureRestore&quot;                type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;ir&quot;/&gt;
+                &lt;var name=&quot;salinityRestore&quot;                   type=&quot;real&quot;     dimensions=&quot;nCells&quot;                      streams=&quot;ir&quot;/&gt;
+                &lt;var name=&quot;windStressMonthly&quot;                 type=&quot;real&quot;     dimensions=&quot;nMonths nEdges&quot;              streams=&quot;ir&quot;/&gt;
+                &lt;var name=&quot;temperatureRestoreMonthly&quot;         type=&quot;real&quot;     dimensions=&quot;nMonths nCells&quot;              streams=&quot;ir&quot;/&gt;
+                &lt;var name=&quot;salinityRestoreMonthly&quot;            type=&quot;real&quot;     dimensions=&quot;nMonths nCells&quot;              streams=&quot;ir&quot;/&gt;
+                &lt;var name=&quot;edgeSignOnCell&quot;                    type=&quot;integer&quot;  dimensions=&quot;maxEdges nCells&quot;/&gt;
+                &lt;var name=&quot;edgeSignOnVertex&quot;                  type=&quot;integer&quot;  dimensions=&quot;maxEdges nVertices&quot;/&gt;
+                &lt;var name=&quot;kiteIndexOnCell&quot;                   type=&quot;integer&quot;  dimensions=&quot;maxEdges nCells&quot;/&gt;
+                &lt;var name=&quot;seaSurfacePressure&quot;                type=&quot;real&quot;     dimensions=&quot;nCells Time&quot;                 streams=&quot;ir&quot;/&gt;
+        &lt;/var_struct&gt;
+        &lt;var_struct name=&quot;tend&quot; time_levs=&quot;1&quot;&gt;
+                &lt;var_array name=&quot;tracers&quot; type=&quot;real&quot; dimensions=&quot;nVertLevels nCells Time&quot;&gt;
+                        &lt;var name=&quot;temperature&quot;   array_group=&quot;dynamics&quot;/&gt;
+                        &lt;var name=&quot;salinity&quot;      array_group=&quot;dynamics&quot;/&gt;
+                        &lt;var name=&quot;tracer1&quot;       array_group=&quot;testing&quot;/&gt;
+                &lt;/var_array&gt;
+                &lt;var name=&quot;u&quot;                            type=&quot;real&quot;     dimensions=&quot;nVertLevels nEdges Time&quot;/&gt;
+                &lt;var name=&quot;h&quot;                            type=&quot;real&quot;     dimensions=&quot;nVertLevels nCells Time&quot;/&gt;
+                &lt;var name=&quot;ssh&quot;                          type=&quot;real&quot;     dimensions=&quot;nCells Time&quot;/&gt;
+        &lt;/var_struct&gt;
+        &lt;var_struct name=&quot;diagnostics&quot; time_levs=&quot;1&quot;&gt;
+                &lt;var name=&quot;RiTopOfCell&quot;                       type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nCells Time&quot;/&gt;
+                &lt;var name=&quot;RiTopOfEdge&quot;                       type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nEdges Time&quot;/&gt;
+                &lt;var name=&quot;vertViscTopOfEdge&quot;                 type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nEdges Time&quot;/&gt;
+                &lt;var name=&quot;vertDiffTopOfCell&quot;                 type=&quot;real&quot;     dimensions=&quot;nVertLevelsP1 nCells Time&quot;/&gt;
+        &lt;/var_struct&gt;
+&lt;/registry&gt;

Modified: branches/xml_registry/src/registry/Makefile
===================================================================
--- branches/xml_registry/src/registry/Makefile        2013-03-14 19:21:28 UTC (rev 2611)
+++ branches/xml_registry/src/registry/Makefile        2013-03-14 20:15:45 UTC (rev 2612)
@@ -1,9 +1,12 @@
 .SUFFIXES: .c .o
 
-OBJS = parse.o dictionary.o gen_inc.o fortprintf.o
+OBJS = parse.o dictionary.o gen_inc.o fortprintf.o ezxml/ezxml.o
 
 all: parse
 
+ezxml/ezxml.o:
+        (cd ezxml; $(CC) -c ezxml.c)
+
 parse: $(OBJS)
         $(CC) -o $@ $(OBJS)
 

Added: branches/xml_registry/src/registry/Registry.xsd
===================================================================
--- branches/xml_registry/src/registry/Registry.xsd                                (rev 0)
+++ branches/xml_registry/src/registry/Registry.xsd        2013-03-14 20:15:45 UTC (rev 2612)
@@ -0,0 +1,119 @@
+&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
+&lt;xs:schema xmlns:xs=&quot;http://www.w3.org/2001/XMLSchema&quot;  elementFormDefault=&quot;qualified&quot;  attributeFormDefault=&quot;unqualified&quot; &gt;
+        &lt;xs:element name=&quot;registry&quot; &gt;
+                &lt;xs:complexType&gt;
+                        &lt;xs:sequence&gt;
+                                &lt;!-- The dims element contains all dimensions --&gt;
+                                &lt;xs:element name=&quot;dims&quot; &gt;
+                                        &lt;xs:complexType&gt;
+                                                &lt;xs:sequence&gt;
+                                                        &lt;!-- Each dimension is an independent child of the &lt;dims&gt;&lt;/dims&gt; element. --&gt;
+                                                        &lt;xs:element name=&quot;dim&quot;  maxOccurs=&quot;unbounded&quot; &gt;
+                                                                &lt;xs:complexType&gt;
+                                                                        &lt;!-- The name attribute should specify the name of the dimension. --&gt;
+                                                                        &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The definition attribute is used to define a dimension based on other pre-defined dimensions --&gt;
+                                                                        &lt;xs:attribute name=&quot;definition&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The units attribute defines the units of the dimension. --&gt;
+                                                                        &lt;xs:attribute name=&quot;units&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The description attribute describes the dimensions. --&gt;
+                                                                        &lt;xs:attribute name=&quot;description&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                &lt;/xs:complexType&gt;
+                                                        &lt;/xs:element&gt;
+                                                &lt;/xs:sequence&gt;
+                                        &lt;/xs:complexType&gt;
+                                &lt;/xs:element&gt;
+                                &lt;!-- The nml_record element contains all namelist options for a particular namelist record --&gt;
+                                &lt;xs:element name=&quot;nml_record&quot;  maxOccurs=&quot;unbounded&quot; &gt;
+                                        &lt;xs:complexType&gt;
+                                                &lt;xs:sequence&gt;
+                                                        &lt;!-- The nml_option element defines a particular namelist option that lives within the defined nml_record --&gt;
+                                                        &lt;xs:element name=&quot;nml_option&quot;  maxOccurs=&quot;unbounded&quot; &gt;
+                                                                &lt;xs:complexType&gt;
+                                                                        &lt;!-- The name attribute defines the name of the namelist option. This is how it would look in a namelist file. --&gt;
+                                                                        &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The type attribute defines the type of the particular namelist option. Options are real, integer, character, and logical. --&gt;
+                                                                        &lt;xs:attribute name=&quot;type&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The default_value attribute defines the default value of the namelist option. This is used if the option is omitted from a namelist file. --&gt;
+                                                                        &lt;xs:attribute name=&quot;default_value&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The units attribute defines the units for the particular namelist option. --&gt;
+                                                                        &lt;xs:attribute name=&quot;units&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The description attribute describes the namelist option. --&gt;
+                                                                        &lt;xs:attribute name=&quot;description&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The possible_values attribute defines what values are allowable for the namelist option. --&gt;
+                                                                        &lt;xs:attribute name=&quot;possible_values&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                &lt;/xs:complexType&gt;
+                                                        &lt;/xs:element&gt;
+                                                &lt;/xs:sequence&gt;
+                                                &lt;!-- The name attribute defines the name of the namelist record. This would be seen as &amp;name in the actual namelist. --&gt;
+                                                &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                        &lt;/xs:complexType&gt;
+                                &lt;/xs:element&gt;
+                                &lt;!-- The var_struct element defines a grouping of variables. This is similar to mesh, or state and lives at the domain % blocklist level. --&gt;
+                                &lt;xs:element name=&quot;var_struct&quot;  maxOccurs=&quot;unbounded&quot; &gt;
+                                        &lt;xs:complexType&gt;
+                                                &lt;xs:sequence&gt;
+                                                        &lt;!-- The var_array element defines an array of variables. 
+                                                                 Within the code all constituent variables are merged into a one higher dimension array, for ease of use.
+                                                                 When written to the output file, they will be named their individual names. --&gt;
+                                                        &lt;xs:element name=&quot;var_array&quot; maxOccurs=&quot;unbounded&quot; minOccurs=&quot;0&quot; &gt;
+                                                                &lt;xs:complexType&gt;
+                                                                        &lt;xs:sequence&gt;
+                                                                                &lt;!-- This specific var element defines a variable that is a constituent to a particular var_array group. --&gt;
+                                                                                &lt;xs:element name=&quot;var&quot;  maxOccurs=&quot;unbounded&quot; minOccurs=&quot;0&quot; &gt;
+                                                                                        &lt;xs:complexType&gt;
+                                                                                                &lt;!-- The name attribute is the name of the variable. This how it will be displayed in the output file. --&gt;
+                                                                                                &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                                                &lt;!-- The array_group attribute is used to group variables within the var_array for ease of use. --&gt;
+                                                                                                &lt;xs:attribute name=&quot;array_group&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                                                &lt;!-- The streams attribute defines the streams this variable is included in. Allowable values are omitted, i, r, o and any combination of i, r, and o. --&gt;
+                                                                                                &lt;xs:attribute name=&quot;streams&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                                                &lt;!-- The name_in_code attribute defines the name of the variable in the code, if it should be different then in the input/output/restart streams. --&gt;
+                                                                                                &lt;xs:attribute name=&quot;name_in_code&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                                                &lt;!-- The units attribute defines the units of the particular variable --&gt;
+                                                                                                &lt;xs:attribute name=&quot;units&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                                                &lt;!-- The description attribute describes the particular variable --&gt;
+                                                                                                &lt;xs:attribute name=&quot;description&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                                        &lt;/xs:complexType&gt;
+                                                                                &lt;/xs:element&gt;
+                                                                        &lt;/xs:sequence&gt;
+                                                                        &lt;!-- The name attribute is the name of the var_array that will be seen in the code. --&gt;
+                                                                        &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The type attribute defines the type of all constituents for the var_array. Valid options are real, integer, logical, and character --&gt;
+                                                                        &lt;xs:attribute name=&quot;type&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The dimensions attribute defines the dimensions of each individual constituent. This does not include the collapsed dimension. --&gt;
+                                                                        &lt;xs:attribute name=&quot;dimensions&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The persistence attribute determines if the var_array is persistence or scratch. Valid options are persistent, and scratch. --&gt;
+                                                                        &lt;xs:attribute name=&quot;persistence&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                &lt;/xs:complexType&gt;
+                                                        &lt;/xs:element&gt;
+                                                        &lt;!-- This var element defines a variable that does not live within a var_array group. --&gt;
+                                                        &lt;xs:element name=&quot;var&quot;  maxOccurs=&quot;unbounded&quot; minOccurs=&quot;0&quot; &gt;
+                                                                &lt;xs:complexType&gt;
+                                                                        &lt;!-- The name attribute defines the name in the NetCDF files of this variable. --&gt;
+                                                                        &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The type attribute defines the type within MPAS of the variable. --&gt;
+                                                                        &lt;xs:attribute name=&quot;type&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The dimensions attribute defines the dimensions of the variable. --&gt;
+                                                                        &lt;xs:attribute name=&quot;dimensions&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                                        &lt;!-- The streams attribute defines the streams this variable is included in. --&gt;
+                                                                        &lt;xs:attribute name=&quot;streams&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The name_in_code attribute defines the name of the variable within MPAS (if different from name). --&gt;
+                                                                        &lt;xs:attribute name=&quot;name_in_code&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The units attribute defines the units of the variable. --&gt;
+                                                                        &lt;xs:attribute name=&quot;units&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                        &lt;!-- The description attribute provides a brief description of the variable. --&gt;
+                                                                        &lt;xs:attribute name=&quot;description&quot;  type=&quot;xs:string&quot; use=&quot;optional&quot;/&gt;
+                                                                &lt;/xs:complexType&gt;
+                                                        &lt;/xs:element&gt;
+                                                &lt;/xs:sequence&gt;
+                                                &lt;!-- The name attribute defines the name of the var_struct. This would be similar to mesh, or state. --&gt;
+                                                &lt;xs:attribute name=&quot;name&quot;  type=&quot;xs:string&quot; use=&quot;required&quot;/&gt;
+                                                &lt;!-- The time_levs attribute defines the number of time levels this var_struct contains. --&gt;
+                                                &lt;xs:attribute name=&quot;time_levs&quot;  type=&quot;xs:int&quot; use=&quot;required&quot;/&gt;
+                                        &lt;/xs:complexType&gt;
+                                &lt;/xs:element&gt;
+                        &lt;/xs:sequence&gt;
+                &lt;/xs:complexType&gt;
+        &lt;/xs:element&gt;
+&lt;/xs:schema&gt;

Added: branches/xml_registry/src/registry/ezxml/ezxml.c
===================================================================
--- branches/xml_registry/src/registry/ezxml/ezxml.c                                (rev 0)
+++ branches/xml_registry/src/registry/ezxml/ezxml.c        2013-03-14 20:15:45 UTC (rev 2612)
@@ -0,0 +1,1015 @@
+/* ezxml.c
+ *
+ * Copyright 2004-2006 Aaron Voisine &lt;aaron@voisine.org&gt;
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * &quot;Software&quot;), 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 &quot;AS IS&quot;, 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.
+ */
+
+#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;stdarg.h&gt;
+#include &lt;string.h&gt;
+#include &lt;ctype.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;sys/types.h&gt;
+#ifndef EZXML_NOMMAP
+#include &lt;sys/mman.h&gt;
+#endif // EZXML_NOMMAP
+#include &lt;sys/stat.h&gt;
+#include &quot;ezxml.h&quot;
+
+#define EZXML_WS   &quot;\t\r</font>
<font color="blue"> &quot;  // whitespace
+#define EZXML_ERRL 128        // maximum error string length
+
+typedef struct ezxml_root *ezxml_root_t;
+struct ezxml_root {       // additional data for the root tag
+    struct ezxml xml;     // is a super-struct built on top of ezxml struct
+    ezxml_t cur;          // current xml tree insertion point
+    char *m;              // original xml string
+    size_t len;           // length of allocated memory for mmap, -1 for malloc
+    char *u;              // UTF-8 conversion of string if original was UTF-16
+    char *s;              // start of work area
+    char *e;              // end of work area
+    char **ent;           // general entities (ampersand sequences)
+    char ***attr;         // default attributes
+    char ***pi;           // processing instructions
+    short standalone;     // non-zero if &lt;?xml standalone=&quot;yes&quot;?&gt;
+    char err[EZXML_ERRL]; // error string
+};
+
+char *EZXML_NIL[] = { NULL }; // empty, null terminated array of strings
+
+// returns the first child tag with the given name or NULL if not found
+ezxml_t ezxml_child(ezxml_t xml, const char *name)
+{
+    xml = (xml) ? xml-&gt;child : NULL;
+    while (xml &amp;&amp; strcmp(name, xml-&gt;name)) xml = xml-&gt;sibling;
+    return xml;
+}
+
+// returns the Nth tag with the same name in the same subsection or NULL if not
+// found
+ezxml_t ezxml_idx(ezxml_t xml, int idx)
+{
+    for (; xml &amp;&amp; idx; idx--) xml = xml-&gt;next;
+    return xml;
+}
+
+// returns the value of the requested tag attribute or NULL if not found
+const char *ezxml_attr(ezxml_t xml, const char *attr)
+{
+    int i = 0, j = 1;
+    ezxml_root_t root = (ezxml_root_t)xml;
+
+    if (! xml || ! xml-&gt;attr) return NULL;
+    while (xml-&gt;attr[i] &amp;&amp; strcmp(attr, xml-&gt;attr[i])) i += 2;
+    if (xml-&gt;attr[i]) return xml-&gt;attr[i + 1]; // found attribute
+
+    while (root-&gt;xml.parent) root = (ezxml_root_t)root-&gt;xml.parent; // root tag
+    for (i = 0; root-&gt;attr[i] &amp;&amp; strcmp(xml-&gt;name, root-&gt;attr[i][0]); i++);
+    if (! root-&gt;attr[i]) return NULL; // no matching default attributes
+    while (root-&gt;attr[i][j] &amp;&amp; strcmp(attr, root-&gt;attr[i][j])) j += 3;
+    return (root-&gt;attr[i][j]) ? root-&gt;attr[i][j + 1] : NULL; // found default
+}
+
+// same as ezxml_get but takes an already initialized va_list
+ezxml_t ezxml_vget(ezxml_t xml, va_list ap)
+{
+    char *name = va_arg(ap, char *);
+    int idx = -1;
+
+    if (name &amp;&amp; *name) {
+        idx = va_arg(ap, int);    
+        xml = ezxml_child(xml, name);
+    }
+    return (idx &lt; 0) ? xml : ezxml_vget(ezxml_idx(xml, idx), ap);
+}
+
+// Traverses the xml tree to retrieve a specific subtag. Takes a variable
+// length list of tag names and indexes. The argument list must be terminated
+// by either an index of -1 or an empty string tag name. Example: 
+// title = ezxml_get(library, &quot;shelf&quot;, 0, &quot;book&quot;, 2, &quot;title&quot;, -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+ezxml_t ezxml_get(ezxml_t xml, ...)
+{
+    va_list ap;
+    ezxml_t r;
+
+    va_start(ap, xml);
+    r = ezxml_vget(xml, ap);
+    va_end(ap);
+    return r;
+}
+
+// returns a null terminated array of processing instructions for the given
+// target
+const char **ezxml_pi(ezxml_t xml, const char *target)
+{
+    ezxml_root_t root = (ezxml_root_t)xml;
+    int i = 0;
+
+    if (! root) return (const char **)EZXML_NIL;
+    while (root-&gt;xml.parent) root = (ezxml_root_t)root-&gt;xml.parent; // root tag
+    while (root-&gt;pi[i] &amp;&amp; strcmp(target, root-&gt;pi[i][0])) i++; // find target
+    return (const char **)((root-&gt;pi[i]) ? root-&gt;pi[i] + 1 : EZXML_NIL);
+}
+
+// set an error string and return root
+ezxml_t ezxml_err(ezxml_root_t root, char *s, const char *err, ...)
+{
+    va_list ap;
+    int line = 1;
+    char *t, fmt[EZXML_ERRL];
+    
+    for (t = root-&gt;s; t &lt; s; t++) if (*t == '</font>
<font color="blue">') line++;
+    snprintf(fmt, EZXML_ERRL, &quot;[error near line %d]: %s&quot;, line, err);
+
+    va_start(ap, err);
+    vsnprintf(root-&gt;err, EZXML_ERRL, fmt, ap);
+    va_end(ap);
+
+    return &amp;root-&gt;xml;
+}
+
+// Recursively decodes entity and character references and normalizes new lines
+// ent is a null terminated array of alternating entity names and values. set t
+// to '&amp;' for general entity decoding, '%' for parameter entity decoding, 'c'
+// for cdata sections, ' ' for attribute normalization, or '*' for non-cdata
+// attribute normalization. Returns s, or if the decoded string is longer than
+// s, returns a malloced string that must be freed.
+char *ezxml_decode(char *s, char **ent, char t)
+{
+    char *e, *r = s, *m = s;
+    long b, c, d, l;
+
+    for (; *s; s++) { // normalize line endings
+        while (*s == '\r') {
+            *(s++) = '</font>
<font color="blue">';
+            if (*s == '</font>
<font color="blue">') memmove(s, (s + 1), strlen(s));
+        }
+    }
+    
+    for (s = r; ; ) {
+        while (*s &amp;&amp; *s != '&amp;' &amp;&amp; (*s != '%' || t != '%') &amp;&amp; !isspace(*s)) s++;
+
+        if (! *s) break;
+        else if (t != 'c' &amp;&amp; ! strncmp(s, &quot;&amp;#&quot;, 2)) { // character reference
+            if (s[2] == 'x') c = strtol(s + 3, &amp;e, 16); // base 16
+            else c = strtol(s + 2, &amp;e, 10); // base 10
+            if (! c || *e != ';') { s++; continue; } // not a character ref
+
+            if (c &lt; 0x80) *(s++) = c; // US-ASCII subset
+            else { // multi-byte UTF-8 sequence
+                for (b = 0, d = c; d; d /= 2) b++; // number of bits in c
+                b = (b - 2) / 5; // number of bytes in payload
+                *(s++) = (0xFF &lt;&lt; (7 - b)) | (c &gt;&gt; (6 * b)); // head
+                while (b) *(s++) = 0x80 | ((c &gt;&gt; (6 * --b)) &amp; 0x3F); // payload
+            }
+
+            memmove(s, strchr(s, ';') + 1, strlen(strchr(s, ';')));
+        }
+        else if ((*s == '&amp;' &amp;&amp; (t == '&amp;' || t == ' ' || t == '*')) ||
+                 (*s == '%' &amp;&amp; t == '%')) { // entity reference
+            for (b = 0; ent[b] &amp;&amp; strncmp(s + 1, ent[b], strlen(ent[b]));
+                 b += 2); // find entity in entity list
+
+            if (ent[b++]) { // found a match
+                if ((c = strlen(ent[b])) - 1 &gt; (e = strchr(s, ';')) - s) {
+                    l = (d = (s - r)) + c + strlen(e); // new length
+                    r = (r == m) ? strcpy(malloc(l), r) : realloc(r, l);
+                    e = strchr((s = r + d), ';'); // fix up pointers
+                }
+
+                memmove(s + c, e + 1, strlen(e)); // shift rest of string
+                strncpy(s, ent[b], c); // copy in replacement text
+            }
+            else s++; // not a known entity
+        }
+        else if ((t == ' ' || t == '*') &amp;&amp; isspace(*s)) *(s++) = ' ';
+        else s++; // no decoding needed
+    }
+
+    if (t == '*') { // normalize spaces for non-cdata attributes
+        for (s = r; *s; s++) {
+            if ((l = strspn(s, &quot; &quot;))) memmove(s, s + l, strlen(s + l) + 1);
+            while (*s &amp;&amp; *s != ' ') s++;
+        }
+        if (--s &gt;= r &amp;&amp; *s == ' ') *s = '\0'; // trim any trailing space
+    }
+    return r;
+}
+
+// called when parser finds start of new tag
+void ezxml_open_tag(ezxml_root_t root, char *name, char **attr)
+{
+    ezxml_t xml = root-&gt;cur;
+    
+    if (xml-&gt;name) xml = ezxml_add_child(xml, name, strlen(xml-&gt;txt));
+    else xml-&gt;name = name; // first open tag
+
+    xml-&gt;attr = attr;
+    root-&gt;cur = xml; // update tag insertion point
+}
+
+// called when parser finds character content between open and closing tag
+void ezxml_char_content(ezxml_root_t root, char *s, size_t len, char t)
+{
+    ezxml_t xml = root-&gt;cur;
+    char *m = s;
+    size_t l;
+
+    if (! xml || ! xml-&gt;name || ! len) return; // sanity check
+
+    s[len] = '\0'; // null terminate text (calling functions anticipate this)
+    len = strlen(s = ezxml_decode(s, root-&gt;ent, t)) + 1;
+
+    if (! *(xml-&gt;txt)) xml-&gt;txt = s; // initial character content
+    else { // allocate our own memory and make a copy
+        xml-&gt;txt = (xml-&gt;flags &amp; EZXML_TXTM) // allocate some space
+                   ? realloc(xml-&gt;txt, (l = strlen(xml-&gt;txt)) + len)
+                   : strcpy(malloc((l = strlen(xml-&gt;txt)) + len), xml-&gt;txt);
+        strcpy(xml-&gt;txt + l, s); // add new char content
+        if (s != m) free(s); // free s if it was malloced by ezxml_decode()
+    }
+
+    if (xml-&gt;txt != m) ezxml_set_flag(xml, EZXML_TXTM);
+}
+
+// called when parser finds closing tag
+ezxml_t ezxml_close_tag(ezxml_root_t root, char *name, char *s)
+{
+    if (! root-&gt;cur || ! root-&gt;cur-&gt;name || strcmp(name, root-&gt;cur-&gt;name))
+        return ezxml_err(root, s, &quot;unexpected closing tag &lt;/%s&gt;&quot;, name);
+
+    root-&gt;cur = root-&gt;cur-&gt;parent;
+    return NULL;
+}
+
+// checks for circular entity references, returns non-zero if no circular
+// references are found, zero otherwise
+int ezxml_ent_ok(char *name, char *s, char **ent)
+{
+    int i;
+
+    for (; ; s++) {
+        while (*s &amp;&amp; *s != '&amp;') s++; // find next entity reference
+        if (! *s) return 1;
+        if (! strncmp(s + 1, name, strlen(name))) return 0; // circular ref.
+        for (i = 0; ent[i] &amp;&amp; strncmp(ent[i], s + 1, strlen(ent[i])); i += 2);
+        if (ent[i] &amp;&amp; ! ezxml_ent_ok(name, ent[i + 1], ent)) return 0;
+    }
+}
+
+// called when the parser finds a processing instruction
+void ezxml_proc_inst(ezxml_root_t root, char *s, size_t len)
+{
+    int i = 0, j = 1;
+    char *target = s;
+
+    s[len] = '\0'; // null terminate instruction
+    if (*(s += strcspn(s, EZXML_WS))) {
+        *s = '\0'; // null terminate target
+        s += strspn(s + 1, EZXML_WS) + 1; // skip whitespace after target
+    }
+
+    if (! strcmp(target, &quot;xml&quot;)) { // &lt;?xml ... ?&gt;
+        if ((s = strstr(s, &quot;standalone&quot;)) &amp;&amp; ! strncmp(s + strspn(s + 10,
+            EZXML_WS &quot;='\&quot;&quot;) + 10, &quot;yes&quot;, 3)) root-&gt;standalone = 1;
+        return;
+    }
+
+    if (! root-&gt;pi[0]) *(root-&gt;pi = malloc(sizeof(char **))) = NULL; //first pi
+
+    while (root-&gt;pi[i] &amp;&amp; strcmp(target, root-&gt;pi[i][0])) i++; // find target
+    if (! root-&gt;pi[i]) { // new target
+        root-&gt;pi = realloc(root-&gt;pi, sizeof(char **) * (i + 2));
+        root-&gt;pi[i] = malloc(sizeof(char *) * 3);
+        root-&gt;pi[i][0] = target;
+        root-&gt;pi[i][1] = (char *)(root-&gt;pi[i + 1] = NULL); // terminate pi list
+        root-&gt;pi[i][2] = strdup(&quot;&quot;); // empty document position list
+    }
+
+    while (root-&gt;pi[i][j]) j++; // find end of instruction list for this target
+    root-&gt;pi[i] = realloc(root-&gt;pi[i], sizeof(char *) * (j + 3));
+    root-&gt;pi[i][j + 2] = realloc(root-&gt;pi[i][j + 1], j + 1);
+    strcpy(root-&gt;pi[i][j + 2] + j - 1, (root-&gt;xml.name) ? &quot;&gt;&quot; : &quot;&lt;&quot;);
+    root-&gt;pi[i][j + 1] = NULL; // null terminate pi list for this target
+    root-&gt;pi[i][j] = s; // set instruction
+}
+
+// called when the parser finds an internal doctype subset
+short ezxml_internal_dtd(ezxml_root_t root, char *s, size_t len)
+{
+    char q, *c, *t, *n = NULL, *v, **ent, **pe;
+    int i, j;
+    
+    pe = memcpy(malloc(sizeof(EZXML_NIL)), EZXML_NIL, sizeof(EZXML_NIL));
+
+    for (s[len] = '\0'; s; ) {
+        while (*s &amp;&amp; *s != '&lt;' &amp;&amp; *s != '%') s++; // find next declaration
+
+        if (! *s) break;
+        else if (! strncmp(s, &quot;&lt;!ENTITY&quot;, 8)) { // parse entity definitions
+            c = s += strspn(s + 8, EZXML_WS) + 8; // skip white space separator
+            n = s + strspn(s, EZXML_WS &quot;%&quot;); // find name
+            *(s = n + strcspn(n, EZXML_WS)) = ';'; // append ; to name
+
+            v = s + strspn(s + 1, EZXML_WS) + 1; // find value
+            if ((q = *(v++)) != '&quot;' &amp;&amp; q != '\'') { // skip externals
+                s = strchr(s, '&gt;');
+                continue;
+            }
+
+            for (i = 0, ent = (*c == '%') ? pe : root-&gt;ent; ent[i]; i++);
+            ent = realloc(ent, (i + 3) * sizeof(char *)); // space for next ent
+            if (*c == '%') pe = ent;
+            else root-&gt;ent = ent;
+
+            *(++s) = '\0'; // null terminate name
+            if ((s = strchr(v, q))) *(s++) = '\0'; // null terminate value
+            ent[i + 1] = ezxml_decode(v, pe, '%'); // set value
+            ent[i + 2] = NULL; // null terminate entity list
+            if (! ezxml_ent_ok(n, ent[i + 1], ent)) { // circular reference
+                if (ent[i + 1] != v) free(ent[i + 1]);
+                ezxml_err(root, v, &quot;circular entity declaration &amp;%s&quot;, n);
+                break;
+            }
+            else ent[i] = n; // set entity name
+        }
+        else if (! strncmp(s, &quot;&lt;!ATTLIST&quot;, 9)) { // parse default attributes
+            t = s + strspn(s + 9, EZXML_WS) + 9; // skip whitespace separator
+            if (! *t) { ezxml_err(root, t, &quot;unclosed &lt;!ATTLIST&quot;); break; }
+            if (*(s = t + strcspn(t, EZXML_WS &quot;&gt;&quot;)) == '&gt;') continue;
+            else *s = '\0'; // null terminate tag name
+            for (i = 0; root-&gt;attr[i] &amp;&amp; strcmp(n, root-&gt;attr[i][0]); i++);
+
+            while (*(n = ++s + strspn(s, EZXML_WS)) &amp;&amp; *n != '&gt;') {
+                if (*(s = n + strcspn(n, EZXML_WS))) *s = '\0'; // attr name
+                else { ezxml_err(root, t, &quot;malformed &lt;!ATTLIST&quot;); break; }
+
+                s += strspn(s + 1, EZXML_WS) + 1; // find next token
+                c = (strncmp(s, &quot;CDATA&quot;, 5)) ? &quot;*&quot; : &quot; &quot;; // is it cdata?
+                if (! strncmp(s, &quot;NOTATION&quot;, 8))
+                    s += strspn(s + 8, EZXML_WS) + 8;
+                s = (*s == '(') ? strchr(s, ')') : s + strcspn(s, EZXML_WS);
+                if (! s) { ezxml_err(root, t, &quot;malformed &lt;!ATTLIST&quot;); break; }
+
+                s += strspn(s, EZXML_WS &quot;)&quot;); // skip white space separator
+                if (! strncmp(s, &quot;#FIXED&quot;, 6))
+                    s += strspn(s + 6, EZXML_WS) + 6;
+                if (*s == '#') { // no default value
+                    s += strcspn(s, EZXML_WS &quot;&gt;&quot;) - 1;
+                    if (*c == ' ') continue; // cdata is default, nothing to do
+                    v = NULL;
+                }
+                else if ((*s == '&quot;' || *s == '\'')  &amp;&amp;  // default value
+                         (s = strchr(v = s + 1, *s))) *s = '\0';
+                else { ezxml_err(root, t, &quot;malformed &lt;!ATTLIST&quot;); break; }
+
+                if (! root-&gt;attr[i]) { // new tag name
+                    root-&gt;attr = (! i) ? malloc(2 * sizeof(char **))
+                                       : realloc(root-&gt;attr,
+                                                 (i + 2) * sizeof(char **));
+                    root-&gt;attr[i] = malloc(2 * sizeof(char *));
+                    root-&gt;attr[i][0] = t; // set tag name
+                    root-&gt;attr[i][1] = (char *)(root-&gt;attr[i + 1] = NULL);
+                }
+
+                for (j = 1; root-&gt;attr[i][j]; j += 3); // find end of list
+                root-&gt;attr[i] = realloc(root-&gt;attr[i],
+                                        (j + 4) * sizeof(char *));
+
+                root-&gt;attr[i][j + 3] = NULL; // null terminate list
+                root-&gt;attr[i][j + 2] = c; // is it cdata?
+                root-&gt;attr[i][j + 1] = (v) ? ezxml_decode(v, root-&gt;ent, *c)
+                                           : NULL;
+                root-&gt;attr[i][j] = n; // attribute name 
+            }
+        }
+        else if (! strncmp(s, &quot;&lt;!--&quot;, 4)) s = strstr(s + 4, &quot;--&gt;&quot;); // comments
+        else if (! strncmp(s, &quot;&lt;?&quot;, 2)) { // processing instructions
+            if ((s = strstr(c = s + 2, &quot;?&gt;&quot;)))
+                ezxml_proc_inst(root, c, s++ - c);
+        }
+        else if (*s == '&lt;') s = strchr(s, '&gt;'); // skip other declarations
+        else if (*(s++) == '%' &amp;&amp; ! root-&gt;standalone) break;
+    }
+
+    free(pe);
+    return ! *root-&gt;err;
+}
+
+// Converts a UTF-16 string to UTF-8. Returns a new string that must be freed
+// or NULL if no conversion was needed.
+char *ezxml_str2utf8(char **s, size_t *len)
+{
+    char *u;
+    size_t l = 0, sl, max = *len;
+    long c, d;
+    int b, be = (**s == '\xFE') ? 1 : (**s == '\xFF') ? 0 : -1;
+
+    if (be == -1) return NULL; // not UTF-16
+
+    u = malloc(max);
+    for (sl = 2; sl &lt; *len - 1; sl += 2) {
+        c = (be) ? (((*s)[sl] &amp; 0xFF) &lt;&lt; 8) | ((*s)[sl + 1] &amp; 0xFF)  //UTF-16BE
+                 : (((*s)[sl + 1] &amp; 0xFF) &lt;&lt; 8) | ((*s)[sl] &amp; 0xFF); //UTF-16LE
+        if (c &gt;= 0xD800 &amp;&amp; c &lt;= 0xDFFF &amp;&amp; (sl += 2) &lt; *len - 1) { // high-half
+            d = (be) ? (((*s)[sl] &amp; 0xFF) &lt;&lt; 8) | ((*s)[sl + 1] &amp; 0xFF)
+                     : (((*s)[sl + 1] &amp; 0xFF) &lt;&lt; 8) | ((*s)[sl] &amp; 0xFF);
+            c = (((c &amp; 0x3FF) &lt;&lt; 10) | (d &amp; 0x3FF)) + 0x10000;
+        }
+
+        while (l + 6 &gt; max) u = realloc(u, max += EZXML_BUFSIZE);
+        if (c &lt; 0x80) u[l++] = c; // US-ASCII subset
+        else { // multi-byte UTF-8 sequence
+            for (b = 0, d = c; d; d /= 2) b++; // bits in c
+            b = (b - 2) / 5; // bytes in payload
+            u[l++] = (0xFF &lt;&lt; (7 - b)) | (c &gt;&gt; (6 * b)); // head
+            while (b) u[l++] = 0x80 | ((c &gt;&gt; (6 * --b)) &amp; 0x3F); // payload
+        }
+    }
+    return *s = realloc(u, *len = l);
+}
+
+// frees a tag attribute list
+void ezxml_free_attr(char **attr) {
+    int i = 0;
+    char *m;
+    
+    if (! attr || attr == EZXML_NIL) return; // nothing to free
+    while (attr[i]) i += 2; // find end of attribute list
+    m = attr[i + 1]; // list of which names and values are malloced
+    for (i = 0; m[i]; i++) {
+        if (m[i] &amp; EZXML_NAMEM) free(attr[i * 2]);
+        if (m[i] &amp; EZXML_TXTM) free(attr[(i * 2) + 1]);
+    }
+    free(m);
+    free(attr);
+}
+
+// parse the given xml string and return an ezxml structure
+ezxml_t ezxml_parse_str(char *s, size_t len)
+{
+    ezxml_root_t root = (ezxml_root_t)ezxml_new(NULL);
+    char q, e, *d, **attr, **a = NULL; // initialize a to avoid compile warning
+    int l, i, j;
+
+    root-&gt;m = s;
+    if (! len) return ezxml_err(root, NULL, &quot;root tag missing&quot;);
+    root-&gt;u = ezxml_str2utf8(&amp;s, &amp;len); // convert utf-16 to utf-8
+    root-&gt;e = (root-&gt;s = s) + len; // record start and end of work area
+    
+    e = s[len - 1]; // save end char
+    s[len - 1] = '\0'; // turn end char into null terminator
+
+    while (*s &amp;&amp; *s != '&lt;') s++; // find first tag
+    if (! *s) return ezxml_err(root, s, &quot;root tag missing&quot;);
+
+    for (; ; ) {
+        attr = (char **)EZXML_NIL;
+        d = ++s;
+        
+        if (isalpha(*s) || *s == '_' || *s == ':' || *s &lt; '\0') { // new tag
+            if (! root-&gt;cur)
+                return ezxml_err(root, d, &quot;markup outside of root element&quot;);
+
+            s += strcspn(s, EZXML_WS &quot;/&gt;&quot;);
+            while (isspace(*s)) *(s++) = '\0'; // null terminate tag name
+  
+            if (*s &amp;&amp; *s != '/' &amp;&amp; *s != '&gt;') // find tag in default attr list
+                for (i = 0; (a = root-&gt;attr[i]) &amp;&amp; strcmp(a[0], d); i++);
+
+            for (l = 0; *s &amp;&amp; *s != '/' &amp;&amp; *s != '&gt;'; l += 2) { // new attrib
+                attr = (l) ? realloc(attr, (l + 4) * sizeof(char *))
+                           : malloc(4 * sizeof(char *)); // allocate space
+                attr[l + 3] = (l) ? realloc(attr[l + 1], (l / 2) + 2)
+                                  : malloc(2); // mem for list of maloced vals
+                strcpy(attr[l + 3] + (l / 2), &quot; &quot;); // value is not malloced
+                attr[l + 2] = NULL; // null terminate list
+                attr[l + 1] = &quot;&quot;; // temporary attribute value
+                attr[l] = s; // set attribute name
+
+                s += strcspn(s, EZXML_WS &quot;=/&gt;&quot;);
+                if (*s == '=' || isspace(*s)) { 
+                    *(s++) = '\0'; // null terminate tag attribute name
+                    q = *(s += strspn(s, EZXML_WS &quot;=&quot;));
+                    if (q == '&quot;' || q == '\'') { // attribute value
+                        attr[l + 1] = ++s;
+                        while (*s &amp;&amp; *s != q) s++;
+                        if (*s) *(s++) = '\0'; // null terminate attribute val
+                        else {
+                            ezxml_free_attr(attr);
+                            return ezxml_err(root, d, &quot;missing %c&quot;, q);
+                        }
+
+                        for (j = 1; a &amp;&amp; a[j] &amp;&amp; strcmp(a[j], attr[l]); j +=3);
+                        attr[l + 1] = ezxml_decode(attr[l + 1], root-&gt;ent, (a
+                                                   &amp;&amp; a[j]) ? *a[j + 2] : ' ');
+                        if (attr[l + 1] &lt; d || attr[l + 1] &gt; s)
+                            attr[l + 3][l / 2] = EZXML_TXTM; // value malloced
+                    }
+                }
+                while (isspace(*s)) s++;
+            }
+
+            if (*s == '/') { // self closing tag
+                *(s++) = '\0';
+                if ((*s &amp;&amp; *s != '&gt;') || (! *s &amp;&amp; e != '&gt;')) {
+                    if (l) ezxml_free_attr(attr);
+                    return ezxml_err(root, d, &quot;missing &gt;&quot;);
+                }
+                ezxml_open_tag(root, d, attr);
+                ezxml_close_tag(root, d, s);
+            }
+            else if ((q = *s) == '&gt;' || (! *s &amp;&amp; e == '&gt;')) { // open tag
+                *s = '\0'; // temporarily null terminate tag name
+                ezxml_open_tag(root, d, attr);
+                *s = q;
+            }
+            else {
+                if (l) ezxml_free_attr(attr);
+                return ezxml_err(root, d, &quot;missing &gt;&quot;); 
+            }
+        }
+        else if (*s == '/') { // close tag
+            s += strcspn(d = s + 1, EZXML_WS &quot;&gt;&quot;) + 1;
+            if (! (q = *s) &amp;&amp; e != '&gt;') return ezxml_err(root, d, &quot;missing &gt;&quot;);
+            *s = '\0'; // temporarily null terminate tag name
+            if (ezxml_close_tag(root, d, s)) return &amp;root-&gt;xml;
+            if (isspace(*s = q)) s += strspn(s, EZXML_WS);
+        }
+        else if (! strncmp(s, &quot;!--&quot;, 3)) { // xml comment
+            if (! (s = strstr(s + 3, &quot;--&quot;)) || (*(s += 2) != '&gt;' &amp;&amp; *s) ||
+                (! *s &amp;&amp; e != '&gt;')) return ezxml_err(root, d, &quot;unclosed &lt;!--&quot;);
+        }
+        else if (! strncmp(s, &quot;![CDATA[&quot;, 8)) { // cdata
+            if ((s = strstr(s, &quot;]]&gt;&quot;)))
+                ezxml_char_content(root, d + 8, (s += 2) - d - 10, 'c');
+            else return ezxml_err(root, d, &quot;unclosed &lt;![CDATA[&quot;);
+        }
+        else if (! strncmp(s, &quot;!DOCTYPE&quot;, 8)) { // dtd
+            for (l = 0; *s &amp;&amp; ((! l &amp;&amp; *s != '&gt;') || (l &amp;&amp; (*s != ']' || 
+                 *(s + strspn(s + 1, EZXML_WS) + 1) != '&gt;')));
+                 l = (*s == '[') ? 1 : l) s += strcspn(s + 1, &quot;[]&gt;&quot;) + 1;
+            if (! *s &amp;&amp; e != '&gt;')
+                return ezxml_err(root, d, &quot;unclosed &lt;!DOCTYPE&quot;);
+            d = (l) ? strchr(d, '[') + 1 : d;
+            if (l &amp;&amp; ! ezxml_internal_dtd(root, d, s++ - d)) return &amp;root-&gt;xml;
+        }
+        else if (*s == '?') { // &lt;?...?&gt; processing instructions
+            do { s = strchr(s, '?'); } while (s &amp;&amp; *(++s) &amp;&amp; *s != '&gt;');
+            if (! s || (! *s &amp;&amp; e != '&gt;')) 
+                return ezxml_err(root, d, &quot;unclosed &lt;?&quot;);
+            else ezxml_proc_inst(root, d + 1, s - d - 2);
+        }
+        else return ezxml_err(root, d, &quot;unexpected &lt;&quot;);
+        
+        if (! s || ! *s) break;
+        *s = '\0';
+        d = ++s;
+        if (*s &amp;&amp; *s != '&lt;') { // tag character content
+            while (*s &amp;&amp; *s != '&lt;') s++;
+            if (*s) ezxml_char_content(root, d, s - d, '&amp;');
+            else break;
+        }
+        else if (! *s) break;
+    }
+
+    if (! root-&gt;cur) return &amp;root-&gt;xml;
+    else if (! root-&gt;cur-&gt;name) return ezxml_err(root, d, &quot;root tag missing&quot;);
+    else return ezxml_err(root, d, &quot;unclosed tag &lt;%s&gt;&quot;, root-&gt;cur-&gt;name);
+}
+
+// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire
+// stream into memory and then parses it. For xml files, use ezxml_parse_file()
+// or ezxml_parse_fd()
+ezxml_t ezxml_parse_fp(FILE *fp)
+{
+    ezxml_root_t root;
+    size_t l, len = 0;
+    char *s;
+
+    if (! (s = malloc(EZXML_BUFSIZE))) return NULL;
+    do {
+        len += (l = fread((s + len), 1, EZXML_BUFSIZE, fp));
+        if (l == EZXML_BUFSIZE) s = realloc(s, len + EZXML_BUFSIZE);
+    } while (s &amp;&amp; l == EZXML_BUFSIZE);
+
+    if (! s) return NULL;
+    root = (ezxml_root_t)ezxml_parse_str(s, len);
+    root-&gt;len = -1; // so we know to free s in ezxml_free()
+    return &amp;root-&gt;xml;
+}
+
+// A wrapper for ezxml_parse_str() that accepts a file descriptor. First
+// attempts to mem map the file. Failing that, reads the file into memory.
+// Returns NULL on failure.
+ezxml_t ezxml_parse_fd(int fd)
+{
+    ezxml_root_t root;
+    struct stat st;
+    size_t l;
+    void *m;
+
+    if (fd &lt; 0) return NULL;
+    fstat(fd, &amp;st);
+
+#ifndef EZXML_NOMMAP
+    l = (st.st_size + sysconf(_SC_PAGESIZE) - 1) &amp; ~(sysconf(_SC_PAGESIZE) -1);
+    if ((m = mmap(NULL, l, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) !=
+        MAP_FAILED) {
+        madvise(m, l, MADV_SEQUENTIAL); // optimize for sequential access
+        root = (ezxml_root_t)ezxml_parse_str(m, st.st_size);
+        madvise(m, root-&gt;len = l, MADV_NORMAL); // put it back to normal
+    }
+    else { // mmap failed, read file into memory
+#endif // EZXML_NOMMAP
+        l = read(fd, m = malloc(st.st_size), st.st_size);
+        root = (ezxml_root_t)ezxml_parse_str(m, l);
+        root-&gt;len = -1; // so we know to free s in ezxml_free()
+#ifndef EZXML_NOMMAP
+    }
+#endif // EZXML_NOMMAP
+    return &amp;root-&gt;xml;
+}
+
+// a wrapper for ezxml_parse_fd that accepts a file name
+ezxml_t ezxml_parse_file(const char *file)
+{
+    int fd = open(file, O_RDONLY, 0);
+    ezxml_t xml = ezxml_parse_fd(fd);
+    
+    if (fd &gt;= 0) close(fd);
+    return xml;
+}
+
+// Encodes ampersand sequences appending the results to *dst, reallocating *dst
+// if length excedes max. a is non-zero for attribute encoding. Returns *dst
+char *ezxml_ampencode(const char *s, size_t len, char **dst, size_t *dlen,
+                      size_t *max, short a)
+{
+    const char *e;
+    
+    for (e = s + len; s != e; s++) {
+        while (*dlen + 10 &gt; *max) *dst = realloc(*dst, *max += EZXML_BUFSIZE);
+
+        switch (*s) {
+        case '\0': return *dst;
+        case '&amp;': *dlen += sprintf(*dst + *dlen, &quot;&amp;amp;&quot;); break;
+        case '&lt;': *dlen += sprintf(*dst + *dlen, &quot;&amp;lt;&quot;); break;
+        case '&gt;': *dlen += sprintf(*dst + *dlen, &quot;&amp;gt;&quot;); break;
+        case '&quot;': *dlen += sprintf(*dst + *dlen, (a) ? &quot;&amp;quot;&quot; : &quot;\&quot;&quot;); break;
+        case '</font>
<font color="black">': *dlen += sprintf(*dst + *dlen, (a) ? &quot;&amp;#xA;&quot; : &quot;</font>
<font color="blue">&quot;); break;
+        case '\t': *dlen += sprintf(*dst + *dlen, (a) ? &quot;&amp;#x9;&quot; : &quot;\t&quot;); break;
+        case '\r': *dlen += sprintf(*dst + *dlen, &quot;&amp;#xD;&quot;); break;
+        default: (*dst)[(*dlen)++] = *s;
+        }
+    }
+    return *dst;
+}
+
+// Recursively converts each tag to xml appending it to *s. Reallocates *s if
+// its length excedes max. start is the location of the previous tag in the
+// parent tag's character content. Returns *s.
+char *ezxml_toxml_r(ezxml_t xml, char **s, size_t *len, size_t *max,
+                    size_t start, char ***attr)
+{
+    int i, j;
+    char *txt = (xml-&gt;parent) ? xml-&gt;parent-&gt;txt : &quot;&quot;;
+    size_t off = 0;
+
+    // parent character content up to this tag
+    *s = ezxml_ampencode(txt + start, xml-&gt;off - start, s, len, max, 0);
+
+    while (*len + strlen(xml-&gt;name) + 4 &gt; *max) // reallocate s
+        *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+    *len += sprintf(*s + *len, &quot;&lt;%s&quot;, xml-&gt;name); // open tag
+    for (i = 0; xml-&gt;attr[i]; i += 2) { // tag attributes
+        if (ezxml_attr(xml, xml-&gt;attr[i]) != xml-&gt;attr[i + 1]) continue;
+        while (*len + strlen(xml-&gt;attr[i]) + 7 &gt; *max) // reallocate s
+            *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+        *len += sprintf(*s + *len, &quot; %s=\&quot;&quot;, xml-&gt;attr[i]);
+        ezxml_ampencode(xml-&gt;attr[i + 1], -1, s, len, max, 1);
+        *len += sprintf(*s + *len, &quot;\&quot;&quot;);
+    }
+
+    for (i = 0; attr[i] &amp;&amp; strcmp(attr[i][0], xml-&gt;name); i++);
+    for (j = 1; attr[i] &amp;&amp; attr[i][j]; j += 3) { // default attributes
+        if (! attr[i][j + 1] || ezxml_attr(xml, attr[i][j]) != attr[i][j + 1])
+            continue; // skip duplicates and non-values
+        while (*len + strlen(attr[i][j]) + 7 &gt; *max) // reallocate s
+            *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+        *len += sprintf(*s + *len, &quot; %s=\&quot;&quot;, attr[i][j]);
+        ezxml_ampencode(attr[i][j + 1], -1, s, len, max, 1);
+        *len += sprintf(*s + *len, &quot;\&quot;&quot;);
+    }
+    *len += sprintf(*s + *len, &quot;&gt;&quot;);
+
+    *s = (xml-&gt;child) ? ezxml_toxml_r(xml-&gt;child, s, len, max, 0, attr) //child
+                      : ezxml_ampencode(xml-&gt;txt, -1, s, len, max, 0);  //data
+    
+    while (*len + strlen(xml-&gt;name) + 4 &gt; *max) // reallocate s
+        *s = realloc(*s, *max += EZXML_BUFSIZE);
+
+    *len += sprintf(*s + *len, &quot;&lt;/%s&gt;&quot;, xml-&gt;name); // close tag
+
+    while (txt[off] &amp;&amp; off &lt; xml-&gt;off) off++; // make sure off is within bounds
+    return (xml-&gt;ordered) ? ezxml_toxml_r(xml-&gt;ordered, s, len, max, off, attr)
+                          : ezxml_ampencode(txt + off, -1, s, len, max, 0);
+}
+
+// Converts an ezxml structure back to xml. Returns a string of xml data that
+// must be freed.
+char *ezxml_toxml(ezxml_t xml)
+{
+    ezxml_t p = (xml) ? xml-&gt;parent : NULL, o = (xml) ? xml-&gt;ordered : NULL;
+    ezxml_root_t root = (ezxml_root_t)xml;
+    size_t len = 0, max = EZXML_BUFSIZE;
+    char *s = strcpy(malloc(max), &quot;&quot;), *t, *n;
+    int i, j, k;
+
+    if (! xml || ! xml-&gt;name) return realloc(s, len + 1);
+    while (root-&gt;xml.parent) root = (ezxml_root_t)root-&gt;xml.parent; // root tag
+
+    for (i = 0; ! p &amp;&amp; root-&gt;pi[i]; i++) { // pre-root processing instructions
+        for (k = 2; root-&gt;pi[i][k - 1]; k++);
+        for (j = 1; (n = root-&gt;pi[i][j]); j++) {
+            if (root-&gt;pi[i][k][j - 1] == '&gt;') continue; // not pre-root
+            while (len + strlen(t = root-&gt;pi[i][0]) + strlen(n) + 7 &gt; max)
+                s = realloc(s, max += EZXML_BUFSIZE);
+            len += sprintf(s + len, &quot;&lt;?%s%s%s?&gt;</font>
<font color="blue">&quot;, t, *n ? &quot; &quot; : &quot;&quot;, n);
+        }
+    }
+
+    xml-&gt;parent = xml-&gt;ordered = NULL;
+    s = ezxml_toxml_r(xml, &amp;s, &amp;len, &amp;max, 0, root-&gt;attr);
+    xml-&gt;parent = p;
+    xml-&gt;ordered = o;
+
+    for (i = 0; ! p &amp;&amp; root-&gt;pi[i]; i++) { // post-root processing instructions
+        for (k = 2; root-&gt;pi[i][k - 1]; k++);
+        for (j = 1; (n = root-&gt;pi[i][j]); j++) {
+            if (root-&gt;pi[i][k][j - 1] == '&lt;') continue; // not post-root
+            while (len + strlen(t = root-&gt;pi[i][0]) + strlen(n) + 7 &gt; max)
+                s = realloc(s, max += EZXML_BUFSIZE);
+            len += sprintf(s + len, &quot;</font>
<font color="blue">&lt;?%s%s%s?&gt;&quot;, t, *n ? &quot; &quot; : &quot;&quot;, n);
+        }
+    }
+    return realloc(s, len + 1);
+}
+
+// free the memory allocated for the ezxml structure
+void ezxml_free(ezxml_t xml)
+{
+    ezxml_root_t root = (ezxml_root_t)xml;
+    int i, j;
+    char **a, *s;
+
+    if (! xml) return;
+    ezxml_free(xml-&gt;child);
+    ezxml_free(xml-&gt;ordered);
+
+    if (! xml-&gt;parent) { // free root tag allocations
+        for (i = 10; root-&gt;ent[i]; i += 2) // 0 - 9 are default entites (&lt;&gt;&amp;&quot;')
+            if ((s = root-&gt;ent[i + 1]) &lt; root-&gt;s || s &gt; root-&gt;e) free(s);
+        free(root-&gt;ent); // free list of general entities
+
+        for (i = 0; (a = root-&gt;attr[i]); i++) {
+            for (j = 1; a[j++]; j += 2) // free malloced attribute values
+                if (a[j] &amp;&amp; (a[j] &lt; root-&gt;s || a[j] &gt; root-&gt;e)) free(a[j]);
+            free(a);
+        }
+        if (root-&gt;attr[0]) free(root-&gt;attr); // free default attribute list
+
+        for (i = 0; root-&gt;pi[i]; i++) {
+            for (j = 1; root-&gt;pi[i][j]; j++);
+            free(root-&gt;pi[i][j + 1]);
+            free(root-&gt;pi[i]);
+        }            
+        if (root-&gt;pi[0]) free(root-&gt;pi); // free processing instructions
+
+        if (root-&gt;len == -1) free(root-&gt;m); // malloced xml data
+#ifndef EZXML_NOMMAP
+        else if (root-&gt;len) munmap(root-&gt;m, root-&gt;len); // mem mapped xml data
+#endif // EZXML_NOMMAP
+        if (root-&gt;u) free(root-&gt;u); // utf8 conversion
+    }
+
+    ezxml_free_attr(xml-&gt;attr); // tag attributes
+    if ((xml-&gt;flags &amp; EZXML_TXTM)) free(xml-&gt;txt); // character content
+    if ((xml-&gt;flags &amp; EZXML_NAMEM)) free(xml-&gt;name); // tag name
+    free(xml);
+}
+
+// return parser error message or empty string if none
+const char *ezxml_error(ezxml_t xml)
+{
+    while (xml &amp;&amp; xml-&gt;parent) xml = xml-&gt;parent; // find root tag
+    return (xml) ? ((ezxml_root_t)xml)-&gt;err : &quot;&quot;;
+}
+
+// returns a new empty ezxml structure with the given root tag name
+ezxml_t ezxml_new(const char *name)
+{
+    static char *ent[] = { &quot;lt;&quot;, &quot;&amp;#60;&quot;, &quot;gt;&quot;, &quot;&amp;#62;&quot;, &quot;quot;&quot;, &quot;&amp;#34;&quot;,
+                           &quot;apos;&quot;, &quot;&amp;#39;&quot;, &quot;amp;&quot;, &quot;&amp;#38;&quot;, NULL };
+    ezxml_root_t root = (ezxml_root_t)memset(malloc(sizeof(struct ezxml_root)), 
+                                             '\0', sizeof(struct ezxml_root));
+    root-&gt;xml.name = (char *)name;
+    root-&gt;cur = &amp;root-&gt;xml;
+    strcpy(root-&gt;err, root-&gt;xml.txt = &quot;&quot;);
+    root-&gt;ent = memcpy(malloc(sizeof(ent)), ent, sizeof(ent));
+    root-&gt;attr = root-&gt;pi = (char ***)(root-&gt;xml.attr = EZXML_NIL);
+    return &amp;root-&gt;xml;
+}
+
+// inserts an existing tag into an ezxml structure
+ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off)
+{
+    ezxml_t cur, prev, head;
+
+    xml-&gt;next = xml-&gt;sibling = xml-&gt;ordered = NULL;
+    xml-&gt;off = off;
+    xml-&gt;parent = dest;
+
+    if ((head = dest-&gt;child)) { // already have sub tags
+        if (head-&gt;off &lt;= off) { // not first subtag
+            for (cur = head; cur-&gt;ordered &amp;&amp; cur-&gt;ordered-&gt;off &lt;= off;
+                 cur = cur-&gt;ordered);
+            xml-&gt;ordered = cur-&gt;ordered;
+            cur-&gt;ordered = xml;
+        }
+        else { // first subtag
+            xml-&gt;ordered = head;
+            dest-&gt;child = xml;
+        }
+
+        for (cur = head, prev = NULL; cur &amp;&amp; strcmp(cur-&gt;name, xml-&gt;name);
+             prev = cur, cur = cur-&gt;sibling); // find tag type
+        if (cur &amp;&amp; cur-&gt;off &lt;= off) { // not first of type
+            while (cur-&gt;next &amp;&amp; cur-&gt;next-&gt;off &lt;= off) cur = cur-&gt;next;
+            xml-&gt;next = cur-&gt;next;
+            cur-&gt;next = xml;
+        }
+        else { // first tag of this type
+            if (prev &amp;&amp; cur) prev-&gt;sibling = cur-&gt;sibling; // remove old first
+            xml-&gt;next = cur; // old first tag is now next
+            for (cur = head, prev = NULL; cur &amp;&amp; cur-&gt;off &lt;= off;
+                 prev = cur, cur = cur-&gt;sibling); // new sibling insert point
+            xml-&gt;sibling = cur;
+            if (prev) prev-&gt;sibling = xml;
+        }
+    }
+    else dest-&gt;child = xml; // only sub tag
+
+    return xml;
+}
+
+// Adds a child tag. off is the offset of the child tag relative to the start
+// of the parent tag's character content. Returns the child tag.
+ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off)
+{
+    ezxml_t child;
+
+    if (! xml) return NULL;
+    child = (ezxml_t)memset(malloc(sizeof(struct ezxml)), '\0',
+                            sizeof(struct ezxml));
+    child-&gt;name = (char *)name;
+    child-&gt;attr = EZXML_NIL;
+    child-&gt;txt = &quot;&quot;;
+
+    return ezxml_insert(child, xml, off);
+}
+
+// sets the character content for the given tag and returns the tag
+ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt)
+{
+    if (! xml) return NULL;
+    if (xml-&gt;flags &amp; EZXML_TXTM) free(xml-&gt;txt); // existing txt was malloced
+    xml-&gt;flags &amp;= ~EZXML_TXTM;
+    xml-&gt;txt = (char *)txt;
+    return xml;
+}
+
+// Sets the given tag attribute or adds a new attribute if not found. A value
+// of NULL will remove the specified attribute. Returns the tag given.
+ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value)
+{
+    int l = 0, c;
+
+    if (! xml) return NULL;
+    while (xml-&gt;attr[l] &amp;&amp; strcmp(xml-&gt;attr[l], name)) l += 2;
+    if (! xml-&gt;attr[l]) { // not found, add as new attribute
+        if (! value) return xml; // nothing to do
+        if (xml-&gt;attr == EZXML_NIL) { // first attribute
+            xml-&gt;attr = malloc(4 * sizeof(char *));
+            xml-&gt;attr[1] = strdup(&quot;&quot;); // empty list of malloced names/vals
+        }
+        else xml-&gt;attr = realloc(xml-&gt;attr, (l + 4) * sizeof(char *));
+
+        xml-&gt;attr[l] = (char *)name; // set attribute name
+        xml-&gt;attr[l + 2] = NULL; // null terminate attribute list
+        xml-&gt;attr[l + 3] = realloc(xml-&gt;attr[l + 1],
+                                   (c = strlen(xml-&gt;attr[l + 1])) + 2);
+        strcpy(xml-&gt;attr[l + 3] + c, &quot; &quot;); // set name/value as not malloced
+        if (xml-&gt;flags &amp; EZXML_DUP) xml-&gt;attr[l + 3][c] = EZXML_NAMEM;
+    }
+    else if (xml-&gt;flags &amp; EZXML_DUP) free((char *)name); // name was strduped
+
+    for (c = l; xml-&gt;attr[c]; c += 2); // find end of attribute list
+    if (xml-&gt;attr[c + 1][l / 2] &amp; EZXML_TXTM) free(xml-&gt;attr[l + 1]); //old val
+    if (xml-&gt;flags &amp; EZXML_DUP) xml-&gt;attr[c + 1][l / 2] |= EZXML_TXTM;
+    else xml-&gt;attr[c + 1][l / 2] &amp;= ~EZXML_TXTM;
+
+    if (value) xml-&gt;attr[l + 1] = (char *)value; // set attribute value
+    else { // remove attribute
+        if (xml-&gt;attr[c + 1][l / 2] &amp; EZXML_NAMEM) free(xml-&gt;attr[l]);
+        memmove(xml-&gt;attr + l, xml-&gt;attr + l + 2, (c - l + 2) * sizeof(char*));
+        xml-&gt;attr = realloc(xml-&gt;attr, (c + 2) * sizeof(char *));
+        memmove(xml-&gt;attr[c + 1] + (l / 2), xml-&gt;attr[c + 1] + (l / 2) + 1,
+                (c / 2) - (l / 2)); // fix list of which name/vals are malloced
+    }
+    xml-&gt;flags &amp;= ~EZXML_DUP; // clear strdup() flag
+    return xml;
+}
+
+// sets a flag for the given tag and returns the tag
+ezxml_t ezxml_set_flag(ezxml_t xml, short flag)
+{
+    if (xml) xml-&gt;flags |= flag;
+    return xml;
+}
+
+// removes a tag along with its subtags without freeing its memory
+ezxml_t ezxml_cut(ezxml_t xml)
+{
+    ezxml_t cur;
+
+    if (! xml) return NULL; // nothing to do
+    if (xml-&gt;next) xml-&gt;next-&gt;sibling = xml-&gt;sibling; // patch sibling list
+
+    if (xml-&gt;parent) { // not root tag
+        cur = xml-&gt;parent-&gt;child; // find head of subtag list
+        if (cur == xml) xml-&gt;parent-&gt;child = xml-&gt;ordered; // first subtag
+        else { // not first subtag
+            while (cur-&gt;ordered != xml) cur = cur-&gt;ordered;
+            cur-&gt;ordered = cur-&gt;ordered-&gt;ordered; // patch ordered list
+
+            cur = xml-&gt;parent-&gt;child; // go back to head of subtag list
+            if (strcmp(cur-&gt;name, xml-&gt;name)) { // not in first sibling list
+                while (strcmp(cur-&gt;sibling-&gt;name, xml-&gt;name))
+                    cur = cur-&gt;sibling;
+                if (cur-&gt;sibling == xml) { // first of a sibling list
+                    cur-&gt;sibling = (xml-&gt;next) ? xml-&gt;next
+                                               : cur-&gt;sibling-&gt;sibling;
+                }
+                else cur = cur-&gt;sibling; // not first of a sibling list
+            }
+
+            while (cur-&gt;next &amp;&amp; cur-&gt;next != xml) cur = cur-&gt;next;
+            if (cur-&gt;next) cur-&gt;next = cur-&gt;next-&gt;next; // patch next list
+        }        
+    }
+    xml-&gt;ordered = xml-&gt;sibling = xml-&gt;next = NULL;
+    return xml;
+}
+
+#ifdef EZXML_TEST // test harness
+int main(int argc, char **argv)
+{
+    ezxml_t xml;
+    char *s;
+    int i;
+
+    if (argc != 2) return fprintf(stderr, &quot;usage: %s xmlfile</font>
<font color="blue">&quot;, argv[0]);
+
+    xml = ezxml_parse_file(argv[1]);
+    printf(&quot;%s</font>
<font color="gray">&quot;, (s = ezxml_toxml(xml)));
+    free(s);
+    i = fprintf(stderr, &quot;%s&quot;, ezxml_error(xml));
+    ezxml_free(xml);
+    return (i) ? 1 : 0;
+}
+#endif // EZXML_TEST

Added: branches/xml_registry/src/registry/ezxml/ezxml.h
===================================================================
--- branches/xml_registry/src/registry/ezxml/ezxml.h                                (rev 0)
+++ branches/xml_registry/src/registry/ezxml/ezxml.h        2013-03-14 20:15:45 UTC (rev 2612)
@@ -0,0 +1,167 @@
+/* ezxml.h
+ *
+ * Copyright 2004-2006 Aaron Voisine &lt;aaron@voisine.org&gt;
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * &quot;Software&quot;), 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 &quot;AS IS&quot;, 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.
+ */
+
+#ifndef _EZXML_H
+#define _EZXML_H
+
+#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+#include &lt;stdarg.h&gt;
+#include &lt;fcntl.h&gt;
+
+#ifdef __cplusplus
+extern &quot;C&quot; {
+#endif
+
+#define EZXML_BUFSIZE 1024 // size of internal memory buffers
+#define EZXML_NAMEM   0x80 // name is malloced
+#define EZXML_TXTM    0x40 // txt is malloced
+#define EZXML_DUP     0x20 // attribute name and value are strduped
+
+typedef struct ezxml *ezxml_t;
+struct ezxml {
+    char *name;      // tag name
+    char **attr;     // tag attributes { name, value, name, value, ... NULL }
+    char *txt;       // tag character content, empty string if none
+    size_t off;      // tag offset from start of parent tag character content
+    ezxml_t next;    // next tag with same name in this section at this depth
+    ezxml_t sibling; // next tag with different name in same section and depth
+    ezxml_t ordered; // next tag, same section and depth, in original order
+    ezxml_t child;   // head of sub tag list, NULL if none
+    ezxml_t parent;  // parent tag, NULL if current tag is root tag
+    short flags;     // additional information
+};
+
+// Given a string of xml data and its length, parses it and creates an ezxml
+// structure. For efficiency, modifies the data by adding null terminators
+// and decoding ampersand sequences. If you don't want this, copy the data and
+// pass in the copy. Returns NULL on failure.
+ezxml_t ezxml_parse_str(char *s, size_t len);
+
+// A wrapper for ezxml_parse_str() that accepts a file descriptor. First
+// attempts to mem map the file. Failing that, reads the file into memory.
+// Returns NULL on failure.
+ezxml_t ezxml_parse_fd(int fd);
+
+// a wrapper for ezxml_parse_fd() that accepts a file name
+ezxml_t ezxml_parse_file(const char *file);
+    
+// Wrapper for ezxml_parse_str() that accepts a file stream. Reads the entire
+// stream into memory and then parses it. For xml files, use ezxml_parse_file()
+// or ezxml_parse_fd()
+ezxml_t ezxml_parse_fp(FILE *fp);
+
+// returns the first child tag (one level deeper) with the given name or NULL
+// if not found
+ezxml_t ezxml_child(ezxml_t xml, const char *name);
+
+// returns the next tag of the same name in the same section and depth or NULL
+// if not found
+#define ezxml_next(xml) ((xml) ? xml-&gt;next : NULL)
+
+// Returns the Nth tag with the same name in the same section at the same depth
+// or NULL if not found. An index of 0 returns the tag given.
+ezxml_t ezxml_idx(ezxml_t xml, int idx);
+
+// returns the name of the given tag
+#define ezxml_name(xml) ((xml) ? xml-&gt;name : NULL)
+
+// returns the given tag's character content or empty string if none
+#define ezxml_txt(xml) ((xml) ? xml-&gt;txt : &quot;&quot;)
+
+// returns the value of the requested tag attribute, or NULL if not found
+const char *ezxml_attr(ezxml_t xml, const char *attr);
+
+// Traverses the ezxml sturcture to retrieve a specific subtag. Takes a
+// variable length list of tag names and indexes. The argument list must be
+// terminated by either an index of -1 or an empty string tag name. Example: 
+// title = ezxml_get(library, &quot;shelf&quot;, 0, &quot;book&quot;, 2, &quot;title&quot;, -1);
+// This retrieves the title of the 3rd book on the 1st shelf of library.
+// Returns NULL if not found.
+ezxml_t ezxml_get(ezxml_t xml, ...);
+
+// Converts an ezxml structure back to xml. Returns a string of xml data that
+// must be freed.
+char *ezxml_toxml(ezxml_t xml);
+
+// returns a NULL terminated array of processing instructions for the given
+// target
+const char **ezxml_pi(ezxml_t xml, const char *target);
+
+// frees the memory allocated for an ezxml structure
+void ezxml_free(ezxml_t xml);
+    
+// returns parser error message or empty string if none
+const char *ezxml_error(ezxml_t xml);
+
+// returns a new empty ezxml structure with the given root tag name
+ezxml_t ezxml_new(const char *name);
+
+// wrapper for ezxml_new() that strdup()s name
+#define ezxml_new_d(name) ezxml_set_flag(ezxml_new(strdup(name)), EZXML_NAMEM)
+
+// Adds a child tag. off is the offset of the child tag relative to the start
+// of the parent tag's character content. Returns the child tag.
+ezxml_t ezxml_add_child(ezxml_t xml, const char *name, size_t off);
+
+// wrapper for ezxml_add_child() that strdup()s name
+#define ezxml_add_child_d(xml, name, off) \
+    ezxml_set_flag(ezxml_add_child(xml, strdup(name), off), EZXML_NAMEM)
+
+// sets the character content for the given tag and returns the tag
+ezxml_t ezxml_set_txt(ezxml_t xml, const char *txt);
+
+// wrapper for ezxml_set_txt() that strdup()s txt
+#define ezxml_set_txt_d(xml, txt) \
+    ezxml_set_flag(ezxml_set_txt(xml, strdup(txt)), EZXML_TXTM)
+
+// Sets the given tag attribute or adds a new attribute if not found. A value
+// of NULL will remove the specified attribute. Returns the tag given.
+ezxml_t ezxml_set_attr(ezxml_t xml, const char *name, const char *value);
+
+// Wrapper for ezxml_set_attr() that strdup()s name/value. Value cannot be NULL
+#define ezxml_set_attr_d(xml, name, value) \
+    ezxml_set_attr(ezxml_set_flag(xml, EZXML_DUP), strdup(name), strdup(value))
+
+// sets a flag for the given tag and returns the tag
+ezxml_t ezxml_set_flag(ezxml_t xml, short flag);
+
+// removes a tag along with its subtags without freeing its memory
+ezxml_t ezxml_cut(ezxml_t xml);
+
+// inserts an existing tag into an ezxml structure
+ezxml_t ezxml_insert(ezxml_t xml, ezxml_t dest, size_t off);
+
+// Moves an existing tag to become a subtag of dest at the given offset from
+// the start of dest's character content. Returns the moved tag.
+#define ezxml_move(xml, dest, off) ezxml_insert(ezxml_cut(xml), dest, off)
+
+// removes a tag along with all its subtags
+#define ezxml_remove(xml) ezxml_free(ezxml_cut(xml))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _EZXML_H

Modified: branches/xml_registry/src/registry/gen_inc.c
===================================================================
--- branches/xml_registry/src/registry/gen_inc.c        2013-03-14 19:21:28 UTC (rev 2611)
+++ branches/xml_registry/src/registry/gen_inc.c        2013-03-14 20:15:45 UTC (rev 2612)
@@ -1159,7 +1159,10 @@
             for(i=1; i&lt;=ntime_levs; i++) 
             {
                                 fortprintf(fd, &quot;         if(associated(next) .and. associated(prev)) then</font>
<font color="red">&quot;);        
-                                fortprintf(fd, &quot;           call mpas_create_%s_links(b %% %s %% time_levs(%i) %% %s, prev = prev %% %s %% time_levs(%i) %% %s, next = next %% %s %% time_levs(%i) %% %s)</font>
<font color="blue">&quot;, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name, i, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name);
+//                                fortprintf(fd, &quot;           call mpas_create_%s_links(b %% %s %% time_levs(%i) %% %s, prev = prev %% %s %% time_levs(%i) %% %s, next = next %% %s %% time_levs(%i) %% %s)</font>
<font color="blue">&quot;, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name, i, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name);
+                                fortprintf(fd, &quot;           call mpas_create_%s_links(b %% %s %% time_levs(%i) %% %s, &quot;, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name, i);
+                                fortprintf(fd, &quot; prev = prev %% %s %% time_levs(%i) %% %s,&quot;, group_ptr-&gt;name, i, group_ptr-&gt;name);
+                                fortprintf(fd, &quot; next = next %% %s %% time_levs(%i) %% %s)</font>
<font color="black">&quot;, group_ptr-&gt;name, i, group_ptr-&gt;name);
                                 fortprintf(fd, &quot;         else if(associated(next)) then</font>
<font color="black">&quot;);        
                                 fortprintf(fd, &quot;           call mpas_create_%s_links(b %% %s %% time_levs(%i) %% %s, next = next %% %s %% time_levs(%i) %% %s)</font>
<font color="black">&quot;, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name, group_ptr-&gt;name, i, group_ptr-&gt;name);
                                 fortprintf(fd, &quot;         else if(associated(prev)) then</font>
<font color="gray">&quot;);        
@@ -1387,7 +1390,7 @@
 void gen_reads(struct group_list * groups, struct variable * vars, struct dimension * dims)
 {
    struct variable * var_ptr;
-   struct variable_list * var_list_ptr;
+   struct variable_list * var_list_ptr, *var_list_ptr2;
    struct dimension * dim_ptr;
    struct dimension_list * dimlist_ptr, * lastdim;
    struct group_list * group_ptr;
@@ -2117,8 +2120,10 @@
 /*            fortprintf(fd, &quot;         write(0,*) \'adding input field %s\'</font>
<font color="black">&quot;, var_ptr-&gt;super_array); */
             fortprintf(fd, &quot;         call MPAS_streamAddField(input_obj %% io_stream, %s %% %s, nferr)</font>
<font color="blue">&quot;, struct_deref, var_ptr-&gt;super_array);
             while (var_list_ptr &amp;&amp; strncmp(super_array, var_list_ptr-&gt;var-&gt;super_array, 1024) == 0) {
+                           var_list_ptr2 = var_list_ptr;
                var_list_ptr = var_list_ptr-&gt;next;
             }
+                        var_list_ptr = var_list_ptr2;
          }
          else {
             fortprintf(fd, &quot;      if ((%s %% %s %% ioinfo %% input .and. input_obj %% stream == STREAM_INPUT) .or. &amp;</font>
<font color="gray">&quot;, struct_deref, var_ptr-&gt;name_in_code);
@@ -2174,8 +2179,10 @@
 /*                     fortprintf(fd, &quot;         write(0,*) \'exchange halo for %s\'</font>
<font color="black">&quot;, var_ptr-&gt;super_array); */
                      fortprintf(fd, &quot;         call mpas_dmpar_exch_halo_field(%s %% %s)</font>
<font color="blue">&quot;, struct_deref, var_ptr-&gt;super_array);
                      while (var_list_ptr &amp;&amp; strncmp(super_array, var_list_ptr-&gt;var-&gt;super_array, 1024) == 0) {
+                                                var_list_ptr2 = var_list_ptr;
                         var_list_ptr = var_list_ptr-&gt;next;
                      }
+                                         var_list_ptr = var_list_ptr2;
                   }
                   else {
                      fortprintf(fd, &quot;      if ((%s %% %s %% ioinfo %% input .and. input_obj %% stream == STREAM_INPUT) .or. &amp;</font>
<font color="gray">&quot;, struct_deref, var_ptr-&gt;name_in_code);
@@ -2381,7 +2388,7 @@
 void gen_writes(struct group_list * groups, struct variable * vars, struct dimension * dims, struct namelist * namelists)
 {
    struct variable * var_ptr;
-   struct variable_list * var_list_ptr;
+   struct variable_list * var_list_ptr, *var_list_ptr2;
    struct dimension * dim_ptr;
    struct dimension_list * dimlist_ptr, * lastdim;
    struct group_list * group_ptr;
@@ -2563,8 +2570,10 @@
             memcpy(super_array, var_ptr-&gt;super_array, 1024);
             fortprintf(fd, &quot;         call MPAS_streamAddField(output_obj %% io_stream, %s %% %s, ierr)</font>
<font color="blue">&quot;, struct_deref, super_array);
             while (var_list_ptr &amp;&amp; strncmp(super_array, var_list_ptr-&gt;var-&gt;super_array, 1024) == 0) {
+                           var_list_ptr2 = var_list_ptr;
                var_list_ptr = var_list_ptr-&gt;next;
             }
+                        var_list_ptr = var_list_ptr2;
          }
          else {
             fortprintf(fd, &quot;      if ((%s %% %s %% ioinfo %% output .and. output_obj %% stream == OUTPUT) .or. &amp;</font>
<font color="gray">&quot;, struct_deref, var_ptr-&gt;name_in_code);

Modified: branches/xml_registry/src/registry/parse.c
===================================================================
--- branches/xml_registry/src/registry/parse.c        2013-03-14 19:21:28 UTC (rev 2611)
+++ branches/xml_registry/src/registry/parse.c        2013-03-14 20:15:45 UTC (rev 2612)
@@ -3,6 +3,7 @@
 #include &lt;string.h&gt;
 #include &quot;registry_types.h&quot;
 #include &quot;gen_inc.h&quot;
+#include &quot;ezxml/ezxml.h&quot;
 
 int parse_reg(FILE *, struct namelist **, struct dimension **, struct variable **, struct group_list **);
 int getword(FILE *, char *);
@@ -30,9 +31,16 @@
    nls = NULL;
    dims = NULL;
    vars = NULL;
+  
+   if (parse_reg_xml(regfile, &amp;nls, &amp;dims, &amp;vars, &amp;groups)) {
+      return 1;
+   }
+  
+/* Old Parser
    if (parse_reg(regfile, &amp;nls, &amp;dims, &amp;vars, &amp;groups)) {
       return 1;
    }
+*/
 
    sort_vars(vars);
    sort_group_vars(groups);
@@ -45,7 +53,391 @@
    return 0;
 }
 
+int parse_reg_xml(FILE * regfile, struct namelist **nls, struct dimension ** dims, struct variable ** vars, struct group_list ** groups)
+{
+        struct namelist * nls_ptr, *nls_ptr2;
+        struct namelist * nls_chk_ptr;
+        struct dimension * dim_ptr, *dim_ptr2;
+        struct variable * var_ptr, *var_ptr2;
+        struct dimension_list * dimlist_ptr;
+        struct dimension * dimlist_cursor;
+        struct group_list * grouplist_ptr;
+        struct variable_list * vlist_cursor;
 
+        ezxml_t registry = ezxml_parse_fp(regfile);
+        ezxml_t dims_xml, dim_xml;
+        ezxml_t structs_xml, var_arr_xml, var_xml;
+        ezxml_t nmlrecs_xml, nmlopt_xml;
+
+        const char *dimname, *dimunits, *dimdesc, *dimdef;
+        const char *nmlrecname, *nmloptname, *nmlopttype, *nmloptval, *nmloptunits, *nmloptdesc, *nmloptposvals;
+        const char *structname, *structlevs;
+        const char *vararrname, *vararrtype, *vararrdims, *vararrpersistence;
+        const char *varname, *varpersistence, *vartype, *vardims, *varunits, *vardesc, *vararrgroup, *varstreams;
+        const char *varname_in_code;
+
+        char dimensions[2048];
+        char *dimension_list;
+        char dimension_buffer[128];
+        char streams_buffer[128];
+
+        NEW_NAMELIST(nls_ptr)
+        NEW_DIMENSION(dim_ptr)
+        NEW_VARIABLE(var_ptr)
+        NEW_GROUP_LIST(grouplist_ptr);
+        *nls = nls_ptr;
+        *dims = dim_ptr;
+        *vars = var_ptr;
+        *groups = grouplist_ptr;
+
+        // Parse Namelist Records
+        for (nmlrecs_xml = ezxml_child(registry, &quot;nml_record&quot;); nmlrecs_xml; nmlrecs_xml = nmlrecs_xml-&gt;next){
+                nmlrecname = ezxml_attr(nmlrecs_xml, &quot;name&quot;);
+                for (nmlopt_xml = ezxml_child(nmlrecs_xml, &quot;nml_option&quot;); nmlopt_xml; nmlopt_xml = nmlopt_xml-&gt;next){
+                        nmloptname = ezxml_attr(nmlopt_xml, &quot;name&quot;);
+                        nmlopttype = ezxml_attr(nmlopt_xml, &quot;type&quot;);
+                        nmloptval = ezxml_attr(nmlopt_xml, &quot;default_value&quot;);
+                        nmloptunits = ezxml_attr(nmlopt_xml, &quot;units&quot;);
+                        nmloptdesc = ezxml_attr(nmlopt_xml, &quot;description&quot;);
+                        nmloptposvals = ezxml_attr(nmlopt_xml, &quot;possible_values&quot;);
+
+                        snprintf(nls_ptr-&gt;record, 1024, &quot;%s&quot;, nmlrecname);
+                        snprintf(nls_ptr-&gt;name, 1024, &quot;%s&quot;, nmloptname);
+
+                        if(strncmp(nmlopttype, &quot;real&quot;, 1024) == 0){
+                                nls_ptr-&gt;vtype = REAL;
+                        } else if(strncmp(nmlopttype, &quot;integer&quot;, 1024) == 0){
+                                nls_ptr-&gt;vtype = INTEGER;
+                        } else if(strncmp(nmlopttype, &quot;logical&quot;, 1024) == 0){
+                                nls_ptr-&gt;vtype = LOGICAL;
+                        } else if(strncmp(nmlopttype, &quot;character&quot;, 1024) == 0){
+                                nls_ptr-&gt;vtype = CHARACTER;
+                        }
+
+                        switch(nls_ptr-&gt;vtype){
+                                case REAL:
+                                        nls_ptr-&gt;defval.rval = (float)atof(nmloptval);
+                                        break;
+                                case INTEGER:
+                                        nls_ptr-&gt;defval.ival = atoi(nmloptval);
+                                        break;
+                                case LOGICAL:
+                                        if(strncmp(nmloptval, &quot;true&quot;, 1024) ==0){
+                                                nls_ptr-&gt;defval.lval = 1;
+                                        } else if (strncmp(nmloptval, &quot;false&quot;, 1024) == 0){
+                                                nls_ptr-&gt;defval.lval = 0;
+                                        }
+                                        break;
+                                case CHARACTER:
+                                        snprintf(nls_ptr-&gt;defval.cval, 32, &quot;%s&quot;, nmloptval);
+                                        break;
+                        }
+
+                        NEW_NAMELIST(nls_ptr-&gt;next)
+                        nls_ptr2 = nls_ptr;
+                        nls_ptr = nls_ptr-&gt;next;
+                }
+        }
+
+        if(nls_ptr2-&gt;next) free(nls_ptr2-&gt;next);
+        nls_ptr2-&gt;next = NULL;
+
+        // Parse Dimensions
+        for (dims_xml = ezxml_child(registry, &quot;dims&quot;); dims_xml; dims_xml = dims_xml-&gt;next){
+                for (dim_xml = ezxml_child(dims_xml, &quot;dim&quot;); dim_xml; dim_xml = dim_xml-&gt;next){
+                        dimname = ezxml_attr(dim_xml, &quot;name&quot;);
+                        dimdef = ezxml_attr(dim_xml, &quot;definition&quot;);        
+                        dimunits = ezxml_attr(dim_xml, &quot;units&quot;);
+                        dimdesc = ezxml_attr(dim_xml, &quot;description&quot;);
+
+                        dim_ptr-&gt;namelist_defined = 0;
+
+                        snprintf(dim_ptr-&gt;name_in_file, 1024, &quot;%s&quot;, dimname);
+                        if(dimdef == NULL){
+                                snprintf(dim_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, dimname);
+                                dim_ptr-&gt;constant_value = -1;
+                        } else {
+                                snprintf(dim_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, dimdef);
+                                // Check namelist defined ??
+                                dim_ptr-&gt;constant_value = is_integer_constant(dim_ptr-&gt;name_in_code);
+                                if(strncmp(dim_ptr-&gt;name_in_code, &quot;namelist:&quot;, 9) == 0) {
+                                        dim_ptr-&gt;namelist_defined = 1;
+                                        snprintf(dim_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, (dim_ptr-&gt;name_in_code)+9);
+
+                                        /* Check that the referenced namelist variable is defined as an integer variable */
+                                        nls_chk_ptr = (*nls)-&gt;next;
+                                        while (nls_chk_ptr) {
+                                                if (strncmp(nls_chk_ptr-&gt;name, dim_ptr-&gt;name_in_code, 1024) == 0) {
+                                                        if (nls_chk_ptr-&gt;vtype != INTEGER) {
+                                                                printf(&quot;</font>
<font color="black">Registry error: Namelist variable %s must be an integer for namelist-derived dimension %s</font>
<font color="black"></font>
<font color="blue">&quot;, nls_chk_ptr-&gt;name, dim_ptr-&gt;name_in_file);
+                                                                return 1;
+                                                        }
+                                                        break;
+                                                } 
+                                                nls_chk_ptr = nls_chk_ptr-&gt;next;
+                                        }
+                                        if (!nls_chk_ptr) {
+                                                printf(&quot;</font>
<font color="black">Registry error: Namelist variable %s not defined for namelist-derived dimension %s</font>
<font color="black"></font>
<font color="blue">&quot;, dim_ptr-&gt;name_in_code, dim_ptr-&gt;name_in_file);
+                                                return 1;
+                                        }
+
+                                }
+                        }
+
+                        NEW_DIMENSION(dim_ptr-&gt;next)
+                        dim_ptr2 = dim_ptr;
+                        dim_ptr = dim_ptr-&gt;next;
+                }   
+        }
+
+        if(dim_ptr2-&gt;next) free(dim_ptr2-&gt;next);
+        dim_ptr2-&gt;next = NULL;
+
+        // Parse Variable Structures
+        for(structs_xml = ezxml_child(registry, &quot;var_struct&quot;); structs_xml; structs_xml = structs_xml-&gt;next){
+                structname = ezxml_attr(structs_xml, &quot;name&quot;);
+                structlevs = ezxml_attr(structs_xml, &quot;time_levs&quot;);
+
+                grouplist_ptr = *groups;
+                while(grouplist_ptr-&gt;next) grouplist_ptr = grouplist_ptr-&gt;next;
+                NEW_GROUP_LIST(grouplist_ptr-&gt;next);
+                grouplist_ptr = grouplist_ptr-&gt;next;
+                snprintf(grouplist_ptr-&gt;name, 1024, &quot;%s&quot;, structname);
+                vlist_cursor = NULL;
+
+                // Parse variable arrays
+                for(var_arr_xml = ezxml_child(structs_xml, &quot;var_array&quot;); var_arr_xml; var_arr_xml = var_arr_xml-&gt;next){
+                        vararrname = ezxml_attr(var_arr_xml, &quot;name&quot;);
+                        vararrtype = ezxml_attr(var_arr_xml, &quot;type&quot;);
+                        vararrdims = ezxml_attr(var_arr_xml, &quot;dimensions&quot;);
+                        vararrpersistence = ezxml_attr(var_arr_xml, &quot;persistence&quot;);
+
+                        //Parse variables in variable arrays
+                        for(var_xml = ezxml_child(var_arr_xml, &quot;var&quot;); var_xml; var_xml = var_xml-&gt;next){
+                                varname = ezxml_attr(var_xml, &quot;name&quot;);
+                                varunits = ezxml_attr(var_xml, &quot;units&quot;);
+                                vardesc = ezxml_attr(var_xml, &quot;description&quot;);
+                                varstreams = ezxml_attr(var_xml, &quot;streams&quot;);
+                                vararrgroup = ezxml_attr(var_xml, &quot;array_group&quot;);
+                                varname_in_code = ezxml_attr(var_xml, &quot;name_in_code&quot;);
+
+                                if(vlist_cursor == NULL){
+                                        NEW_VARIABLE_LIST(grouplist_ptr-&gt;vlist);
+                                        vlist_cursor = grouplist_ptr-&gt;vlist;
+                                } else {
+                                        NEW_VARIABLE_LIST(vlist_cursor-&gt;next);
+                                        vlist_cursor-&gt;next-&gt;prev = vlist_cursor;
+                                        vlist_cursor = vlist_cursor-&gt;next;
+                                }
+                                vlist_cursor-&gt;var = var_ptr;
+                                vlist_cursor-&gt;next = NULL;
+
+                                var_ptr-&gt;ndims = 0;
+                                var_ptr-&gt;timedim = 0;
+                                var_ptr-&gt;iostreams = 0;
+
+                                snprintf(var_ptr-&gt;name_in_file, 1024, &quot;%s&quot;, varname);
+
+                                if(vararrpersistence == NULL){
+                                        var_ptr-&gt;persistence = PERSISTENT;
+                                } else {
+                                        if(strncmp(vararrpersistence, &quot;persistent&quot;, 1024) == 0){
+                                                var_ptr-&gt;persistence = PERSISTENT;
+                                        } else if(strncmp(vararrpersistence, &quot;scratch&quot;, 1024) == 0){
+                                                var_ptr-&gt;persistence = SCRATCH;
+                                        }
+                                }
+
+                                if(strncmp(vararrtype, &quot;real&quot;, 1024) == 0){
+                                        var_ptr-&gt;vtype = REAL;
+                                } else if(strncmp(vararrtype, &quot;integer&quot;, 1024) == 0){
+                                        var_ptr-&gt;vtype = INTEGER;
+                                } else if(strncmp(vararrtype, &quot;logical&quot;, 1024) == 0){
+                                        var_ptr-&gt;vtype = LOGICAL;
+                                } else if(strncmp(vararrtype, &quot;text&quot;, 1024) == 0){
+                                        var_ptr-&gt;vtype = CHARACTER;
+                                }
+
+                                NEW_DIMENSION_LIST(dimlist_ptr)
+                                var_ptr-&gt;dimlist = dimlist_ptr;
+
+                                snprintf(dimensions,2048, &quot;%s&quot;, vararrdims);
+                                dimension_list = strtok(dimensions, &quot; &quot;);
+                                while(dimension_list != NULL){
+                                        snprintf(dimension_buffer, 128, &quot;%s&quot;, dimension_list);
+                                        if(strncmp(dimension_buffer, &quot;Time&quot;, 1024) == 0){
+                                                var_ptr-&gt;timedim = 1;
+                                        } else {
+                                                NEW_DIMENSION_LIST(dimlist_ptr-&gt;next)
+                                                dimlist_ptr-&gt;next-&gt;prev = dimlist_ptr;
+                                                dimlist_ptr = dimlist_ptr-&gt;next;
+
+                                                dimlist_cursor = (*dims);
+                                                while(dimlist_cursor &amp;&amp; (strncmp(dimension_buffer, dimlist_cursor-&gt;name_in_file, 1024) != 0)){
+                                                        dimlist_cursor = dimlist_cursor-&gt;next;
+                                                }
+                                                if (dimlist_cursor) {
+                                                        dimlist_ptr-&gt;dim = dimlist_cursor;
+                                                } else {
+                                                        fprintf(stderr, &quot;Error: Unknown dimension %s for variable %s</font>
<font color="blue">&quot;, dimension_buffer, var_ptr-&gt;name_in_file);
+                                                        return 1;
+                                                }
+                                                var_ptr-&gt;ndims++;
+                                        }
+                                        dimension_list = strtok(NULL, &quot; &quot;);
+                                }
+                                dimlist_ptr = var_ptr-&gt;dimlist;
+                                if(var_ptr-&gt;dimlist) var_ptr-&gt;dimlist = var_ptr-&gt;dimlist-&gt;next;
+                                free(dimlist_ptr);
+
+                                var_ptr-&gt;ntime_levs = atoi(structlevs);
+
+                                if(varstreams != NULL){
+                                        snprintf(streams_buffer, 128, &quot;%s&quot;, varstreams);
+                                        if(strchr(streams_buffer, (int)'i')) var_ptr-&gt;iostreams |= INPUT0;
+                                        if(strchr(streams_buffer, (int)'s')) var_ptr-&gt;iostreams |= SFC0;
+                                        if(strchr(streams_buffer, (int)'r')) var_ptr-&gt;iostreams |= RESTART0;
+                                        if(strchr(streams_buffer, (int)'o')) var_ptr-&gt;iostreams |= OUTPUT0;
+                                }
+
+                                if(varname_in_code == NULL){
+                                        snprintf(var_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, varname);
+                                } else {
+                                        snprintf(var_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, varname_in_code);
+                                }
+
+                                snprintf(var_ptr-&gt;super_array, 1024, &quot;%s&quot;, vararrname);
+                                snprintf(var_ptr-&gt;array_class, 1024, &quot;%s&quot;, vararrgroup);
+
+                                NEW_VARIABLE(var_ptr-&gt;next);
+                                var_ptr2 = var_ptr;
+                                var_ptr = var_ptr-&gt;next;
+                        }
+                }
+
+                for(var_xml = ezxml_child(structs_xml, &quot;var&quot;); var_xml; var_xml = var_xml-&gt;next){
+                        varname = ezxml_attr(var_xml, &quot;name&quot;);
+                        varpersistence = ezxml_attr(var_xml, &quot;persistence&quot;);
+                        vartype = ezxml_attr(var_xml, &quot;type&quot;);
+                        vardims = ezxml_attr(var_xml, &quot;dimensions&quot;);
+                        varunits = ezxml_attr(var_xml, &quot;units&quot;);
+                        vardesc = ezxml_attr(var_xml, &quot;description&quot;);
+                        varstreams = ezxml_attr(var_xml, &quot;streams&quot;);
+                        varname_in_code = ezxml_attr(var_xml, &quot;name_in_code&quot;);
+
+                        if(vlist_cursor == NULL){
+                                NEW_VARIABLE_LIST(grouplist_ptr-&gt;vlist);
+                                vlist_cursor = grouplist_ptr-&gt;vlist;
+                        } else {
+                                NEW_VARIABLE_LIST(vlist_cursor-&gt;next);
+                                vlist_cursor-&gt;next-&gt;prev = vlist_cursor;
+                                vlist_cursor = vlist_cursor-&gt;next;
+                        }
+                        vlist_cursor-&gt;var = var_ptr;
+                        vlist_cursor-&gt;next = NULL;
+
+                        var_ptr-&gt;ndims = 0;
+                        var_ptr-&gt;timedim = 0;
+                        var_ptr-&gt;iostreams = 0;
+
+                        snprintf(var_ptr-&gt;name_in_file, 1024, &quot;%s&quot;, varname);
+
+                        if(varpersistence == NULL){
+                                var_ptr-&gt;persistence = PERSISTENT;
+                        } else {
+                                if(strncmp(varpersistence, &quot;persistent&quot;, 1024) == 0){
+                                        var_ptr-&gt;persistence = PERSISTENT;
+                                } else if(strncmp(varpersistence, &quot;scratch&quot;, 1024) == 0){
+                                        var_ptr-&gt;persistence = SCRATCH;
+                                }
+                        }
+
+                        if(strncmp(vartype, &quot;real&quot;, 1024) == 0){
+                                var_ptr-&gt;vtype = REAL;
+                        } else if(strncmp(vartype, &quot;integer&quot;, 1024) == 0){
+                                var_ptr-&gt;vtype = INTEGER;
+                        } else if(strncmp(vartype, &quot;logical&quot;, 1024) == 0){
+                                var_ptr-&gt;vtype = LOGICAL;
+                        } else if(strncmp(vartype, &quot;text&quot;, 1024) == 0){
+                                var_ptr-&gt;vtype = CHARACTER;
+                        }
+
+                        NEW_DIMENSION_LIST(dimlist_ptr)
+                        var_ptr-&gt;dimlist = dimlist_ptr;
+
+                        snprintf(dimensions, 2048, &quot;%s&quot;, vardims);
+                        dimension_list = strtok(dimensions, &quot; &quot;);
+                        while(dimension_list != NULL){
+                                snprintf(dimension_buffer, 128, &quot;%s&quot;, dimension_list);
+                                if(strncmp(dimension_buffer, &quot;Time&quot;, 1024) == 0){
+                                        var_ptr-&gt;timedim = 1;
+                                } else {
+                                        NEW_DIMENSION_LIST(dimlist_ptr-&gt;next)
+                                        dimlist_ptr-&gt;next-&gt;prev = dimlist_ptr;
+                                        dimlist_ptr = dimlist_ptr-&gt;next;
+
+                                        dimlist_cursor = (*dims);
+                                        while(dimlist_cursor &amp;&amp; (strncmp(dimension_buffer, dimlist_cursor-&gt;name_in_file, 1024) != 0) )
+                                                dimlist_cursor = dimlist_cursor-&gt;next;
+                                        if (dimlist_cursor) {
+                                                dimlist_ptr-&gt;dim = dimlist_cursor;
+                                        } else {
+                                                fprintf(stderr, &quot;Error: Unknown dimension %s for variable %s</font>
<font color="gray">&quot;, dimension_buffer, var_ptr-&gt;name_in_file);
+                                                return 1;
+                                        }
+                                        var_ptr-&gt;ndims++;
+                                }
+                                dimension_list = strtok(NULL, &quot; &quot;);
+                        }
+
+                        dimlist_ptr = var_ptr-&gt;dimlist;
+                        if(var_ptr-&gt;dimlist) var_ptr-&gt;dimlist = var_ptr-&gt;dimlist-&gt;next;
+                        free(dimlist_ptr);
+
+                        var_ptr-&gt;ntime_levs = atoi(structlevs);
+
+                        if(varstreams != NULL){
+                                snprintf(streams_buffer, 128, &quot;%s&quot;, varstreams);
+                                if(strchr(streams_buffer, (int)'i')) {
+                                        var_ptr-&gt;iostreams |= INPUT0;
+                                }
+                                if(strchr(streams_buffer, (int)'s')) {
+                                        var_ptr-&gt;iostreams |= SFC0;
+                                }
+                                if(strchr(streams_buffer, (int)'r')) {
+                                        var_ptr-&gt;iostreams |= RESTART0;
+                                }
+                                if(strchr(streams_buffer, (int)'o')) {
+                                        var_ptr-&gt;iostreams |= OUTPUT0;
+                                }
+                        }
+
+                        if(varname_in_code == NULL){
+                                snprintf(var_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, varname);
+                        } else {
+                                snprintf(var_ptr-&gt;name_in_code, 1024, &quot;%s&quot;, varname_in_code);
+                        }
+
+                        snprintf(var_ptr-&gt;super_array, 1024, &quot;-&quot;);
+                        snprintf(var_ptr-&gt;array_class, 1024, &quot;-&quot;);
+
+                        NEW_VARIABLE(var_ptr-&gt;next);
+                        var_ptr2 = var_ptr;
+                        var_ptr = var_ptr-&gt;next;
+                }
+        }
+
+        if(var_ptr2-&gt;next) free(var_ptr2-&gt;next);
+        var_ptr2-&gt;next = NULL;
+
+        grouplist_ptr = *groups;
+        if ((*groups)-&gt;next) *groups = (*groups)-&gt;next;
+        if (grouplist_ptr) free(grouplist_ptr);
+
+        return 0;
+}
+
+
 int parse_reg(FILE * regfile, struct namelist ** nls, struct dimension ** dims, struct variable ** vars, struct group_list ** groups)
 {
    char word[1024];
@@ -228,7 +620,6 @@
             vlist_cursor-&gt;var = var_ptr;
          }
 
-
          getword(regfile, var_ptr-&gt;super_array);
          getword(regfile, var_ptr-&gt;array_class);
 
@@ -402,7 +793,7 @@
          memcpy(super_array, var_ptr-&gt;var-&gt;super_array, 1024);
          var_ptr2_prev = var_ptr;
          var_ptr2 = var_ptr-&gt;next;
-         if (var_ptr2 &amp;&amp; strncmp(super_array, var_ptr2-&gt;var-&gt;super_array, 1024) != 0) {
+         if (var_ptr2 != NULL &amp;&amp; strncmp(super_array, var_ptr2-&gt;var-&gt;super_array, 1024) != 0) {
             while (var_ptr2) {
                if (strncmp(super_array, var_ptr2-&gt;var-&gt;super_array, 1024) == 0) {
                   var_ptr2_prev-&gt;next = var_ptr2-&gt;next;

</font>
</pre>