You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by ji...@apache.org on 2021/03/30 15:15:16 UTC

[daffodil] branch runtime2-2202 updated (6f01c57 -> b547722)

This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a change to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git.


 discard 6f01c57  Support booleans, arrays of complex types, fixed values, fill bytes
    omit bb73837  Support choices in runtime2 code generator with restrictions
    omit c01af12  Support arrays, real numbers, and improve TDML processing
    omit 300f64a  Test all integer sizes, signs, and byte orders
    omit 75e2e88  Expand C code generator to handle more integer types
    omit 401ac33  Reorganize C source files
    omit 0677a75  WIP: Add runtime2 backend with C code generator
     add d65af5b  Schematron implementation of the Validator API
     add 7867d8e  Add validation support for tunables
     add 09d46dc  Fixes sonarcloud duplication error
     add e9d2407  Improve newVariableInstace defaultValue expressions
     add fbefd3a  Enabled non-constant expressions in defineVariable
     add 1fd854e  Add JIRA ticket reference to test
     add fb73683  Fix abort when viewing prefixed length elements in the debugger
     add f5eccdb  Add tests confirming round-trip behavior of date/times
     add 9da6568  Add support for displaying variables in the debugger
     add 40c8b79  Fix how we throw away buckets during parsing
     add 1ac990c  Add test that shows DAFFODIL-2456 doesn't happen.
     add b896c31  SAX API Refactoring
     add c2357f5  Add test verifying we warn when dfdl:length property is ignored
     add 583a91d  Support embedding Schematron rules in DFDL schemas.
     add ed870f2  Removed test looking for compile time check.
     add 0be304d  fix random failures of cli parsing on windows by using getBefore to get the ec string
     add 0c6d14f  Enable 3 tests showing apostrophes work properly now in TDML
     add cda1eab  Added println so proper operation of UpdateEclipseClasspaths is visible.
     add 94e57c4  Confirm behavior when compiling schemas without global elements
     add 92a7901  Replace updateEclipseClasspaths with sbt eclipse plugin settings
     add e29292b  Update debugger support of found delimiters/fields/diffs
     add 4674dee  Bump copyright year to 2021
     add 0a390f6  Allow garbage collection of UStateForSuspension's and DirectOrBufferedDataOutputStream's
     add 8d5dbed  Updates to make top level project
     add 5177fed  Add .asf.yaml file to configure ASF gitbox/github
     add 66c272b  Add debugger "info suspensions" and "set diffExcludes" commands
     add 6c3a89f  Patterns to match strings with newlines.
     add f1603a0  Implement variable direction property
     add 040927b  Update jackson-core to 2.11.4
     add 043acaa  Update Jackson JSON dependency in bin.LICENSE and bin.NOTICE
     add d183cb2  Update woodstox-core to 6.2.4
     add 368f4a5  Update icu4j to 68.2
     add 7717c20  Update jackson-core to 2.12.2
     add b3eccbc  Update typesafe:config to 1.4.1
     add eeb24c7  Update sbt-native-packager to 1.7.6
     add a262b58  Update junit to 4.13.2
     add 995e7a4  Update sbt-native-packager to 1.8.1
     add bda861a  Update genjavadoc-plugin to 0.17
     add 9a40a1f  Update xercesImpl to 2.12.1
     add fb60b69  Update scalacheck to 1.15.3
     add 420f882  Update scallop to 4.0.2
     add 046fb8a  Update jansi to 1.18
     add 1099c3d  Update Saxon-HE to 9.9.1-8
     add 6aa4108  Update Saxon-HE to 10.3
     add 78bcc3b  Add tests for DAF-2486 discr and DAF-2487 hang bugs
     add 5289f59  Fix hang caused by a zero-length first separated infix element
     add 5032694  Improve detection of disallowed entities in property values
     new 8a2c1f4  WIP: Add runtime2 backend with C code generator
     new daa4f46  Reorganize C source files
     new 3f96471  Expand C code generator to handle more integer types
     new be9cf97  Test all integer sizes, signs, and byte orders
     new 1061804  Support arrays, real numbers, and improve TDML processing
     new 80a9570  Support choices in runtime2 code generator with restrictions
     new 48858f8  Support booleans, arrays of complex types, fixed values, fill bytes
     new 57b3c89  Fix compilation errors after rebase
     new b547722  Fix test failures after rebase

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (6f01c57)
            \
             N -- N -- N   refs/heads/runtime2-2202 (b547722)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .codecov.yml => .asf.yaml                          |   23 +-
 .github/workflows/main.yml                         |   21 +-
 .github/workflows/sonarcloud.yml                   |   30 +-
 DISCLAIMER                                         |    7 -
 KEYS                                               |    2 +-
 LICENSE                                            |   61 +-
 NOTICE                                             |    2 +-
 README.md                                          |   37 +-
 build.sbt                                          |   93 +-
 .../release-candidate/daffodil-release-candidate   |   14 +-
 daffodil-cli/README.md                             |   44 +-
 daffodil-cli/bin.LICENSE                           |  634 +++++-
 daffodil-cli/bin.NOTICE                            |   36 +-
 daffodil-cli/build.sbt                             |   56 +-
 .../org/apache/daffodil/CLI/input/input1.txt.xml   |   13 +-
 .../input9.txt.xml}                                |   22 +-
 .../org/apache/daffodil/CLI/input/prefix.txt       |    1 +
 .../org/apache/daffodil/CLI/input/uuid.txt         |    1 +
 .../apache/daffodil/CLI/prefixed_length.dfdl.xsd   |   26 +-
 .../it/scala/org/apache/daffodil/CLI/Util.scala    |    8 +
 .../apache/daffodil/debugger/TestCLIDebugger.scala |  281 ++-
 .../daffodil/generating/TestCLIGenerateC.scala     |   42 +-
 .../apache/daffodil/parsing/TestCLIParsing.scala   |   24 +-
 .../apache/daffodil/schematron/TestEmbedded.scala  |  107 +
 .../daffodil/schematron/TestValidating.scala       |   44 +
 .../org/apache/daffodil/schematron/package.scala   |  144 ++
 .../daffodil/unparsing/TestCLIUnparsing.scala      |    2 +-
 daffodil-cli/src/main/resources/META-INF/NOTICE    |    2 +-
 .../src/main/scala/org/apache/daffodil/Main.scala  |  231 +-
 .../src/windows/DisclaimerDlg_Daffodil.wxs         |   38 -
 daffodil-cli/src/windows/Product_en-us.wxl         |    6 -
 daffodil-cli/src/windows/WixUI_Daffodil.wxs        |   11 +-
 daffodil-cli/src/windows/apache-daffodil.ico       |  Bin 90022 -> 116317 bytes
 daffodil-cli/src/windows/dialog.bmp                |  Bin 615402 -> 615402 bytes
 daffodil-core/src/main/resources/META-INF/NOTICE   |    2 +-
 .../daffodil/dsom/AnnotatedSchemaComponent.scala   |   11 +-
 .../apache/daffodil/dsom/DFDLDefineVariable.scala  |   10 +-
 .../scala/org/apache/daffodil/dsom/Facets.scala    |   12 +-
 .../grammar/primitives/ElementCombinator.scala     |    4 +-
 .../grammar/primitives/PrimitivesExpressions.scala |   48 +-
 .../externalvars/TestExternalVariablesLoader.scala |   12 +-
 .../daffodil/processor/TestSAXParseAPI.scala       |    2 +-
 .../processor/TestSAXParseUnparseAPI.scala         |    2 +-
 .../daffodil/processor/TestSAXUnparseAPI.scala     |   26 +-
 daffodil-io/src/main/resources/META-INF/NOTICE     |    2 +-
 .../scala/org/apache/daffodil/io/InputSource.scala |   12 +-
 daffodil-japi/build.sbt                            |    2 +-
 daffodil-japi/src/main/resources/META-INF/NOTICE   |    2 +-
 .../daffodil/example/ValidatorApiExample.java      |   37 +-
 .../resources/test/japi/alwaysInvalid.dfdl.xsd     |   22 +-
 daffodil-lib/src/main/resources/META-INF/LICENSE   |    6 +-
 daffodil-lib/src/main/resources/META-INF/NOTICE    |    2 +-
 .../org/apache/daffodil/cookers/Cookers.scala      |    2 +-
 .../apache/daffodil/cookers/EntityReplacer.scala   |  136 +-
 .../scala/org/apache/daffodil/util/MStack.scala    |    2 +-
 .../scala/org/apache/daffodil/xml/XMLUtils.scala   |   59 +-
 .../daffodil/xml/test/unit/TestXMLUtils.scala      |    5 +-
 .../org/apache/daffodil/xsd/DFDL_part3_model.xsd   |    1 +
 .../resources/org/apache/daffodil/xsd/dafext.xsd   |  211 +-
 .../resources/org/apache/daffodil/xsd/dfdlx.xsd    |    9 +
 .../apache/daffodil/propGen/TunableGenerator.scala |  103 +-
 .../src/main/resources/META-INF/NOTICE             |    2 +-
 .../processors/unparsers/ElementUnparser.scala     |    4 +-
 .../unparsers/ExpressionEvaluatingUnparsers.scala  |   35 +-
 .../unparsers/SpecifiedLengthUnparsers.scala       |   14 +-
 .../src/main/resources/META-INF/NOTICE             |    2 +-
 .../daffodil/debugger/InteractiveDebugger.scala    |  669 ++++--
 .../org/apache/daffodil/dpath/DPathRuntime.scala   |    3 +-
 .../apache/daffodil/events/ParseEventHandler.scala |    8 +-
 .../org/apache/daffodil/infoset/InfosetImpl.scala  |   14 +
 .../daffodil/infoset/SAXInfosetOutputter.scala     |  115 -
 .../DaffodilParseOutputStreamContentHandler.scala  |  139 ++
 .../processors/DaffodilParseXMLReader.scala        |  209 ++
 .../apache/daffodil/processors/DataProcessor.scala |  204 +-
 .../apache/daffodil/processors/EvDelimiters.scala  |    6 +-
 .../daffodil/processors/ProcessorStateBases.scala  |   33 +-
 .../apache/daffodil/processors/RuntimeData.scala   |   22 +-
 .../daffodil/processors/SuspendableOperation.scala |    2 +-
 .../daffodil/processors/SuspensionTracker.scala    |    2 +
 .../apache/daffodil/processors/VariableMap1.scala  |  314 ++-
 .../processors/parsers/BinaryNumberTraits.scala    |    8 +-
 .../parsers/ExpressionEvaluatingParsers.scala      |    7 +-
 .../daffodil/processors/parsers/PState.scala       |    6 +-
 .../processors/parsers/SequenceParserBases.scala   |   22 +-
 .../daffodil/processors/unparsers/UState.scala     |   57 +-
 .../daffodil/runtime2/TestCodeGenerator.scala      |    9 +-
 daffodil-sapi/root-doc.txt                         |    2 +-
 daffodil-sapi/src/main/resources/META-INF/NOTICE   |    2 +-
 daffodil-schematron/README.md                      |   57 +
 .../src/main/resources/META-INF/LICENSE            |   62 +
 .../src/main/resources/META-INF/NOTICE             |    2 +-
 .../org.apache.daffodil.api.ValidatorFactory       |    2 +-
 .../iso-schematron-xslt2/ExtractSchFromXSD-2.xsl   |  113 +
 .../iso-schematron-xslt2/iso_abstract_expand.xsl   |  313 +++
 .../iso-schematron-xslt2/iso_dsdl_include.xsl      | 1519 +++++++++++++
 .../iso_schematron_message_xslt2.xsl               |   64 +
 .../iso_schematron_skeleton_for_saxon.xsl          | 2306 ++++++++++++++++++++
 .../iso-schematron-xslt2/iso_svrl_for_xslt2.xsl    |  692 ++++++
 .../iso-schematron-xslt2/sch-messages-en.xhtml     |   85 +
 .../schematron/ClassPathUriResolver.scala          |   53 +
 .../validation/schematron/Schematron.scala         |   81 +
 .../schematron/SchematronValidator.scala           |   43 +-
 .../schematron/SchematronValidatorFactory.scala    |   60 +
 .../validation/schematron/Transforms.scala         |   59 +
 .../test/resources/custom-resolver/title-rules.sch |   20 +-
 .../src/test/resources/sch/always-fails.sch        |   24 +-
 .../src/test/resources/sch/never-fails.sch         |   24 +-
 .../src/test/resources/sch/schematron-1.sch        |   24 +-
 .../src/test/resources/sch/schematron-2.sch        |   37 +
 .../src/test/resources/sch/schematron-3.sch        |   37 +
 .../src/test/resources/xml/article-1.xml           |   33 +
 .../src/test/resources/xml/article-2.xml           |   32 +
 .../src/test/resources/xml/article-3.xml           |   33 +
 .../src/test/resources/xml/embedded-1.xml          |    6 +-
 .../src/test/resources/xsd/always-fails-1.dfdl.xsd |   51 +-
 .../src/test/resources/xsd/embedded-1.dfdl.xsd     |   50 +
 .../src/test/resources/xsd/embedded-2.dfdl.xsd     |   57 +
 .../src/test/resources/xsd/embedded-3.dfdl.xsd     |   91 +
 .../src/test/resources/xsd/extends-1.dfdl.xsd      |   59 +
 .../src/test/resources/xsd/never-fails-1.dfdl.xsd  |   52 +-
 .../src/test/resources/xsd/string.dfdl.xsd         |   21 +-
 .../src/test/resources/xsd/unit_price.dfdl.xsd     |   85 +
 .../src/test/resources/xsd/uuid.dfdl.xsd           |   39 +
 .../src/test/resources/xsd/with-ns-1.dfdl.xsd      |   53 +
 .../src/test/resources/xsd/without-ns-1.dfdl.xsd   |   48 +
 .../validation/schematron/EmbeddedTesting.scala    |   90 +
 .../schematron/TestBasicValidation.scala           |   79 +
 .../schematron/TestEmbeddedSchematron.scala        |   73 +
 .../validation/schematron/TestSpiLoading.scala     |   35 +-
 .../validation/schematron/TestUriResolver.scala    |   25 +-
 .../schematron/TestValidatorFactory.scala          |   19 +-
 .../src/main/resources/META-INF/NOTICE             |    2 +-
 .../src/main/resources/META-INF/NOTICE             |    2 +-
 .../tdml/processor/DaffodilTDMLDFDLProcessor.scala |    2 +-
 .../src/test/resources/test/tdml/tdmlQuoting.tdml  |    4 +-
 .../org/apache/daffodil/tdml/TestTDMLRunner2.scala |   22 +-
 .../general/testUnparserFileBuffering.tdml         |   73 +-
 .../MissingAppinfoSourceNonDfdl.dfdl.xsd}          |   23 +-
 .../SchemaDefinitionErrors.tdml                    |   20 +
 .../daffodil/section05/facets/PatternRanges.tdml   |  121 +
 .../section05/simple_types/SimpleTypes.tdml        |  280 ++-
 .../daffodil/section06/entities/Entities.tdml      |    2 +-
 .../daffodil/section06/entities/entities_01.tdml   |    8 +-
 .../section06/namespaces/multi_A_20.dfdl.xsd       |   16 +
 .../section06/namespaces/multi_A_21.dfdl.xsd       |    2 +-
 .../section06/namespaces/multi_base_20.dfdl.xsd    |   18 +-
 .../section06/namespaces/multi_base_21.dfdl.xsd    |    2 +-
 .../daffodil/section06/namespaces/namespaces.tdml  |   25 +-
 .../section07/discriminators/discriminator2.tdml   |  226 ++
 .../daffodil/section07/variables/variables.tdml    |  716 +++++-
 .../DelimiterPropertiesUnparse.tdml                |    6 +-
 .../daffodil/section12/lengthKind/implicit.tdml    |   28 +
 .../section13/nillable/literal-character-nils.tdml |    4 +-
 .../text_number_props/TextNumberProps.tdml         |   18 +-
 .../text_number_props/TextNumberPropsUnparse.tdml  |   10 +-
 .../sequence_groups/SequenceGroupNestedArray.tdml  |  288 +++
 .../section23/dfdl_expressions/expressions.tdml    |   21 -
 .../section00/general/TestFileBuffering.scala      |   48 +-
 .../section00/general/TestUnparserGeneral.scala    |    3 +-
 .../schema_definition_errors/TestSDE.scala         |    1 +
 ...{TestNulChars.scala => TestPatternRanges.scala} |   17 +-
 .../section05/simple_types/TestSimpleTypes.scala   |   11 +
 .../section06/namespaces/TestNamespaces.scala      |    1 +
 .../discriminators/TestDiscriminators.scala        |    8 +
 .../section07/variables/TestVariables.scala        |   23 +
 .../lengthKind/TestLengthKindImplicit.scala        |    1 +
 .../TestSequenceGroupNestedArray.scala             |   24 +-
 .../dfdl_expressions/TestDFDLExpressions.scala     |    2 -
 daffodil-udf/README.md                             |    2 +-
 daffodil-udf/src/main/resources/META-INF/NOTICE    |    2 +-
 project/Dependencies.scala                         |   22 +-
 project/Rat.scala                                  |    2 +
 project/UpdateEclipseClasspaths.scala              |  106 -
 project/plugins.sbt                                |    4 +-
 sonar-project.properties                           |   10 +-
 .../src/main/resources/DFDLTutorialStylesheet.xsl  |   25 +-
 176 files changed, 11780 insertions(+), 1894 deletions(-)
 copy .codecov.yml => .asf.yaml (66%)
 delete mode 100644 DISCLAIMER
 copy daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_1.xml => daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/input1.txt.xml (82%)
 copy daffodil-cli/src/it/resources/org/apache/daffodil/CLI/{global_element_import.dfdl.xsd => input/input9.txt.xml} (67%)
 create mode 100644 daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/prefix.txt
 create mode 100644 daffodil-cli/src/it/resources/org/apache/daffodil/CLI/input/uuid.txt
 copy daffodil-test/src/test/resources/childDir/anotherChildDir/include01_01_03.dfdl.xsd => daffodil-cli/src/it/resources/org/apache/daffodil/CLI/prefixed_length.dfdl.xsd (66%)
 create mode 100644 daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestEmbedded.scala
 create mode 100644 daffodil-cli/src/it/scala/org/apache/daffodil/schematron/TestValidating.scala
 create mode 100644 daffodil-cli/src/it/scala/org/apache/daffodil/schematron/package.scala
 delete mode 100644 daffodil-cli/src/windows/DisclaimerDlg_Daffodil.wxs
 copy daffodil-test/src/test/resources/org/apache/daffodil/section02/schema_definition_errors/MissingClosingTag.dfdl.xsd => daffodil-japi/src/test/resources/test/japi/alwaysInvalid.dfdl.xsd (63%)
 mode change 100644 => 100755 daffodil-lib/src/main/scala/org/apache/daffodil/cookers/EntityReplacer.scala
 create mode 100644 daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilParseOutputStreamContentHandler.scala
 create mode 100644 daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DaffodilParseXMLReader.scala
 create mode 100644 daffodil-schematron/README.md
 copy {daffodil-io => daffodil-schematron}/src/main/resources/META-INF/LICENSE (77%)
 copy {daffodil-io => daffodil-schematron}/src/main/resources/META-INF/NOTICE (89%)
 copy {daffodil-lib => daffodil-schematron}/src/main/resources/META-INF/services/org.apache.daffodil.api.ValidatorFactory (92%)
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/ExtractSchFromXSD-2.xsl
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_abstract_expand.xsl
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_dsdl_include.xsl
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_schematron_message_xslt2.xsl
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_schematron_skeleton_for_saxon.xsl
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/iso_svrl_for_xslt2.xsl
 create mode 100644 daffodil-schematron/src/main/resources/iso-schematron-xslt2/sch-messages-en.xhtml
 create mode 100644 daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/ClassPathUriResolver.scala
 create mode 100644 daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Schematron.scala
 copy daffodil-lib/src/test/scala/org/apache/daffodil/validation/ValidatorSPISupport.scala => daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/SchematronValidator.scala (51%)
 create mode 100644 daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/SchematronValidatorFactory.scala
 create mode 100644 daffodil-schematron/src/main/scala/org/apache/daffodil/validation/schematron/Transforms.scala
 copy daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml => daffodil-schematron/src/test/resources/custom-resolver/title-rules.sch (73%)
 copy daffodil-tdml-lib/src/test/resources/test-suite/ibm-contributed/dpaext1-2.tdml => daffodil-schematron/src/test/resources/sch/always-fails.sch (58%)
 copy daffodil-tdml-lib/src/test/resources/test-suite/ibm-contributed/dpaext1-2.tdml => daffodil-schematron/src/test/resources/sch/never-fails.sch (58%)
 copy daffodil-tdml-lib/src/test/resources/test-suite/ibm-contributed/dpaext1-2.tdml => daffodil-schematron/src/test/resources/sch/schematron-1.sch (55%)
 create mode 100644 daffodil-schematron/src/test/resources/sch/schematron-2.sch
 create mode 100644 daffodil-schematron/src/test/resources/sch/schematron-3.sch
 create mode 100644 daffodil-schematron/src/test/resources/xml/article-1.xml
 create mode 100644 daffodil-schematron/src/test/resources/xml/article-2.xml
 create mode 100644 daffodil-schematron/src/test/resources/xml/article-3.xml
 copy daffodil-tdml-processor/src/test/resources/test/tdml/test.xml => daffodil-schematron/src/test/resources/xml/embedded-1.xml (91%)
 copy test-stdLayout/src/main/resources/org1/xsd/innerEnvelope.dfdl.xsd => daffodil-schematron/src/test/resources/xsd/always-fails-1.dfdl.xsd (50%)
 create mode 100644 daffodil-schematron/src/test/resources/xsd/embedded-1.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/resources/xsd/embedded-2.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/resources/xsd/embedded-3.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/resources/xsd/extends-1.dfdl.xsd
 copy test-stdLayout/src/main/resources/org1/xsd/innerEnvelope.dfdl.xsd => daffodil-schematron/src/test/resources/xsd/never-fails-1.dfdl.xsd (50%)
 copy daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/test03sch1.dfdl.xsd => daffodil-schematron/src/test/resources/xsd/string.dfdl.xsd (65%)
 create mode 100644 daffodil-schematron/src/test/resources/xsd/unit_price.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/resources/xsd/uuid.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/resources/xsd/with-ns-1.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/resources/xsd/without-ns-1.dfdl.xsd
 create mode 100644 daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/EmbeddedTesting.scala
 create mode 100644 daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestBasicValidation.scala
 create mode 100644 daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestEmbeddedSchematron.scala
 copy daffodil-test/src/test/scala/org/apache/daffodil/layers/TestAIS.scala => daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestSpiLoading.scala (55%)
 copy daffodil-lib/src/test/scala/org/apache/daffodil/exceptions/TestExceptions.scala => daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestUriResolver.scala (52%)
 copy daffodil-lib/src/test/scala/org/apache/daffodil/exceptions/TestExceptions.scala => daffodil-schematron/src/test/scala/org/apache/daffodil/validation/schematron/TestValidatorFactory.scala (58%)
 copy daffodil-test/src/test/resources/{childDir/anotherChildDir/include01_01_03.dfdl.xsd => org/apache/daffodil/section02/schema_definition_errors/MissingAppinfoSourceNonDfdl.dfdl.xsd} (69%)
 create mode 100644 daffodil-test/src/test/resources/org/apache/daffodil/section05/facets/PatternRanges.tdml
 create mode 100644 daffodil-test/src/test/resources/org/apache/daffodil/section07/discriminators/discriminator2.tdml
 create mode 100644 daffodil-test/src/test/resources/org/apache/daffodil/section14/sequence_groups/SequenceGroupNestedArray.tdml
 copy daffodil-test/src/test/scala/org/apache/daffodil/section05/facets/{TestNulChars.scala => TestPatternRanges.scala} (69%)
 copy test-stdLayout/src/test/scala/org1/TestOrg1.scala => daffodil-test/src/test/scala/org/apache/daffodil/section14/sequence_groups/TestSequenceGroupNestedArray.scala (59%)
 delete mode 100644 project/UpdateEclipseClasspaths.scala

[daffodil] 03/09: Expand C code generator to handle more integer types

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 3f96471b75412a966257dedac92fc239c33f15e7
Author: John Interrante <in...@research.ge.com>
AuthorDate: Wed Dec 9 17:16:16 2020 -0500

    Expand C code generator to handle more integer types
    
    Add another example schema to runtime2 tests and make C code generator
    able to handle more integer types.  Starting to run into alignment
    issues currently causing different behavior between runtime1 and
    runtime2 and will need to handle these issues later.
    
    In xml_reader.c, rename xmlInt32Elem to xmlIntegerElem and expand it
    to read 8, 16, 32, and 64-bit signed/unsigned integer numbers from XML
    elements.  Have not tested all cases yet.
    
    In xml_writer.c, rename xmlInt32Elem to xmlIntegerElem and expand it
    to write 8, 16, 32, and 64-bit signed/unsigned integers as XML element
    values.  Have not tested all cases yet.
    
    In infoset.c, expand walkInfosetNode to call visitIntegerElem method
    for 8, 16, 32, and 64-bit signed/unsigned integer type codes.
    
    In infoset.h, rename VisitInt32Elem type to VisitIntegerElem and
    visitInteger32Elem field to visitIntegerElem.  Add 8, 16, 32, and
    64-bit signed/unsigned integer type codes to TypeCode.
    
    In ex_int32.c, update to reflect changes to generated code actually
    generated from ex_int32 root element in TestRuntime2.tdml.
    
    In ex_int32.h, update to reflect changes to generated code actually
    generated from ex_int32 root element in TestRuntime2.tdml.
    
    In Runtime2DataProcessor.scala, make parse and unparse methods remove
    temporary directories after using them and make ParseResult convert
    output file to XML immediately instead of waiting until called later
    since output file will no longer be around.
    
    In BinaryIntegerKnownLengthCodeGenerator.scala, remove some
    restrictions from when code generator could handle only 32-bit signed
    integers.  Modify generated code more flexible and capable of handling
    different integer lengths.
    
    In CodeGeneratorState.scala, expand CodeGeneratorState to handle 8,
    16, 32, and 64-bit signed/unsigned integers.  Modify generated code to
    define dummy be8toh and htobe8 functions since <endian.h> doesn't
    define any endian byte-swapping functions for 8-bit integers.
    
    In ElementParseAndUnspecifiedLengthCodeGenerator.scala, allow
    alignment fills to precede elements in order to allow code to be
    generated, although we still need to generate some extra code to
    adjust for alignment fills later.
    
    In TestRuntime2.dfdl.xsd, expand test schema to add another schema
    example coming from somewhere else (an orion_command element using
    8-bit and 16-bit signed/unsigned integers).  This element has
    inadvertently required an alignment fill of 1 byte before the checksum
    field that probably should be removed, but we may need to generate
    code to handle alignment fills anyway.
    
    In TestRuntime2.tdml, rename parse_int32 & unparse_int32 tests to
    ex_int32_parse & ex_int32_unparse and add two new tests
    orion_command_parse & orion_command_unparse.  Specify explicit root
    elements for every test since we have multiple root elements now.
    
    Rename parse_int32 & unparse_int32 data files to ex_int32_parse &
    ex_int32_unparse.  Generated code doesn't expect XML elements to have
    an ex prefix anymore (need to check why) so remove ex prefixes from
    ex_int32_unparse elements.
    
    Add orion_command_parse && orion_command_unparse data files for new
    tests.
    
    In TestRuntime2.scala, call ex_int32 & orion_command tests.
    
    In Rat.scala, exclude renamed & new binary data files from checks.
---
 .../src/main/resources/c/libcli/xml_reader.c       |  52 ++++++++++++++--
 .../src/main/resources/c/libcli/xml_writer.c       |  49 ++++++++++++---
 .../src/main/resources/c/libruntime/infoset.c      |  16 +++--
 .../src/main/resources/c/libruntime/infoset.h      |  16 +++--
 .../src/main/resources/examples/ex_int32.c         |  67 +++++++++++----------
 .../src/main/resources/examples/ex_int32.h         |   4 +-
 .../daffodil/runtime2/Runtime2DataProcessor.scala  |   9 +--
 .../BinaryIntegerKnownLengthCodeGenerator.scala    |  33 +++++-----
 .../runtime2/generators/CodeGeneratorState.scala   |  17 +++++-
 ...entParseAndUnspecifiedLengthCodeGenerator.scala |   4 +-
 .../apache/daffodil/runtime2/TestRuntime2.dfdl.xsd |  66 +++++++++++++++++---
 .../org/apache/daffodil/runtime2/TestRuntime2.tdml |  44 +++++++++++---
 .../runtime2/{parse_int32 => ex_int32_parse}       | Bin
 .../runtime2/{unparse_int32 => ex_int32_unparse}   |  16 ++---
 .../apache/daffodil/runtime2/orion_command_parse   | Bin 0 -> 13 bytes
 .../{unparse_int32 => orion_command_unparse}       |  21 ++++---
 .../apache/daffodil/runtime2/TestRuntime2.scala    |   6 +-
 project/Rat.scala                                  |   3 +-
 18 files changed, 308 insertions(+), 115 deletions(-)

diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
index 34035d3..763c5e3 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
@@ -162,10 +162,10 @@ xmlEndComplex(XMLReader *reader, const InfosetBase *base)
     return NULL;
 }
 
-// Read 32-bit integer value from XML data
+// Read 8, 16, 32, or 64-bit signed/unsigned integer number from XML data
 
 static const char *
-xmlInt32Elem(XMLReader *reader, const ERD *erd, int32_t *location)
+xmlIntegerElem(XMLReader *reader, const ERD *erd, void *intLocation)
 {
     // Consume any newlines or whitespace before the element
     while (mxmlGetType(reader->node) == MXML_OPAQUE)
@@ -184,10 +184,50 @@ xmlInt32Elem(XMLReader *reader, const ERD *erd, int32_t *location)
     {
         if (strcmp(name_from_xml, name_from_erd) == 0)
         {
-            // Check for any errors getting the 32-bit integer
+            // Check for any errors getting the integer number
             const char *errstr = NULL;
-            *location = (int32_t)strtonum(number_from_xml, INT32_MIN, INT32_MAX,
-                                          &errstr);
+
+            // Need to handle varying bit lengths and signedness
+            const enum TypeCode typeCode = erd->typeCode;
+            switch (typeCode)
+            {
+            case PRIMITIVE_UINT64:
+                *(uint64_t *)intLocation =
+                    (uint64_t)strtonum(number_from_xml, 0, UINT64_MAX, &errstr);
+                break;
+            case PRIMITIVE_UINT32:
+                *(uint32_t *)intLocation =
+                    (uint32_t)strtonum(number_from_xml, 0, UINT32_MAX, &errstr);
+                break;
+            case PRIMITIVE_UINT16:
+                *(uint16_t *)intLocation =
+                    (uint16_t)strtonum(number_from_xml, 0, UINT16_MAX, &errstr);
+                break;
+            case PRIMITIVE_UINT8:
+                *(uint8_t *)intLocation =
+                    (uint8_t)strtonum(number_from_xml, 0, UINT8_MAX, &errstr);
+                break;
+            case PRIMITIVE_INT64:
+                *(int64_t *)intLocation = (int64_t)strtonum(
+                    number_from_xml, INT64_MIN, INT64_MAX, &errstr);
+                break;
+            case PRIMITIVE_INT32:
+                *(int32_t *)intLocation = (int32_t)strtonum(
+                    number_from_xml, INT32_MIN, INT32_MAX, &errstr);
+                break;
+            case PRIMITIVE_INT16:
+                *(int16_t *)intLocation = (int16_t)strtonum(
+                    number_from_xml, INT16_MIN, INT16_MAX, &errstr);
+                break;
+            case PRIMITIVE_INT8:
+                *(int8_t *)intLocation = (int8_t)strtonum(
+                    number_from_xml, INT8_MIN, INT8_MAX, &errstr);
+                break;
+            default:
+                errstr = "Unexpected ERD typeCode while reading integer from XML data";
+                break;
+            }
+
             return errstr;
         }
         else
@@ -206,5 +246,5 @@ xmlInt32Elem(XMLReader *reader, const ERD *erd, int32_t *location)
 const VisitEventHandler xmlReaderMethods = {
     (VisitStartDocument)&xmlStartDocument, (VisitEndDocument)&xmlEndDocument,
     (VisitStartComplex)&xmlStartComplex,   (VisitEndComplex)&xmlEndComplex,
-    (VisitInt32Elem)&xmlInt32Elem,
+    (VisitIntegerElem)&xmlIntegerElem,
 };
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
index 2db0ce4..791968b 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
@@ -90,23 +90,58 @@ xmlEndComplex(XMLWriter *writer, const InfosetBase *base)
     return complex ? NULL : "Underflowed the XML stack";
 }
 
-// Write 32-bit integer value as element
+// Write 8, 16, 32, or 64-bit signed/unsigned integer as element
 
 static const char *
-xmlInt32Elem(XMLWriter *writer, const ERD *erd, const int32_t *location)
+xmlIntegerElem(XMLWriter *writer, const ERD *erd, const void *intLocation)
 {
     mxml_node_t *parent = stack_top(&writer->stack);
     const char * name = get_erd_name(erd);
-    const char * xmlns = get_erd_xmlns(erd);
     mxml_node_t *simple = mxmlNewElement(parent, name);
-    int32_t      value = *location;
-    mxml_node_t *text = mxmlNewOpaquef(simple, "%i", value);
+
+    // Set namespace declaration if necessary
+    const char *xmlns = get_erd_xmlns(erd);
     if (xmlns)
     {
         const char *ns = get_erd_ns(erd);
         mxmlElementSetAttr(simple, xmlns, ns);
     }
-    return (simple && text) ? NULL : "Error making new int32 simple element";
+
+    // Need to handle varying bit lengths and signedness
+    const enum TypeCode typeCode = erd->typeCode;
+    mxml_node_t *       text = NULL;
+    switch (typeCode)
+    {
+    case PRIMITIVE_UINT64:
+        text = mxmlNewOpaquef(simple, "%lu", *(const uint64_t *)intLocation);
+        break;
+    case PRIMITIVE_UINT32:
+        text = mxmlNewOpaquef(simple, "%u", *(const uint32_t *)intLocation);
+        break;
+    case PRIMITIVE_UINT16:
+        text = mxmlNewOpaquef(simple, "%hu", *(const uint16_t *)intLocation);
+        break;
+    case PRIMITIVE_UINT8:
+        text = mxmlNewOpaquef(simple, "%hhu", *(const uint8_t *)intLocation);
+        break;
+    case PRIMITIVE_INT64:
+        text = mxmlNewOpaquef(simple, "%li", *(const int64_t *)intLocation);
+        break;
+    case PRIMITIVE_INT32:
+        text = mxmlNewOpaquef(simple, "%i", *(const int32_t *)intLocation);
+        break;
+    case PRIMITIVE_INT16:
+        text = mxmlNewOpaquef(simple, "%hi", *(const int16_t *)intLocation);
+        break;
+    case PRIMITIVE_INT8:
+        text = mxmlNewOpaquef(simple, "%hhi", *(const int8_t *)intLocation);
+        break;
+    default:
+        // Let text remain NULL and report error below
+        break;
+    }
+
+    return (simple && text) ? NULL : "Error making new simple integer element";
 }
 
 // Initialize a struct with our visitor event handler methods
@@ -114,5 +149,5 @@ xmlInt32Elem(XMLWriter *writer, const ERD *erd, const int32_t *location)
 const VisitEventHandler xmlWriterMethods = {
     (VisitStartDocument)&xmlStartDocument, (VisitEndDocument)&xmlEndDocument,
     (VisitStartComplex)&xmlStartComplex,   (VisitEndComplex)&xmlEndComplex,
-    (VisitInt32Elem)&xmlInt32Elem,
+    (VisitIntegerElem)&xmlIntegerElem,
 };
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
index f0c8bff..b30f92e 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
@@ -136,18 +136,26 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
         // We use only one of these variables below depending on typeCode
         const InfosetBase *childNode =
             (const InfosetBase *)((const char *)infoNode + offset);
-        const int32_t *intLocation =
-            (const int32_t *)((const char *)infoNode + offset);
+        const void *intLocation =
+            (const void *)((const char *)infoNode + offset);
 
         // Need to handle more element types
-        enum TypeCode typeCode = childERD->typeCode;
+        const enum TypeCode typeCode = childERD->typeCode;
         switch (typeCode)
         {
         case COMPLEX:
             error_msg = walkInfosetNode(handler, childNode);
             break;
+        case PRIMITIVE_UINT64:
+        case PRIMITIVE_UINT32:
+        case PRIMITIVE_UINT16:
+        case PRIMITIVE_UINT8:
+        case PRIMITIVE_INT64:
         case PRIMITIVE_INT32:
-            error_msg = handler->visitInt32Elem(handler, childERD, intLocation);
+        case PRIMITIVE_INT16:
+        case PRIMITIVE_INT8:
+            error_msg =
+                handler->visitIntegerElem(handler, childERD, intLocation);
             break;
         }
     }
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
index 459557c..523a0d6 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
@@ -48,8 +48,9 @@ typedef const char *(*VisitStartComplex)(const VisitEventHandler *handler,
                                          const InfosetBase *      base);
 typedef const char *(*VisitEndComplex)(const VisitEventHandler *handler,
                                        const InfosetBase *      base);
-typedef const char *(*VisitInt32Elem)(const VisitEventHandler *handler,
-                                      const ERD *erd, const int32_t *location);
+typedef const char *(*VisitIntegerElem)(const VisitEventHandler *handler,
+                                        const ERD *              erd,
+                                        const void *             intLocation);
 
 // NamedQName - name of an infoset element
 
@@ -65,7 +66,14 @@ typedef struct NamedQName
 enum TypeCode
 {
     COMPLEX,
-    PRIMITIVE_INT32
+    PRIMITIVE_UINT64,
+    PRIMITIVE_UINT32,
+    PRIMITIVE_UINT16,
+    PRIMITIVE_UINT8,
+    PRIMITIVE_INT64,
+    PRIMITIVE_INT32,
+    PRIMITIVE_INT16,
+    PRIMITIVE_INT8
 };
 
 // ERD - element runtime data needed to parse/unparse objects
@@ -112,7 +120,7 @@ typedef struct VisitEventHandler
     const VisitEndDocument   visitEndDocument;
     const VisitStartComplex  visitStartComplex;
     const VisitEndComplex    visitEndComplex;
-    const VisitInt32Elem     visitInt32Elem;
+    const VisitIntegerElem   visitIntegerElem;
 } VisitEventHandler;
 
 // get_erd_name, get_erd_xmlns, get_erd_ns - get name and xmlns
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_int32.c b/daffodil-runtime2/src/main/resources/examples/ex_int32.c
index d2b9217..5e38ae0 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_int32.c
+++ b/daffodil-runtime2/src/main/resources/examples/ex_int32.c
@@ -25,15 +25,15 @@
 static void        c2_initSelf(c2 *instance);
 static const char *c2_parseSelf(c2 *instance, const PState *pstate);
 static const char *c2_unparseSelf(const c2 *instance, const UState *ustate);
-static void        c1_initSelf(c1 *instance);
-static const char *c1_parseSelf(c1 *instance, const PState *pstate);
-static const char *c1_unparseSelf(const c1 *instance, const UState *ustate);
+static void        ex_int32_initSelf(ex_int32 *instance);
+static const char *ex_int32_parseSelf(ex_int32 *instance, const PState *pstate);
+static const char *ex_int32_unparseSelf(const ex_int32 *instance, const UState *ustate);
 
 // Metadata singletons
 
 static const ERD e1_ERD = {
     {
-        "ex", // namedQName.prefix
+        NULL, // namedQName.prefix
         "e1", // namedQName.local
         NULL, // namedQName.ns
     },
@@ -48,7 +48,7 @@ static const ERD e1_ERD = {
 
 static const ERD e2_ERD = {
     {
-        "ex", // namedQName.prefix
+        NULL, // namedQName.prefix
         "e2", // namedQName.local
         NULL, // namedQName.ns
     },
@@ -63,7 +63,7 @@ static const ERD e2_ERD = {
 
 static const ERD e3_ERD = {
     {
-        "ex", // namedQName.prefix
+        NULL, // namedQName.prefix
         "e3", // namedQName.local
         NULL, // namedQName.ns
     },
@@ -86,7 +86,7 @@ static const ERD *c2_childrenERDs[2] = {&e2_ERD, &e3_ERD};
 
 static const ERD c2_ERD = {
     {
-        "ex", // namedQName.prefix
+        NULL, // namedQName.prefix
         "c2", // namedQName.local
         NULL, // namedQName.ns
     },
@@ -99,27 +99,27 @@ static const ERD c2_ERD = {
     (ERDUnparseSelf)&c2_unparseSelf, // unparseSelf
 };
 
-static const c1 c1_compute_ERD_offsets;
+static const ex_int32 ex_int32_compute_ERD_offsets;
 
-static const ptrdiff_t c1_offsets[2] = {
-    (char *)&c1_compute_ERD_offsets.e1 - (char *)&c1_compute_ERD_offsets,
-    (char *)&c1_compute_ERD_offsets.c2 - (char *)&c1_compute_ERD_offsets};
+static const ptrdiff_t ex_int32_offsets[2] = {
+    (char *)&ex_int32_compute_ERD_offsets.e1 - (char *)&ex_int32_compute_ERD_offsets,
+    (char *)&ex_int32_compute_ERD_offsets.c2 - (char *)&ex_int32_compute_ERD_offsets};
 
-static const ERD *c1_childrenERDs[2] = {&e1_ERD, &c2_ERD};
+static const ERD *ex_int32_childrenERDs[2] = {&e1_ERD, &c2_ERD};
 
-static const ERD c1_ERD = {
+static const ERD ex_int32_ERD = {
     {
-        "ex",                 // namedQName.prefix
-        "c1",                 // namedQName.local
+        NULL, // namedQName.prefix
+        "ex_int32", // namedQName.local
         "http://example.com", // namedQName.ns
     },
     COMPLEX,                         // typeCode
     2,                               // numChildren
-    c1_offsets,                      // offsets
-    c1_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&c1_initSelf,       // initSelf
-    (ERDParseSelf)&c1_parseSelf,     // parseSelf
-    (ERDUnparseSelf)&c1_unparseSelf, // unparseSelf
+    ex_int32_offsets,                      // offsets
+    ex_int32_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&ex_int32_initSelf,       // initSelf
+    (ERDParseSelf)&ex_int32_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&ex_int32_unparseSelf, // unparseSelf
 };
 
 // Return a root element to be used for parsing or unparsing
@@ -127,14 +127,17 @@ static const ERD c1_ERD = {
 InfosetBase *
 rootElement()
 {
-    static c1    instance;
+    static ex_int32    instance;
     InfosetBase *root = &instance._base;
-    c1_ERD.initSelf(root);
+    ex_int32_ERD.initSelf(root);
     return root;
 }
 
 // Methods to initialize, parse, and unparse infoset nodes
 
+static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
+static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
+
 static void
 c2_initSelf(c2 *instance)
 {
@@ -149,7 +152,7 @@ c2_parseSelf(c2 *instance, const PState *pstate)
     const char *error_msg = NULL;
     if (!error_msg)
     {
-        char   buffer[4];
+        char   buffer[sizeof(uint32_t)];
         size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
         if (count < sizeof(buffer))
         {
@@ -159,7 +162,7 @@ c2_parseSelf(c2 *instance, const PState *pstate)
     }
     if (!error_msg)
     {
-        char   buffer[4];
+        char   buffer[sizeof(uint32_t)];
         size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
         if (count < sizeof(buffer))
         {
@@ -178,7 +181,7 @@ c2_unparseSelf(const c2 *instance, const UState *ustate)
     {
         union
         {
-            char     c_val[4];
+            char     c_val[sizeof(uint32_t)];
             uint32_t i_val;
         } buffer;
         buffer.i_val = htobe32(instance->e2);
@@ -192,7 +195,7 @@ c2_unparseSelf(const c2 *instance, const UState *ustate)
     {
         union
         {
-            char     c_val[4];
+            char     c_val[sizeof(uint32_t)];
             uint32_t i_val;
         } buffer;
         buffer.i_val = htobe32(instance->e3);
@@ -206,20 +209,20 @@ c2_unparseSelf(const c2 *instance, const UState *ustate)
 }
 
 static void
-c1_initSelf(c1 *instance)
+ex_int32_initSelf(ex_int32 *instance)
 {
     instance->e1 = 0xCDCDCDCD;
     c2_initSelf(&instance->c2);
-    instance->_base.erd = &c1_ERD;
+    instance->_base.erd = &ex_int32_ERD;
 }
 
 static const char *
-c1_parseSelf(c1 *instance, const PState *pstate)
+ex_int32_parseSelf(ex_int32 *instance, const PState *pstate)
 {
     const char *error_msg = NULL;
     if (!error_msg)
     {
-        char   buffer[4];
+        char   buffer[sizeof(uint32_t)];
         size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
         if (count < sizeof(buffer))
         {
@@ -235,14 +238,14 @@ c1_parseSelf(c1 *instance, const PState *pstate)
 }
 
 static const char *
-c1_unparseSelf(const c1 *instance, const UState *ustate)
+ex_int32_unparseSelf(const ex_int32 *instance, const UState *ustate)
 {
     const char *error_msg = NULL;
     if (!error_msg)
     {
         union
         {
-            char     c_val[4];
+            char     c_val[sizeof(uint32_t)];
             uint32_t i_val;
         } buffer;
         buffer.i_val = htobe32(instance->e1);
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_int32.h b/daffodil-runtime2/src/main/resources/examples/ex_int32.h
index affd8b4..b46c30c 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_int32.h
+++ b/daffodil-runtime2/src/main/resources/examples/ex_int32.h
@@ -30,11 +30,11 @@ typedef struct c2
     int32_t     e3;
 } c2;
 
-typedef struct c1
+typedef struct ex_int32
 {
     InfosetBase _base;
     int32_t     e1;
     c2          c2;
-} c1;
+} ex_int32;
 
 #endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala
index 7dd8f68..9e47349 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala
@@ -108,6 +108,8 @@ class Runtime2DataProcessor(executableFile: os.Path) extends DFDL.DataProcessorB
         val parseResult = new ParseResult(outfile, Failure(parseError))
         parseResult.addDiagnostic(parseError)
         parseResult
+    } finally {
+      os.remove.all(tempDir)
     }
   }
 
@@ -145,6 +147,8 @@ class Runtime2DataProcessor(executableFile: os.Path) extends DFDL.DataProcessorB
         val unparseResult = new UnparseResult(finalBitPos0b, Failure(unparseError))
         unparseResult.addDiagnostic(unparseError)
         unparseResult
+    } finally {
+      os.remove.all(tempDir)
     }
   }
 }
@@ -178,10 +182,7 @@ final class ParseResult(outfile: os.Path,
 
   override def currentLocation: DataLocation = loc
 
-  def infosetAsXML : scala.xml.Elem = {
-    val xml = scala.xml.XML.loadFile(outfile.toIO)
-    xml
-  }
+  val infosetAsXML : scala.xml.Elem = scala.xml.XML.loadFile(outfile.toIO)
 }
 
 final class UnparseResult(val finalBitPos0b: Long,
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
index e1c399d..2936ea6 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
@@ -23,6 +23,8 @@ import org.apache.daffodil.schema.annotation.props.gen.{ BitOrder, ByteOrder }
 trait BinaryIntegerKnownLengthCodeGenerator {
 
   def binaryIntegerKnownLengthGenerateCode(g: BinaryIntegerKnownLength, cgState: CodeGeneratorState): Unit = {
+    // For the time being this is a very limited back end.
+    // So there are numerous restrictions to enforce.
     val e = g.e
     val fieldName = e.namedQName.local
     val lengthInBits: Long = {
@@ -36,50 +38,47 @@ trait BinaryIntegerKnownLengthCodeGenerator {
       val bo = e.byteOrderEv.constValue
       bo
     }
-    // For the time being this is a very limited back end.
-    // So there are numerous restrictions to enforce.
-    e.schemaDefinitionUnless(lengthInBits <= 64, "Length must be 64 bits or less, but was: %s", lengthInBits)
-    if (lengthInBits == 64 && !g.signed)
-      e.SDE("Integers of 64 bits length must be signed.")
 
     // This insures we can use regular java.io library calls.
     if (e.alignmentValueInBits.intValue() % 8 != 0)
       e.SDE("Only alignment to 8-bit (1 byte) boundaries is supported.")
 
     // The restrictions below are ones we want to eventually lift.
-    if (lengthInBits != 32)
-      e.SDE("Lengths other than 32 bits are not supported.")
-
     if (byteOrder ne ByteOrder.BigEndian)
       e.SDE("Only dfdl:byteOrder 'bigEndian' is supported.")
 
     if (e.bitOrder ne BitOrder.MostSignificantBitFirst)
       e.SDE("Only dfdl:bitOrder 'mostSignificantBitFirst' is supported.")
 
-    if (!g.signed)
-      e.SDE("Only signed integers are supported.")
-
-    val initStatement = s"    instance->$fieldName = 0xCDCDCDCD;"
+    // Start generating code snippets
+    val initialValue = lengthInBits match {
+      case 8 => "0xCD"
+      case 16 => "0xCDCD"
+      case 32 => "0xCDCDCDCD"
+      case 64 => "0xCDCDCDCDCDCDCDCD"
+      case _ => e.SDE("Lengths other than 8, 16, 32, or 64 bits are not supported.")
+    }
+    val initStatement = s"    instance->$fieldName = $initialValue;"
     val parseStatement =
       s"""    if (!error_msg)
          |    {
-         |        char   buffer[4];
+         |        char   buffer[sizeof(uint${lengthInBits}_t)];
          |        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
          |        if (count < sizeof(buffer))
          |        {
          |            error_msg = eof_or_error_msg(pstate->stream);
          |        }
-         |        instance->$fieldName = be32toh(*((uint32_t *)(&buffer)));
+         |        instance->$fieldName = be${lengthInBits}toh(*((uint${lengthInBits}_t *)(&buffer)));
          |    }""".stripMargin
     val unparseStatement =
       s"""    if (!error_msg)
          |    {
          |        union
          |        {
-         |            char     c_val[4];
-         |            uint32_t i_val;
+         |            char     c_val[sizeof(uint${lengthInBits}_t)];
+         |            uint${lengthInBits}_t i_val;
          |        } buffer;
-         |        buffer.i_val = htobe32(instance->$fieldName);
+         |        buffer.i_val = htobe${lengthInBits}(instance->$fieldName);
          |        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
          |        if (count < sizeof(buffer))
          |        {
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
index bf97636..0255111 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -170,8 +170,14 @@ class CodeGeneratorState {
     val e = context.namedQName.local
     val qnameInit = defineQNameInit(context)
     val typeCode = context.optPrimType.get match {
+      case PrimType.UnsignedLong => "PRIMITIVE_UINT64"
+      case PrimType.UnsignedInt => "PRIMITIVE_UINT32"
+      case PrimType.UnsignedShort => "PRIMITIVE_UINT16"
+      case PrimType.UnsignedByte => "PRIMITIVE_UINT8"
+      case PrimType.Long => "PRIMITIVE_INT64"
       case PrimType.Int => "PRIMITIVE_INT32"
-      case PrimType.String => "PRIMITIVE_STRING"
+      case PrimType.Short => "PRIMITIVE_INT16"
+      case PrimType.Byte => "PRIMITIVE_INT8"
       case p: PrimType => context.SDE("PrimType %s not supported yet.", p.toString)
     }
     val erd =
@@ -203,8 +209,14 @@ class CodeGeneratorState {
     val definition = if (child.isSimpleType) {
       import NodeInfo.PrimType
       child.optPrimType.get match {
+        case PrimType.UnsignedLong => "uint64_t   "
+        case PrimType.UnsignedInt => "uint32_t   "
+        case PrimType.UnsignedShort => "uint16_t   "
+        case PrimType.UnsignedByte => "uint8_t    "
         case PrimType.Long => "int64_t    "
         case PrimType.Int => "int32_t    "
+        case PrimType.Short => "int16_t    "
+        case PrimType.Byte => "int8_t     "
         case x => context.SDE("Unsupported primitive type: " + x)
       }
     } else {
@@ -260,6 +272,9 @@ class CodeGeneratorState {
          |
          |// Methods to initialize, parse, and unparse infoset nodes
          |
+         |static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
+         |static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
+         |
          |$finalImplementation
          |""".stripMargin
     code
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
index d13be31..b1157d1 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
@@ -17,6 +17,7 @@
 
 package org.apache.daffodil.runtime2.generators
 
+import org.apache.daffodil.grammar.primitives.AlignmentFill
 import org.apache.daffodil.grammar.primitives.ElementParseAndUnspecifiedLength
 import org.apache.daffodil.runtime2.Runtime2CodeGenerator
 
@@ -29,7 +30,8 @@ trait ElementParseAndUnspecifiedLengthCodeGenerator {
 
     context.schemaDefinitionWhen(context.inputValueCalcOption.isDefined, "Elements with inputValueCalc are not supported.")
     context.schemaDefinitionWhen(context.outputValueCalcOption.isDefined, "Elements with outputValueCalc are not supported.")
-    context.schemaDefinitionUnless(g.eBeforeGram.isEmpty, "Statements associated with elements are not supported.")
+    context.schemaDefinitionUnless(g.eBeforeGram.isEmpty
+      || g.eBeforeGram == AlignmentFill(context), "Statements associated with elements are not supported.")
     context.schemaDefinitionUnless(g.eAfterGram.isEmpty, "Statements associated with elements are not supported.")
     context.schemaDefinitionUnless(g.repTypeElementGram.isEmpty, "dfdlx:repType is not supported.")
 
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
index 81cade0..88fdf56 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
@@ -16,30 +16,37 @@
   limitations under the License.
 -->
 
-<xs:schema elementFormDefault="qualified"
-           targetNamespace="http://example.com"
-           xmlns="http://example.com"
-           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
-           xmlns:ex="http://example.com"
-           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+<xs:schema
+    elementFormDefault="qualified"
+    targetNamespace="http://example.com"
+    xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+    xmlns:ex="http://example.com"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns="http://example.com">
 
     <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
 
     <xs:annotation>
         <xs:appinfo source="http://www.ogf.org/dfdl/">
-            <dfdl:format ref="GeneralFormat" representation="binary"/>
+            <dfdl:format
+                alignment="8"
+                alignmentUnits="bits"
+                encoding="UTF-8"
+                lengthUnits="bits"
+                representation="binary"
+                ref="GeneralFormat"/>
         </xs:appinfo>
     </xs:annotation>
 
     <xs:element name="ex_int32">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="e1" type="xs:int"/>
+                <xs:element name="e1" type="xs:int" />
                 <xs:element name="c2">
                     <xs:complexType>
                         <xs:sequence>
-                            <xs:element name="e2" type="xs:int"/>
-                            <xs:element name="e3" type="xs:int"/>
+                            <xs:element name="e2" type="xs:int" />
+                            <xs:element name="e3" type="xs:int" />
                         </xs:sequence>
                     </xs:complexType>
                 </xs:element>
@@ -47,4 +54,43 @@
         </xs:complexType>
     </xs:element>
 
+    <xs:simpleType
+        name="int16"
+        dfdl:alignment="16"
+        dfdl:length="16"
+        dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:short"/>
+    </xs:simpleType>
+    <xs:simpleType
+        name="uint8"
+        dfdl:alignment="8"
+        dfdl:length="8"
+        dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:unsignedByte"/>
+    </xs:simpleType>
+    <xs:simpleType
+        name="uint16"
+        dfdl:alignment="16"
+        dfdl:length="16"
+        dfdl:lengthKind="explicit">
+        <xs:restriction base="xs:unsignedShort"/>
+    </xs:simpleType>
+
+    <xs:element name="orion_command">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="sync0" type="uint8" fixed="208"/>
+                <xs:element name="sync1" type="uint8" fixed="13"/>
+                <xs:element name="id" type="uint8" fixed="1"/>
+                <xs:element name="length" type="uint8" fixed="7"/>
+                <xs:element name="pan" type="int16"/>
+                <xs:element name="tilt" type="int16"/>
+                <xs:element name="mode" type="uint8" fixed="80"/>
+                <xs:element name="stabilized" type="uint8" fixed="0"/>
+                <xs:element name="impulse" type="uint8" fixed="0"/>
+                <xs:element name="checksum" type="uint16"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
 </xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
index 7a5d08b..7b85711 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
@@ -41,26 +41,54 @@ limitations under the License.
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    description="Parse binary int32 integers"
+    description="Parse example ex_int32"
     model="TestRuntime2.dfdl.xsd"
-    name="parse_int32">
+    name="ex_int32_parse"
+    root="ex_int32">
     <tdml:document>
-      <tdml:documentPart type="file">parse_int32</tdml:documentPart>
+      <tdml:documentPart type="file">ex_int32_parse</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">unparse_int32</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_int32_unparse</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="Unparse binary int32 numbers"
+    description="Unparse example ex_int32"
     model="TestRuntime2.dfdl.xsd"
-    name="unparse_int32">
+    name="ex_int32_unparse"
+    root="ex_int32">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">unparse_int32</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_int32_unparse</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">parse_int32</tdml:documentPart>
+      <tdml:documentPart type="file">ex_int32_parse</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="Parse example orion_command"
+    model="TestRuntime2.dfdl.xsd"
+    name="orion_command_parse"
+    root="orion_command">
+    <tdml:document>
+      <tdml:documentPart type="file">orion_command_parse</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">orion_command_unparse</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="Unparse example orion_command"
+    model="TestRuntime2.dfdl.xsd"
+    name="orion_command_unparse"
+    root="orion_command">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">orion_command_unparse</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">orion_command_parse</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32 b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32 b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_unparse
similarity index 81%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_unparse
index ea15640..cad2f06 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_unparse
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
@@ -16,10 +16,10 @@
   limitations under the License.
 -->
 
-<ex:ex_int32 xmlns:ex="http://example.com">
-  <ex:e1>1</ex:e1>
-  <ex:c2>
-    <ex:e2>2</ex:e2>
-    <ex:e3>3</ex:e3>
-  </ex:c2>
-</ex:ex_int32>
+<ex_int32 xmlns="http://example.com">
+  <e1>1</e1>
+  <c2>
+    <e2>2</e2>
+    <e3>3</e3>
+  </c2>
+</ex_int32>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse
new file mode 100644
index 0000000..4484b44
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32 b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse
similarity index 71%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse
index ea15640..8cda886 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
@@ -16,10 +16,15 @@
   limitations under the License.
 -->
 
-<ex:ex_int32 xmlns:ex="http://example.com">
-  <ex:e1>1</ex:e1>
-  <ex:c2>
-    <ex:e2>2</ex:e2>
-    <ex:e3>3</ex:e3>
-  </ex:c2>
-</ex:ex_int32>
+<orion_command xmlns="http://example.com">
+  <sync0>208</sync0>
+  <sync1>12</sync1>
+  <id>1</id>
+  <length>7</length>
+  <pan>-999</pan>
+  <tilt>-21231</tilt>
+  <mode>80</mode>
+  <stabilized>0</stabilized>
+  <impulse>0</impulse>
+  <checksum>30149</checksum>
+</orion_command>
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
index 9bada7c..5a5b7e7 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
@@ -31,6 +31,8 @@ object TestRuntime2 {
 class TestRuntime2 {
   import TestRuntime2._
 
-  @Test def test_parse_int32(): Unit = { runner.runOneTest("parse_int32") }
-  @Test def test_unparse_int32(): Unit = { runner.runOneTest("unparse_int32") }
+  @Test def test_ex_int32_parse(): Unit = { runner.runOneTest("ex_int32_parse") }
+  @Test def test_ex_int32_unparse(): Unit = { runner.runOneTest("ex_int32_unparse") }
+  @Test def test_orion_command_parse(): Unit = { runner.runOneTest("orion_command_parse") }
+  @Test def test_orion_command_unparse(): Unit = { runner.runOneTest("orion_command_unparse") }
 }
diff --git a/project/Rat.scala b/project/Rat.scala
index f9742a1..aa3b78d 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -116,7 +116,8 @@ object Rat {
     file("daffodil-sapi/src/test/resources/test/sapi/myData16.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData19.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myDataBroken.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse"),
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.bin"),
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),

[daffodil] 09/09: Fix test failures after rebase

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit b54772285a3b418ee853b029f2cabe65f0eafbd9
Author: John Interrante <in...@research.ge.com>
AuthorDate: Sat Mar 27 14:33:45 2021 -0400

    Fix test failures after rebase
    
    Rebase runtime2-2202 on latest commits from asf/master.  Fix test
    failures in TestCLIGenerateC.scala due to changes in scallop API.
    Improve CLI error handling in Main.scala.  Make tempDir val instead of
    var in both TestCLIGenerateC.scala and TestCodeGenerator.scala by
    initializing it immediately instead of using before() method.
---
 .../daffodil/generating/TestCLIGenerateC.scala     | 42 ++++++++++------------
 .../src/main/scala/org/apache/daffodil/Main.scala  |  1 +
 .../daffodil/runtime2/TestCodeGenerator.scala      |  9 ++---
 3 files changed, 22 insertions(+), 30 deletions(-)

diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
index e94ebec..33ed867 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -21,7 +21,6 @@ import net.sf.expectit.matcher.Matchers.contains
 import net.sf.expectit.matcher.Matchers.eof
 import org.apache.daffodil.CLI.Util
 import org.junit.After
-import org.junit.Before
 import org.junit.Test
 
 /**
@@ -31,20 +30,17 @@ import org.junit.Test
 class TestCLIGenerateC {
 
   val daffodil: String = Util.binPath
-  var outputDir: os.Path = _
   lazy val schemaFile: String = if (Util.isWindows) Util.cmdConvert(sf) else sf
   val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd")
-
-  @Before def before(): Unit = {
-    outputDir = os.temp.dir()
-  }
+  // Ensure all tests remove tempDir after creating it
+  val tempDir: os.Path = os.temp.dir()
 
   @After def after(): Unit = {
-    os.remove.all(outputDir)
+    os.remove.all(tempDir)
   }
 
   @Test def test_CLI_Generate_schema(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("")
@@ -56,11 +52,11 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
+    assert(os.exists(tempDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_CLI_Generate_noC_error(): Unit = {
-    val generateCmd = s"$daffodil generate -s $schemaFile $outputDir"
+    val generateCmd = s"$daffodil generate -s $schemaFile $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
@@ -75,13 +71,13 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_otherThanC_error(): Unit = {
-    val generateCmd = s"$daffodil generate vhld -s $schemaFile $outputDir"
+    val generateCmd = s"$daffodil generate vhld -s $schemaFile $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
     try {
       shell.sendLine(generateCmd)
-      shell.expect(contains("Excess arguments provided: 'vhld"))
+      shell.expect(contains("Unknown option 's'"))
       shell.sendLine(exitCmd)
       shell.expect(eof())
     } finally {
@@ -90,7 +86,7 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_noSchema_error(): Unit = {
-    val generateCmd = s"$daffodil generate c $outputDir"
+    val generateCmd = s"$daffodil generate c $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
@@ -105,7 +101,7 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_twoSchema_error(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -s $schemaFile $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -s $schemaFile $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
@@ -120,7 +116,7 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_verbose(): Unit = {
-    val generateCmd = s"$daffodil -v generate c -s $schemaFile $outputDir"
+    val generateCmd = s"$daffodil -v generate c -s $schemaFile $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
@@ -134,11 +130,11 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
+    assert(os.exists(tempDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_CLI_Generate_root(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_nums $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_nums $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("")
@@ -150,11 +146,11 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
+    assert(os.exists(tempDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_CLI_Generate_root_error(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_nums $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_nums $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
@@ -170,13 +166,13 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_namespaceNoRoot_error(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com} $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com} $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
     try {
       shell.sendLine(generateCmd)
-      shell.expect(contains("'{http://example.com}' - wrong arguments format"))
+      shell.expect(contains("Invalid syntax for extended QName"))
       shell.sendLine(exitCmd)
       shell.expect(eof())
     } finally {
@@ -185,7 +181,7 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_tunable(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -T parseUnparsePolicy=parseOnly $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -T parseUnparsePolicy=parseOnly $tempDir"
     val exitCmd = "exit"
 
     val shell = Util.start("")
@@ -197,6 +193,6 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
+    assert(os.exists(tempDir/"c"/"libruntime"/"generated_code.c"))
   }
 }
diff --git a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
index 3891195..a1573e0 100644
--- a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
+++ b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
@@ -533,6 +533,7 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments)
       validateFileIsFile(config) // --config must be a file that exists
     }
     addSubcommand(c)
+    requireSubcommand()
   }
 
   addSubcommand(parse)
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
index 3069efa..85af8c5 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
@@ -27,7 +27,6 @@ import org.apache.daffodil.util.SchemaUtils
 import org.apache.daffodil.util.TestUtils
 import org.junit.After
 import org.junit.Assert.assertArrayEquals
-import org.junit.Before
 import org.junit.Test
 
 /**
@@ -39,12 +38,8 @@ import org.junit.Test
  * as you could want.
  */
 class TestCodeGenerator {
-  // Ensure all tests remove tempDir after using it
-  var tempDir: os.Path = _
-
-  @Before def before(): Unit = {
-    tempDir = os.temp.dir()
-  }
+  // Ensure all tests remove tempDir after creating it
+  val tempDir: os.Path = os.temp.dir()
 
   @After def after(): Unit = {
     os.remove.all(tempDir)

[daffodil] 06/09: Support choices in runtime2 code generator with restrictions

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 80a95702696fe3bfcdc8f1e79592e988f5687830
Author: John Interrante <in...@research.ge.com>
AuthorDate: Wed Jan 27 16:56:07 2021 -0500

    Support choices in runtime2 code generator with restrictions
    
    Extend daffodil-runtime2's C code generator to support choices in DFDL
    schemas with restrictions (no anonymous/multiple choice groups, no
    backtracking or discrimination).  Refactoring the DPath expression
    compiler to generate C code will allow more choice dispatch key
    expressions to be supported later.  Refining the choice runtime
    structure and detecting anonymous choice groups will allow multiple
    choice groups to be inlined into parent elements later.
    
    An infoset element must have an xs:choice complex type defining a
    choice group.  The choice group must have a dfdl:choiceDispatchKey
    expression pointing to a preceding infoset element which must store an
    integral value.  Each alternative element in the choice group must
    have a dfdl:choiceBranchKey attribute containing only integer
    literals.  The C code generator makes some assumptions to simplify
    converting the choice dispatch expression to C code accessing a
    preceding infoset element:
    
     - the expression starts with '{xs:string( and ends with )}'
     - the expression returns the value of a previous element without
       changing the value in any way (except converting it to xs:string)
     - both the expression and the C code use only local names (for now...)
     - we can map the context node's path to a Unix-like slash path
     - all dpath operations look like Unix-like relative paths (../tag)
     - we can normalize the new path and convert it to C struct dot notation
     - we can store the dispatch value in an int64_t local variable safely
    
    Secondly, add/move some DFDL schemas contributed by collaborators
    along with their test cases and data files from daffodil-runtime2 to
    daffodil-test as requested by review.  Move runtime2's TDML support
    from daffodil-runtime2 to daffodil-tdml-processor and make changes to
    build.sbt and some tests to keep everything working.
    
    Thirdly, fix a test failure triggered by two threads calling
    CodeGenerator at the same time.
    
    Changelog:
    
    In build.sbt, don't make runtime2 depend on tdmlProc, instead make
    tdmlProc depend on runtime2 and test depend on runtime2's test classes
    so we can move some DFDL schemas and tests from runtime2 to test.
    Trim unnecessary C compile flags (note we don't use the .o files built
    by sbt-cc, we only want C compilation error/warning messages).
    
    In TestCLIGenerateC.scala, update path to TDML file that was renamed
    from TestRuntime2.dfdl.xsd to ex_nums.dfdl.xsd.
    
    In c/Makefile, put *.h files in HEADERS (not SOURCES) and trim
    -Wno-missing-field-initializers from CFLAGS since we've fixed all
    these warnings in the C code now.
    
    In daffodil_argp.c, fix warnings about missing field initializers.
    
    In daffodil_main.c, fix warnings about missing field initializers.
    
    In infoset.c, store offsets as size_t instead of ptrdiff_t since
    they're always positive numbers (can also store very large offsets
    without sign bit overflow).  Handle _choice member field with CHOICE
    typeCode appropriately (i.e., call ERD member function initChoice)
    when walking infoset with visitor methods.
    
    In infoset.h, add InitChoiceRD / initChoice to ERD member types /
    functions and CHOICE to TypeCode enumerations.  Store offsets as
    size_t instead of ptrdiff_t since they're always positive numbers.
    Define static constant NO_CHOICE as test to determine when _choice
    fields are uninitialized.
    
    In parsers.c/unparsers.c, reorder macro definitions slightly.
    
    Add NestedUnion.[ch] to show how C code can support choice complex
    types.  C code was generated from nested.dfdl.xsd schema using
    NestedUnion as the root element.
    
    In ex_nums.[ch], replace old generated code with new generated code.
    
    In CodeGenerator.scala, put a synchronized block around some
    FileSystem code to avoid calling FileSystems.newFileSystem
    concurrently when running TDML tests using runtime2.  Add scaladoc
    comments and remove -lpthread since we don't need to link C executable
    with it.
    
    In Runtime2CodeGenerator.scala, add braces to generateCode method.
    Note that I tried to detect choice groups when walking grammar objects
    in generateCode method but found out it was very difficult to detect
    them in that place while it was easier to detect them in
    ElementParseAndUnspecifiedLengthCodeGenerator.scala instead.
    
    In CodeGeneratorState.scala, rename qualifiedName function to erdName
    and improve it to qualify erdName with global complex type's name and
    append _ERD before returning erdName.  Update calls in rest of file
    accordingly.  Make addImplementation method generate new ERD member
    function initChoice.  Add choiceDispatchField function to convert a
    choiceDispatchKey expression into C struct dot notation for accessing
    the choiceDispatchKey expression's runtime value.  We'll need to
    refactor the DPath expression compiler to generate C code instead of
    using the choiceDispatchField function to handle more use cases later.
    Add new methods addBeforeSwitchStatements and addAfterSwitchStatements
    to generate declarations, ERD definitions, offset computations, ERD
    computations, init statements, initChoice statements, parse
    statements, and unparse statements needed to handle choices with
    several alternative branches.  Make addComplexTypeERD method include
    correct count and initChoice member function in ERDs containing
    alternative branches.  Make addComplexTypeStatements method generate C
    code (switch statement cases) for initChoice, parse, and unparse
    functions of complex types with alternative branches.  Make minor
    changes to addFieldDeclaration, generateCodeFile and
    generateCodeHeader methods to improve the generated C code.
    
    In ElementParseAndUnspecifiedLengthCodeGenerator.scala, call
    cgState.addBeforeSwitchStatements and cgState.addAfterSwitchStatements
    in right places to generate C code for elements having xs:choice
    complex types.
    
    Rename TestRuntime2.dfdl.xsd to ex_nums.dfdl.xsd.
    
    Rename TestRuntime2.tdml to ex_nums.tdml.  Update references to model
    ex_nums.dfdl.xsd and file ex_nums_unparse_runtime[12].xml.  Change
    defaultRoundTrip to "none" since every parse test is accompanied by an
    unparse test, making the extra work done by "onePass" redundant.
    Maybe we should keep defaultRoundTrip="onePass" and delete all the
    unparse tests, but it's nice to have debuggable entry points for both
    parse and unparse tests.
    
    Rename ex_nums_unparse1.xml to ex_nums_unparse_runtime1.xml to make it
    clearer the files are a pair of alternative infoset files for runtime1
    and runtime2, not a pair of alternative files for a choice group.
    
    Rename ex_nums_unparse2.xml to ex_nums_unparse_runtime2.xml.
    
    Add nested.dfdl.xsd with NestedUnion as a small example of a choice
    group using dfdl:choiceDispatchKey and dfdl:choiceBranchKey for
    development and testing.  Add nested.tdml with corresponding binary
    data files and unparse XML files to test NestedUnion in nested schema.
    
    In TDMLRunner.scala, update hardcoded class reference to
    org.apache.daffodil.tdml.processor.Runtime2TDMLDFDLProcessorFactory.
    
    Move Runtime2TDMLDFDLProcessor.scala from daffodil-runtime2 to
    daffodil-tdml-processor and put it in the same directory as
    DaffodilTDMLDFDLProcessor.scala.  Update the package and change the
    first class's name from TDMLDFDLProcessorFactory to
    Runtime2TDMLDFDLProcessorFactory.  Update all references to the new
    name of Runtime2TDMLDFDLProcessorFactory.  Remove [[...]] around
    Runtime2DataProcessor in a scaladoc comment since scaladoc can't find
    Runtime2DataProcessor after the move.
    
    Add or move the following DFDL schemas, test cases, and data files
    from daffodil-runtime2 to daffodil-test.  Note all of the Scala
    classes had to be put in daffodil-runtime2 because it is no longer
    possible for daffodil-runtime2 to run TDML tests itself due to the
    changes in build.sbt:
    
     - camera_state*
     - command*
     - egress_xdcc_bw*
     - ingress_xdcc_bw*
     - orion-command*
     - video_settings*
     - TestEgressXdccBw.scala
     - TestRuntime2.scala (and rename it to TestExNums.scala)
     - TestIngressXdccBw.scala
     - TestNested.scala
     - TestOrionCommand.scala (and add two test cases)
    
    Add egress_xdcc_bw.dfdl.xsd and ingress_xdcc_bw.dfdl.xsd from a
    collaborator who already gave permission for Apache license.  Add
    egress_xdcc_bw.tdml and ingress_xdcc_bw.tdml with corresponding parse
    binary data files and unparse XML files to test all choice
    alternatives in both schemas.
    
    In orion-command.dfdl.xsd, incorporate latest changes from
    collaborator to define global elements using global complex type
    declarations instead of nested complex type declarations.
    
    In orion-command.tdml, change defaultRoundTrip to "none" to avoid
    redundancy and speed up tests.  Add two more test cases (CameraState)
    and corresponding data files to test all orion-command messages.
    
    In choice-unparse2.tdml, change embedded schema name from "c" to "c1"
    to avoid conflict with daffodil-runtime2's "c" directory in its
    resources.
    
    Add TestEgressXdccBw.scala, TestIngressXdccBw.scala, and
    TestNested.scala to provide entry points for calling test cases.
    
    In Rat.scala, update paths of binary data files moved from
    daffodil-runtime2 to daffodil-test and add new binary data files.
---
 build.sbt                                          |  13 +-
 .../daffodil/generating/TestCLIGenerateC.scala     |   2 +-
 daffodil-runtime2/src/main/resources/c/Makefile    |  13 +-
 .../src/main/resources/c/libcli/daffodil_argp.c    |  19 +-
 .../src/main/resources/c/libcli/daffodil_main.c    |  10 +-
 .../src/main/resources/c/libruntime/infoset.c      |  16 +-
 .../src/main/resources/c/libruntime/infoset.h      |  38 +-
 .../src/main/resources/c/libruntime/parsers.c      |  17 +-
 .../src/main/resources/c/libruntime/unparsers.c    |  18 +-
 .../src/main/resources/examples/NestedUnion.c      | 410 ++++++++++
 .../examples/{ex_nums.h => NestedUnion.h}          |  59 +-
 .../src/main/resources/examples/ex_nums.c          | 357 +++------
 .../src/main/resources/examples/ex_nums.h          |   2 +-
 .../apache/daffodil/runtime2/CodeGenerator.scala   |  44 +-
 .../daffodil/runtime2/Runtime2CodeGenerator.scala  |   3 +-
 .../runtime2/generators/CodeGeneratorState.scala   | 271 ++++++-
 ...entParseAndUnspecifiedLengthCodeGenerator.scala |   4 +-
 .../{TestRuntime2.dfdl.xsd => ex_nums.dfdl.xsd}    |   0
 .../runtime2/{TestRuntime2.tdml => ex_nums.tdml}   |  44 +-
 ...s_unparse1.xml => ex_nums_unparse_runtime1.xml} |   0
 ...s_unparse2.xml => ex_nums_unparse_runtime2.xml} |   0
 .../org/apache/daffodil/runtime2/nested.dfdl.xsd   |  84 ++
 .../runtime2/{orion-command.tdml => nested.tdml}   |  62 +-
 .../daffodil/runtime2/nested_struct_parse.dat      | Bin 0 -> 36 bytes
 ...mmand_unparse.xml => nested_struct_unparse.xml} |  26 +-
 .../daffodil/runtime2/nested_union_parse_2.dat     | Bin 0 -> 16 bytes
 .../daffodil/runtime2/nested_union_parse_4.dat     | Bin 0 -> 28 bytes
 ...mand_unparse.xml => nested_union_unparse_2.xml} |  22 +-
 ...mand_unparse.xml => nested_union_unparse_4.xml} |  22 +-
 .../daffodil/runtime2/orion-command.dfdl.xsd       | 104 ---
 .../org/apache/daffodil/tdml/TDMLRunner.scala      |   2 +-
 .../processor}/Runtime2TDMLDFDLProcessor.scala     |  25 +-
 .../daffodil/runtime2/camera_state_parse.dat       | Bin 0 -> 11 bytes
 .../daffodil/runtime2/camera_state_unparse.xml     |  16 +-
 .../org/apache/daffodil/runtime2/command_parse.dat | Bin
 .../apache/daffodil/runtime2/command_unparse.xml   |   0
 .../daffodil/runtime2/egress_xdcc_bw.dfdl.xsd      | 244 ++++++
 .../apache/daffodil/runtime2/egress_xdcc_bw.tdml   | 300 +++++++
 .../daffodil/runtime2/egress_xdcc_bw_parse_11.dat  | Bin 0 -> 36 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_12.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_13.dat  | Bin 0 -> 120 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_14.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_15.dat  | Bin 0 -> 52 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_16.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_17.dat  | Bin 0 -> 56 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_18.dat  | Bin 0 -> 28 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_19.dat  | Bin 0 -> 744 bytes
 .../daffodil/runtime2/egress_xdcc_bw_parse_20.dat  | Bin 0 -> 28 bytes
 .../runtime2/egress_xdcc_bw_unparse_11.xml         |  38 +-
 .../runtime2/egress_xdcc_bw_unparse_12.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_13.xml         | 137 ++++
 .../runtime2/egress_xdcc_bw_unparse_14.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_15.xml         |  46 +-
 .../runtime2/egress_xdcc_bw_unparse_16.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_17.xml         |  73 ++
 .../runtime2/egress_xdcc_bw_unparse_18.xml         |  36 +-
 .../runtime2/egress_xdcc_bw_unparse_19.xml         | 638 +++++++++++++++
 .../runtime2/egress_xdcc_bw_unparse_20.xml         |  36 +-
 .../daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd     | 202 +++++
 .../apache/daffodil/runtime2/ingress_xdcc_bw.tdml  | 196 +++++
 .../runtime2/ingress_xdcc_bw_parse_111.dat         | Bin 0 -> 36 bytes
 .../runtime2/ingress_xdcc_bw_parse_112.dat         | Bin 0 -> 28 bytes
 .../runtime2/ingress_xdcc_bw_parse_113.dat         | Bin 0 -> 120 bytes
 .../runtime2/ingress_xdcc_bw_parse_114.dat         | Bin 0 -> 28 bytes
 .../runtime2/ingress_xdcc_bw_parse_115.dat         | Bin 0 -> 1184 bytes
 .../runtime2/ingress_xdcc_bw_parse_116.dat         | Bin 0 -> 28 bytes
 .../runtime2/ingress_xdcc_bw_unparse_111.xml       |  38 +-
 .../runtime2/ingress_xdcc_bw_unparse_112.xml       |  36 +-
 .../runtime2/ingress_xdcc_bw_unparse_113.xml       | 137 ++++
 .../runtime2/ingress_xdcc_bw_unparse_114.xml       |  36 +-
 .../runtime2/ingress_xdcc_bw_unparse_115.xml       | 859 +++++++++++++++++++++
 .../runtime2/ingress_xdcc_bw_unparse_116.xml       |  36 +-
 .../daffodil/runtime2/orion-command.dfdl.xsd       | 101 +++
 .../apache/daffodil/runtime2/orion-command.tdml    |  28 +-
 .../daffodil/runtime2/video_settings_parse.dat     | Bin
 .../daffodil/runtime2/video_settings_unparse.xml   |   0
 .../section15/choice_groups/choice-unparse2.tdml   |   8 +-
 .../daffodil/runtime2/TestEgressXdccBw.scala       |  54 ++
 .../org/apache/daffodil/runtime2/TestExNums.scala  |  16 +-
 .../daffodil/runtime2/TestIngressXdccBw.scala      |  46 ++
 .../org/apache/daffodil/runtime2/TestNested.scala  |  20 +-
 .../daffodil/runtime2/TestOrionCommand.scala       |   2 +
 project/Rat.scala                                  |  26 +-
 83 files changed, 4433 insertions(+), 767 deletions(-)

diff --git a/build.sbt b/build.sbt
index 489682b..b2fadab 100644
--- a/build.sbt
+++ b/build.sbt
@@ -64,7 +64,7 @@ lazy val runtime1Unparser = Project("daffodil-runtime1-unparser", file("daffodil
 val runtime2CFiles        = Library("libruntime2.a")
 lazy val runtime2         = Project("daffodil-runtime2", file("daffodil-runtime2")).configs(IntegrationTest)
                               .enablePlugins(CcPlugin)
-                              .dependsOn(core, core % "test->test", tdmlProc)
+                              .dependsOn(core, core % "test->test")
                               .settings(commonSettings)
                               .settings(publishArtifact in (Compile, packageDoc) := false)
                               .settings(
@@ -82,12 +82,7 @@ lazy val runtime2         = Project("daffodil-runtime2", file("daffodil-runtime2
                                     (Compile / resourceDirectory).value / "examples"
                                   )
                                 ),
-                                Compile / cFlags := (Compile / cFlags).value.withDefaultValue(Seq(
-                                  "-g",
-                                  "-Wall",
-                                  "-Wextra",
-                                  "-Wno-missing-field-initializers",
-                                ))
+                                Compile / cFlags := (Compile / cFlags).value.withDefaultValue(Seq("-Wall", "-Wextra"))
                               )
 
 lazy val core             = Project("daffodil-core", file("daffodil-core")).configs(IntegrationTest)
@@ -107,7 +102,7 @@ lazy val tdmlLib             = Project("daffodil-tdml-lib", file("daffodil-tdml-
                               .settings(commonSettings)
 
 lazy val tdmlProc         = Project("daffodil-tdml-processor", file("daffodil-tdml-processor")).configs(IntegrationTest)
-                              .dependsOn(tdmlLib, core)
+                              .dependsOn(tdmlLib, runtime2, core)
                               .settings(commonSettings)
 
 lazy val cli              = Project("daffodil-cli", file("daffodil-cli")).configs(IntegrationTest)
@@ -125,7 +120,7 @@ lazy val schematron       = Project("daffodil-schematron", file("daffodil-schema
                               .configs(IntegrationTest)
 
 lazy val test             = Project("daffodil-test", file("daffodil-test")).configs(IntegrationTest)
-                              .dependsOn(tdmlProc, udf % "test->test")
+                              .dependsOn(tdmlProc, runtime2 % "test->test", udf % "test->test")
                               .settings(commonSettings, nopublish)
                               //
                               // Uncomment the following line to run these tests 
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
index 6700b66..e94ebec 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -33,7 +33,7 @@ class TestCLIGenerateC {
   val daffodil: String = Util.binPath
   var outputDir: os.Path = _
   lazy val schemaFile: String = if (Util.isWindows) Util.cmdConvert(sf) else sf
-  val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd")
+  val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd")
 
   @Before def before(): Unit = {
     outputDir = os.temp.dir()
diff --git a/daffodil-runtime2/src/main/resources/c/Makefile b/daffodil-runtime2/src/main/resources/c/Makefile
index fd1cf8d..d8b9e90 100644
--- a/daffodil-runtime2/src/main/resources/c/Makefile
+++ b/daffodil-runtime2/src/main/resources/c/Makefile
@@ -17,12 +17,15 @@
 # Here's how to compile the C sources into a program for running
 # parse/unparse tests (.dat <-> .xml)
 
-SOURCES = libcli/*.[ch] libruntime/*.[ch]
 PROGRAM = ./daffodil
-CFLAGS = -g -Wall -Wextra -Wno-missing-field-initializers
-
-$(PROGRAM): $(SOURCES)
-	$(CC) $(CFLAGS) -I libcli -I libruntime $(SOURCES) -lmxml -o $(PROGRAM)
+HEADERS = libcli/*.h libruntime/*.h
+SOURCES = libcli/*.c libruntime/*.c
+INCLUDES = -I libcli -I libruntime
+CFLAGS = -g -Wall -Wextra
+LIBS = -lmxml
+
+$(PROGRAM): $(HEADERS) $(SOURCES)
+	$(CC) $(CFLAGS) $(INCLUDES) $(SOURCES) $(LIBS) -o $(PROGRAM)
 
 # Here's how to run parse/unparse tests (.dat <-> .xml, although you
 # will need to create the .dat and .xml files first)
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
index 0b4e911..ddc9b31 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
@@ -35,11 +35,12 @@ struct daffodil_parse_cli daffodil_parse = {
 
 static const struct argp_option parse_options[] = {
     {"infoset-type", 'I', "<infoset_type>", 0,
-     "Infoset type to output. Must be one of 'xml' or 'null'"},
+     "Infoset type to output. Must be one of 'xml' or 'null'", 0},
 
     {"output", 'o', "<file>", 0,
      "Write output to a given file. If not given or is -, output is written to "
-     "stdout"},
+     "stdout",
+     0},
 
     {0}};
 
@@ -62,6 +63,9 @@ static const struct argp parse_argp = {
     parse_handler,  // function to get these CLI options
     parse_args_doc, // short usage documentation
     parse_doc,      // long help documentation
+    0,              // child argps parsed after this argp
+    0,              // function to replace help messages
+    0               // domain name for translation lookup
 };
 
 // Handle callbacks to get our "daffodil parse" CLI options
@@ -128,11 +132,12 @@ struct daffodil_unparse_cli daffodil_unparse = {
 
 static const struct argp_option unparse_options[] = {
     {"infoset-type", 'I', "<infoset_type>", 0,
-     "Infoset type to unparse. Must be 'xml'"},
+     "Infoset type to unparse. Must be 'xml'", 0},
 
     {"output", 'o', "<file>", 0,
      "Write output to file. If not given or is -, output is written to "
-     "standard output"},
+     "standard output",
+     0},
 
     {0}};
 
@@ -155,6 +160,9 @@ static const struct argp unparse_argp = {
     unparse_handler,  // function to get these CLI options
     unparse_args_doc, // short usage documentation
     unparse_doc,      // long help documentation
+    0,                // child argps parsed after this argp
+    0,                // function to replace help messages
+    0                 // domain name for translation lookup
 };
 
 // Handle callbacks to get our "daffodil unparse" CLI options
@@ -243,6 +251,9 @@ static const struct argp daffodil_argp = {
     daffodil_handler,  // function to get these CLI options
     daffodil_args_doc, // short usage documentation
     daffodil_doc,      // long help documentation
+    0,                 // child argps parsed after this argp
+    0,                 // function to replace help messages
+    0                  // domain name for translation lookup
 };
 
 // Handle callbacks to get our "daffodil" CLI options
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
index f915d9f..56320ff 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
@@ -85,14 +85,15 @@ main(int argc, char *argv[])
             output = fopen_or_exit(output, daffodil_parse.outfile, "w");
 
             // Parse the input file into our infoset.
-            PState pstate = {input};
+            PState pstate = {input, NULL};
             root->erd->parseSelf(root, &pstate);
             continue_or_exit(pstate.error_msg);
 
             if (strcmp(daffodil_parse.infoset_converter, "xml") == 0)
             {
                 // Visit the infoset and print XML from it.
-                XMLWriter   xmlWriter = {xmlWriterMethods, output};
+                XMLWriter   xmlWriter = {
+                    xmlWriterMethods, output, {NULL, NULL, 0}};
                 const char *error_msg =
                     walkInfoset((VisitEventHandler *)&xmlWriter, root);
                 continue_or_exit(error_msg);
@@ -112,7 +113,8 @@ main(int argc, char *argv[])
             if (strcmp(daffodil_unparse.infoset_converter, "xml") == 0)
             {
                 // Initialize our infoset's values from the XML data.
-                XMLReader   xmlReader = {xmlReaderMethods, input, root};
+                XMLReader   xmlReader = {
+                    xmlReaderMethods, input, root, NULL, NULL};
                 const char *error_msg =
                     walkInfoset((VisitEventHandler *)&xmlReader, root);
                 continue_or_exit(error_msg);
@@ -124,7 +126,7 @@ main(int argc, char *argv[])
             }
 
             // Unparse our infoset to the output file.
-            UState ustate = {output};
+            UState ustate = {output, NULL};
             root->erd->unparseSelf(root, &ustate);
             continue_or_exit(ustate.error_msg);
         }
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
index d40c351..9377b87 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
@@ -127,19 +127,19 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
     // Walk the node's children recursively
     const size_t      count = infoNode->erd->numChildren;
     const ERD **const childrenERDs = infoNode->erd->childrenERDs;
-    const ptrdiff_t * offsets = infoNode->erd->offsets;
+    const size_t *    offsets = infoNode->erd->offsets;
 
     for (size_t i = 0; i < count && !error_msg; i++)
     {
-        ptrdiff_t  offset = offsets[i];
-        const ERD *childERD = childrenERDs[i];
+        const size_t offset = offsets[i];
+        const ERD *  childERD = childrenERDs[i];
         // We use only one of these variables below depending on typeCode
         const InfosetBase *childNode =
             (const InfosetBase *)((const char *)infoNode + offset);
         const void *numLocation =
             (const void *)((const char *)infoNode + offset);
 
-        // Need to handle more element types
+        // Will need to handle more element types
         const enum TypeCode typeCode = childERD->typeCode;
         switch (typeCode)
         {
@@ -159,6 +159,14 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
             error_msg =
                 handler->visitNumberElem(handler, childERD, numLocation);
             break;
+        case CHOICE:
+            // Point next ERD to choice of alternative elements' ERDs
+            if (!infoNode->erd->initChoice(infoNode, rootElement()))
+            {
+                error_msg =
+                    "Walk error: no match between choice dispatch key and any branch key";
+            }
+            break;
         }
     }
 
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
index d9b614c..404bf6d 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
@@ -18,17 +18,12 @@
 #ifndef INFOSET_H
 #define INFOSET_H
 
-#include <stddef.h>  // for ptrdiff_t, size_t
-#include <stdio.h>   // for FILE
+#include <stdbool.h>  // for bool
+#include <stddef.h>   // for size_t
+#include <stdio.h>    // for FILE
 
 // Prototypes needed for compilation
 
-struct ElementRuntimeData;
-struct InfosetBase;
-struct PState;
-struct UState;
-struct VisitEventHandler;
-
 typedef struct ElementRuntimeData ERD;
 typedef struct InfosetBase        InfosetBase;
 typedef struct PState             PState;
@@ -38,6 +33,8 @@ typedef struct VisitEventHandler  VisitEventHandler;
 typedef void (*ERDInitSelf)(InfosetBase *infoNode);
 typedef void (*ERDParseSelf)(InfosetBase *infoNode, PState *pstate);
 typedef void (*ERDUnparseSelf)(const InfosetBase *infoNode, UState *ustate);
+typedef bool (*InitChoiceRD)(const InfosetBase *infoNode,
+                             const InfosetBase *rootElement);
 
 typedef const char *(*VisitStartDocument)(const VisitEventHandler *handler);
 typedef const char *(*VisitEndDocument)(const VisitEventHandler *handler);
@@ -71,7 +68,8 @@ enum TypeCode
     PRIMITIVE_INT16,
     PRIMITIVE_INT8,
     PRIMITIVE_FLOAT,
-    PRIMITIVE_DOUBLE
+    PRIMITIVE_DOUBLE,
+    CHOICE
 };
 
 // ERD - element runtime data needed to parse/unparse objects
@@ -81,34 +79,35 @@ typedef struct ElementRuntimeData
     const NamedQName    namedQName;
     const enum TypeCode typeCode;
     const size_t        numChildren;
-    const ptrdiff_t *   offsets;
+    const size_t *      offsets;
     const ERD **        childrenERDs;
 
     const ERDInitSelf    initSelf;
     const ERDParseSelf   parseSelf;
     const ERDUnparseSelf unparseSelf;
+    const InitChoiceRD   initChoice;
 } ERD;
 
-// InfosetBase - representation of an infoset element
+// InfosetBase - metadata of an infoset element
 
 typedef struct InfosetBase
 {
     const ERD *erd;
 } InfosetBase;
 
-// PState - parser state while parsing input
+// PState - mutable state while parsing data
 
 typedef struct PState
 {
-    FILE *      stream;    // input to read from
+    FILE *      stream;    // input to read data from
     const char *error_msg; // to stop if an error happens
 } PState;
 
-// UState - unparser state while unparsing infoset
+// UState - mutable state while unparsing infoset
 
 typedef struct UState
 {
-    FILE *      stream;    // output to write to
+    FILE *      stream;    // output to write data to
     const char *error_msg; // to stop if an error happens
 } UState;
 
@@ -130,9 +129,10 @@ extern const char *get_erd_name(const ERD *erd);
 extern const char *get_erd_xmlns(const ERD *erd);
 extern const char *get_erd_ns(const ERD *erd);
 
-// rootElement - return a root element to walk while parsing or unparsing
+// rootElement - return an infoset's root element for parsing,
+// walking, or unparsing (implementation actually is generated in
+// generated_code.c, not defined in infoset.c)
 
-// (actual definition will be in generated_code.c, not infoset.c)
 extern InfosetBase *rootElement(void);
 
 // walkInfoset - walk an infoset and call VisitEventHandler methods
@@ -144,4 +144,8 @@ extern const char *walkInfoset(const VisitEventHandler *handler,
 
 extern const char *eof_or_error_msg(FILE *stream);
 
+// NO_CHOICE - value stored in an uninitialized _choice field
+
+static const size_t NO_CHOICE = (size_t)-1;
+
 #endif // INFOSET_H
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
index 87a5f98..8d97b99 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
@@ -19,10 +19,16 @@
 #include <endian.h>  // for be32toh, be64toh, le32toh, le64toh, be16toh, le16toh
 #include <stdio.h>   // for fread, size_t
 
-// Macros to expand into functions below
+// Macros that are not defined by <endian.h>
+
+#define be8toh(var) var
+
+#define le8toh(var) var
+
+// Macros to define parse_<endian>_<type> functions
 
 #define define_parse_endian_real(endian, type, bits)                           \
-    extern void parse_##endian##_##type(type *number, PState *pstate)          \
+    void parse_##endian##_##type(type *number, PState *pstate)                 \
     {                                                                          \
         if (!pstate->error_msg)                                                \
         {                                                                      \
@@ -44,8 +50,7 @@
     }
 
 #define define_parse_endian_integer(endian, type, bits)                        \
-    extern void parse_##endian##_##type##bits(type##bits##_t *number,          \
-                                              PState *        pstate)          \
+    void parse_##endian##_##type##bits(type##bits##_t *number, PState *pstate) \
     {                                                                          \
         if (!pstate->error_msg)                                                \
         {                                                                      \
@@ -64,10 +69,6 @@
         }                                                                      \
     }
 
-#define be8toh(var) var
-
-#define le8toh(var) var
-
 // Define functions to parse binary real and integer numbers
 
 define_parse_endian_real(be, double, 64)
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
index 93cddbd..b48bb5d 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
@@ -19,10 +19,16 @@
 #include <endian.h>  // for htobe32, htobe64, htole32, htole64, htobe16, htole16
 #include <stdio.h>   // for fwrite, size_t
 
-// Macros to expand into functions below
+// Macros that are not defined by <endian.h>
+
+#define htobe8(var) var
+
+#define htole8(var) var
+
+// Macros to define unparse_<endian>_<type> functions
 
 #define define_unparse_endian_real(endian, type, bits)                         \
-    extern void unparse_##endian##_##type(type number, UState *ustate)         \
+    void unparse_##endian##_##type(type number, UState *ustate)                \
     {                                                                          \
         if (!ustate->error_msg)                                                \
         {                                                                      \
@@ -44,8 +50,8 @@
     }
 
 #define define_unparse_endian_integer(endian, type, bits)                      \
-    extern void unparse_##endian##_##type##bits(type##bits##_t number,         \
-                                                UState *       ustate)         \
+    void unparse_##endian##_##type##bits(type##bits##_t number,                \
+                                         UState *       ustate)                \
     {                                                                          \
         if (!ustate->error_msg)                                                \
         {                                                                      \
@@ -64,10 +70,6 @@
         }                                                                      \
     }
 
-#define htobe8(var) var
-
-#define htole8(var) var
-
 // Define functions to unparse binary real and integer numbers
 
 define_unparse_endian_real(be, double, 64)
diff --git a/daffodil-runtime2/src/main/resources/examples/NestedUnion.c b/daffodil-runtime2/src/main/resources/examples/NestedUnion.c
new file mode 100644
index 0000000..da4a0a4
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/examples/NestedUnion.c
@@ -0,0 +1,410 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NestedUnion.h"
+#include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
+#include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
+#include <math.h>       // for NAN
+#include <stdbool.h>    // for bool, false, true
+#include <stddef.h>     // for NULL, size_t
+
+// Prototypes needed for compilation
+
+static void foo_initSelf(foo *instance);
+static void foo_parseSelf(foo *instance, PState *pstate);
+static void foo_unparseSelf(const foo *instance, UState *ustate);
+static void bar_initSelf(bar *instance);
+static void bar_parseSelf(bar *instance, PState *pstate);
+static void bar_unparseSelf(const bar *instance, UState *ustate);
+static void data_initSelf(data *instance);
+static bool data_initChoice(data *instance, const NestedUnion *rootElement);
+static void data_parseSelf(data *instance, PState *pstate);
+static void data_unparseSelf(const data *instance, UState *ustate);
+static void NestedUnion_initSelf(NestedUnion *instance);
+static void NestedUnion_parseSelf(NestedUnion *instance, PState *pstate);
+static void NestedUnion_unparseSelf(const NestedUnion *instance, UState *ustate);
+
+// Metadata singletons
+
+static const ERD tag_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "tag", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD _choice_data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "_choice", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    CHOICE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD a_FooType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "a", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD b_FooType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "b", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD c_FooType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "c", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const foo foo_compute_offsets;
+
+static const size_t foo_offsets[3] = {
+    (const char *)&foo_compute_offsets.a - (const char *)&foo_compute_offsets,
+    (const char *)&foo_compute_offsets.b - (const char *)&foo_compute_offsets,
+    (const char *)&foo_compute_offsets.c - (const char *)&foo_compute_offsets
+};
+
+static const ERD *foo_childrenERDs[3] = {
+    &a_FooType_ERD,
+    &b_FooType_ERD,
+    &c_FooType_ERD
+};
+
+static const ERD foo_data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "foo", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    3, // numChildren
+    foo_offsets, // offsets
+    foo_childrenERDs, // childrenERDs
+    (ERDInitSelf)&foo_initSelf, // initSelf
+    (ERDParseSelf)&foo_parseSelf, // parseSelf
+    (ERDUnparseSelf)&foo_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
+static const ERD x_BarType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "x", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD y_BarType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "y", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD z_BarType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "z", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const bar bar_compute_offsets;
+
+static const size_t bar_offsets[3] = {
+    (const char *)&bar_compute_offsets.x - (const char *)&bar_compute_offsets,
+    (const char *)&bar_compute_offsets.y - (const char *)&bar_compute_offsets,
+    (const char *)&bar_compute_offsets.z - (const char *)&bar_compute_offsets
+};
+
+static const ERD *bar_childrenERDs[3] = {
+    &x_BarType_ERD,
+    &y_BarType_ERD,
+    &z_BarType_ERD
+};
+
+static const ERD bar_data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "bar", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    3, // numChildren
+    bar_offsets, // offsets
+    bar_childrenERDs, // childrenERDs
+    (ERDInitSelf)&bar_initSelf, // initSelf
+    (ERDParseSelf)&bar_parseSelf, // parseSelf
+    (ERDUnparseSelf)&bar_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
+static const data data_compute_offsets;
+
+static const size_t data_offsets[3] = {
+    (const char *)&data_compute_offsets._choice - (const char *)&data_compute_offsets,
+    (const char *)&data_compute_offsets.foo - (const char *)&data_compute_offsets,
+    (const char *)&data_compute_offsets.bar - (const char *)&data_compute_offsets
+};
+
+static const ERD *data_childrenERDs[3] = {
+    &_choice_data_NestedUnionType_ERD,
+    &foo_data_NestedUnionType_ERD,
+    &bar_data_NestedUnionType_ERD
+};
+
+static const ERD data_NestedUnionType_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "data", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    2, // numChildren
+    data_offsets, // offsets
+    data_childrenERDs, // childrenERDs
+    (ERDInitSelf)&data_initSelf, // initSelf
+    (ERDParseSelf)&data_parseSelf, // parseSelf
+    (ERDUnparseSelf)&data_unparseSelf, // unparseSelf
+    (InitChoiceRD)&data_initChoice // initChoice
+};
+
+static const NestedUnion NestedUnion_compute_offsets;
+
+static const size_t NestedUnion_offsets[2] = {
+    (const char *)&NestedUnion_compute_offsets.tag - (const char *)&NestedUnion_compute_offsets,
+    (const char *)&NestedUnion_compute_offsets.data - (const char *)&NestedUnion_compute_offsets
+};
+
+static const ERD *NestedUnion_childrenERDs[2] = {
+    &tag_NestedUnionType_ERD,
+    &data_NestedUnionType_ERD
+};
+
+static const ERD NestedUnion_ERD = {
+    {
+        "idl", // namedQName.prefix
+        "NestedUnion", // namedQName.local
+        "urn:idl:1.0", // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    2, // numChildren
+    NestedUnion_offsets, // offsets
+    NestedUnion_childrenERDs, // childrenERDs
+    (ERDInitSelf)&NestedUnion_initSelf, // initSelf
+    (ERDParseSelf)&NestedUnion_parseSelf, // parseSelf
+    (ERDUnparseSelf)&NestedUnion_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
+// Return a root element to be used for parsing or unparsing
+
+InfosetBase *
+rootElement(void)
+{
+    static bool initialized;
+    static NestedUnion root;
+    if (!initialized)
+    {
+        NestedUnion_initSelf(&root);
+        initialized = true;
+    }
+    return &root._base;
+}
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+foo_initSelf(foo *instance)
+{
+    instance->_base.erd = &foo_data_NestedUnionType_ERD;
+    instance->a = 0xCCCCCCCC;
+    instance->b = 0xCCCCCCCC;
+    instance->c = 0xCCCCCCCC;
+}
+
+static void
+foo_parseSelf(foo *instance, PState *pstate)
+{
+    parse_be_int32(&instance->a, pstate);
+    parse_be_int32(&instance->b, pstate);
+    parse_be_int32(&instance->c, pstate);
+}
+
+static void
+foo_unparseSelf(const foo *instance, UState *ustate)
+{
+    unparse_be_int32(instance->a, ustate);
+    unparse_be_int32(instance->b, ustate);
+    unparse_be_int32(instance->c, ustate);
+}
+
+static void
+bar_initSelf(bar *instance)
+{
+    instance->_base.erd = &bar_data_NestedUnionType_ERD;
+    instance->x = NAN;
+    instance->y = NAN;
+    instance->z = NAN;
+}
+
+static void
+bar_parseSelf(bar *instance, PState *pstate)
+{
+    parse_be_double(&instance->x, pstate);
+    parse_be_double(&instance->y, pstate);
+    parse_be_double(&instance->z, pstate);
+}
+
+static void
+bar_unparseSelf(const bar *instance, UState *ustate)
+{
+    unparse_be_double(instance->x, ustate);
+    unparse_be_double(instance->y, ustate);
+    unparse_be_double(instance->z, ustate);
+}
+
+static void
+data_initSelf(data *instance)
+{
+    instance->_base.erd = &data_NestedUnionType_ERD;
+    instance->_choice = NO_CHOICE;
+    foo_initSelf(&instance->foo);
+    bar_initSelf(&instance->bar);
+}
+
+static bool
+data_initChoice(data *instance, const NestedUnion *rootElement)
+{
+    int64_t key = rootElement->tag;
+    switch (key)
+    {
+    case 1:
+    case 2:
+        instance->_choice = 0;
+        break;
+    case 3:
+    case 4:
+        instance->_choice = 1;
+        break;
+    default:
+        instance->_choice = NO_CHOICE;
+        break;
+    }
+
+    if (instance->_choice != NO_CHOICE)
+    {
+        const size_t choice = instance->_choice + 1; // skip the _choice field
+        const size_t offset = instance->_base.erd->offsets[choice];
+        const ERD *  childERD = instance->_base.erd->childrenERDs[choice];
+        InfosetBase *childNode = (InfosetBase *)((const char *)instance + offset);
+        childNode->erd = childERD;
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+static void
+data_parseSelf(data *instance, PState *pstate)
+{
+    instance->_base.erd->initChoice(&instance->_base, rootElement());
+    switch (instance->_choice)
+    {
+    case 0:
+        foo_parseSelf(&instance->foo, pstate);
+        break;
+    case 1:
+        bar_parseSelf(&instance->bar, pstate);
+        break;
+    default:
+        pstate->error_msg =
+            "Parse error: no match between choice dispatch key and any branch key";
+        break;
+    }
+}
+
+static void
+data_unparseSelf(const data *instance, UState *ustate)
+{
+    instance->_base.erd->initChoice(&instance->_base, rootElement());
+    switch (instance->_choice)
+    {
+    case 0:
+        foo_unparseSelf(&instance->foo, ustate);
+        break;
+    case 1:
+        bar_unparseSelf(&instance->bar, ustate);
+        break;
+    default:
+        ustate->error_msg =
+            "Unparse error: no match between choice dispatch key and any branch key";
+        break;
+    }
+}
+
+static void
+NestedUnion_initSelf(NestedUnion *instance)
+{
+    instance->_base.erd = &NestedUnion_ERD;
+    instance->tag = 0xCCCCCCCC;
+    data_initSelf(&instance->data);
+}
+
+static void
+NestedUnion_parseSelf(NestedUnion *instance, PState *pstate)
+{
+    parse_be_int32(&instance->tag, pstate);
+    data_parseSelf(&instance->data, pstate);
+}
+
+static void
+NestedUnion_unparseSelf(const NestedUnion *instance, UState *ustate)
+{
+    unparse_be_int32(instance->tag, ustate);
+    data_unparseSelf(&instance->data, ustate);
+}
+
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.h b/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
similarity index 57%
copy from daffodil-runtime2/src/main/resources/examples/ex_nums.h
copy to daffodil-runtime2/src/main/resources/examples/NestedUnion.h
index 9e2c1bb..4396cd7 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.h
+++ b/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
@@ -21,51 +21,40 @@
 #include "infoset.h"  // for InfosetBase
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-// Define some infoset structures
+// Define infoset structures
 
-typedef struct array
+typedef struct foo
 {
     InfosetBase _base;
-    int16_t     be_int16[3];
-    float       be_float[3];
-} array;
+    int32_t     a;
+    int32_t     b;
+    int32_t     c;
+} foo;
 
-typedef struct bigEndian
+typedef struct bar
 {
     InfosetBase _base;
-    double      be_double;
-    float       be_float;
-    uint64_t    be_uint64;
-    uint32_t    be_uint32;
-    uint16_t    be_uint16;
-    uint8_t     be_uint8;
-    int64_t     be_int64;
-    int32_t     be_int32;
-    int16_t     be_int16;
-    int8_t      be_int8;
-} bigEndian;
+    double      x;
+    double      y;
+    double      z;
+} bar;
 
-typedef struct littleEndian
+typedef struct data
 {
     InfosetBase _base;
-    uint64_t    le_uint64;
-    uint32_t    le_uint32;
-    uint16_t    le_uint16;
-    uint8_t     le_uint8;
-    int64_t     le_int64;
-    int32_t     le_int32;
-    int16_t     le_int16;
-    int8_t      le_int8;
-    float       le_float;
-    double      le_double;
-} littleEndian;
-
-typedef struct ex_nums
+    size_t      _choice; // choice of which union field to use
+    union
+    {
+        foo foo;
+        bar bar;
+    };
+} data;
+
+typedef struct NestedUnion
 {
     InfosetBase _base;
-    array array;
-    bigEndian bigEndian;
-    littleEndian littleEndian;
-} ex_nums;
+    int32_t     tag;
+    data data;
+} NestedUnion;
 
 #endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.c b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
index 7747006..fb6f98f 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.c
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
@@ -19,7 +19,8 @@
 #include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
 #include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
 #include <math.h>       // for NAN
-#include <stddef.h>     // for NULL, ptrdiff_t
+#include <stdbool.h>    // for bool, false, true
+#include <stddef.h>     // for NULL, size_t
 
 // Prototypes needed for compilation
 
@@ -38,39 +39,29 @@ static void ex_nums_unparseSelf(const ex_nums *instance, UState *ustate);
 
 // Metadata singletons
 
-static const ERD be_int16_array_ex_nums__ERD = {
+static const ERD be_int16_array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_float_array_ex_nums__ERD = {
+static const ERD be_float_array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_float", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_FLOAT, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const array array_compute_offsets;
 
-static const ptrdiff_t array_offsets[6] = {
+static const size_t array_offsets[6] = {
     (const char *)&array_compute_offsets.be_int16[0] - (const char *)&array_compute_offsets,
     (const char *)&array_compute_offsets.be_int16[1] - (const char *)&array_compute_offsets,
     (const char *)&array_compute_offsets.be_int16[2] - (const char *)&array_compute_offsets,
@@ -80,182 +71,133 @@ static const ptrdiff_t array_offsets[6] = {
 };
 
 static const ERD *array_childrenERDs[6] = {
-    &be_int16_array_ex_nums__ERD,
-    &be_int16_array_ex_nums__ERD,
-    &be_int16_array_ex_nums__ERD,
-    &be_float_array_ex_nums__ERD,
-    &be_float_array_ex_nums__ERD,
-    &be_float_array_ex_nums__ERD
+    &be_int16_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD,
+    &be_float_array_ex_nums_ERD,
+    &be_float_array_ex_nums_ERD,
+    &be_float_array_ex_nums_ERD
 };
 
-static const ERD array_ex_nums__ERD = {
+static const ERD array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "array", // namedQName.local
         NULL, // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    6,                               // numChildren
-    array_offsets,                      // offsets
-    array_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&array_initSelf,       // initSelf
-    (ERDParseSelf)&array_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    6, // numChildren
+    array_offsets, // offsets
+    array_childrenERDs, // childrenERDs
+    (ERDInitSelf)&array_initSelf, // initSelf
+    (ERDParseSelf)&array_parseSelf, // parseSelf
     (ERDUnparseSelf)&array_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
-static const ERD be_double_bigEndian_ex_nums__ERD = {
+static const ERD be_double_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_double", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_DOUBLE, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_float_bigEndian_ex_nums__ERD = {
+static const ERD be_float_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_float", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_FLOAT, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint64_bigEndian_ex_nums__ERD = {
+static const ERD be_uint64_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint32_bigEndian_ex_nums__ERD = {
+static const ERD be_uint32_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint16_bigEndian_ex_nums__ERD = {
+static const ERD be_uint16_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint8_bigEndian_ex_nums__ERD = {
+static const ERD be_uint8_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_uint8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int64_bigEndian_ex_nums__ERD = {
+static const ERD be_int64_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int32_bigEndian_ex_nums__ERD = {
+static const ERD be_int32_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int16_bigEndian_ex_nums__ERD = {
+static const ERD be_int16_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int8_bigEndian_ex_nums__ERD = {
+static const ERD be_int8_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "be_int8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const bigEndian bigEndian_compute_offsets;
 
-static const ptrdiff_t bigEndian_offsets[10] = {
+static const size_t bigEndian_offsets[10] = {
     (const char *)&bigEndian_compute_offsets.be_double - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_float - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_uint64 - (const char *)&bigEndian_compute_offsets,
@@ -269,186 +211,137 @@ static const ptrdiff_t bigEndian_offsets[10] = {
 };
 
 static const ERD *bigEndian_childrenERDs[10] = {
-    &be_double_bigEndian_ex_nums__ERD,
-    &be_float_bigEndian_ex_nums__ERD,
-    &be_uint64_bigEndian_ex_nums__ERD,
-    &be_uint32_bigEndian_ex_nums__ERD,
-    &be_uint16_bigEndian_ex_nums__ERD,
-    &be_uint8_bigEndian_ex_nums__ERD,
-    &be_int64_bigEndian_ex_nums__ERD,
-    &be_int32_bigEndian_ex_nums__ERD,
-    &be_int16_bigEndian_ex_nums__ERD,
-    &be_int8_bigEndian_ex_nums__ERD
-};
-
-static const ERD bigEndian_ex_nums__ERD = {
+    &be_double_bigEndian_ex_nums_ERD,
+    &be_float_bigEndian_ex_nums_ERD,
+    &be_uint64_bigEndian_ex_nums_ERD,
+    &be_uint32_bigEndian_ex_nums_ERD,
+    &be_uint16_bigEndian_ex_nums_ERD,
+    &be_uint8_bigEndian_ex_nums_ERD,
+    &be_int64_bigEndian_ex_nums_ERD,
+    &be_int32_bigEndian_ex_nums_ERD,
+    &be_int16_bigEndian_ex_nums_ERD,
+    &be_int8_bigEndian_ex_nums_ERD
+};
+
+static const ERD bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "bigEndian", // namedQName.local
         NULL, // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    10,                               // numChildren
-    bigEndian_offsets,                      // offsets
-    bigEndian_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&bigEndian_initSelf,       // initSelf
-    (ERDParseSelf)&bigEndian_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    10, // numChildren
+    bigEndian_offsets, // offsets
+    bigEndian_childrenERDs, // childrenERDs
+    (ERDInitSelf)&bigEndian_initSelf, // initSelf
+    (ERDParseSelf)&bigEndian_parseSelf, // parseSelf
     (ERDUnparseSelf)&bigEndian_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
-static const ERD le_uint64_littleEndian_ex_nums__ERD = {
+static const ERD le_uint64_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint32_littleEndian_ex_nums__ERD = {
+static const ERD le_uint32_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint16_littleEndian_ex_nums__ERD = {
+static const ERD le_uint16_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint8_littleEndian_ex_nums__ERD = {
+static const ERD le_uint8_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_uint8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_UINT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int64_littleEndian_ex_nums__ERD = {
+static const ERD le_int64_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int64", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int32_littleEndian_ex_nums__ERD = {
+static const ERD le_int32_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int32", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int16_littleEndian_ex_nums__ERD = {
+static const ERD le_int16_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int16", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int8_littleEndian_ex_nums__ERD = {
+static const ERD le_int8_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_int8", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_INT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_float_littleEndian_ex_nums__ERD = {
+static const ERD le_float_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_float", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_FLOAT, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_double_littleEndian_ex_nums__ERD = {
+static const ERD le_double_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "le_double", // namedQName.local
         NULL, // namedQName.ns
     },
     PRIMITIVE_DOUBLE, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
+    0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const littleEndian littleEndian_compute_offsets;
 
-static const ptrdiff_t littleEndian_offsets[10] = {
+static const size_t littleEndian_offsets[10] = {
     (const char *)&littleEndian_compute_offsets.le_uint64 - (const char *)&littleEndian_compute_offsets,
     (const char *)&littleEndian_compute_offsets.le_uint32 - (const char *)&littleEndian_compute_offsets,
     (const char *)&littleEndian_compute_offsets.le_uint16 - (const char *)&littleEndian_compute_offsets,
@@ -462,71 +355,77 @@ static const ptrdiff_t littleEndian_offsets[10] = {
 };
 
 static const ERD *littleEndian_childrenERDs[10] = {
-    &le_uint64_littleEndian_ex_nums__ERD,
-    &le_uint32_littleEndian_ex_nums__ERD,
-    &le_uint16_littleEndian_ex_nums__ERD,
-    &le_uint8_littleEndian_ex_nums__ERD,
-    &le_int64_littleEndian_ex_nums__ERD,
-    &le_int32_littleEndian_ex_nums__ERD,
-    &le_int16_littleEndian_ex_nums__ERD,
-    &le_int8_littleEndian_ex_nums__ERD,
-    &le_float_littleEndian_ex_nums__ERD,
-    &le_double_littleEndian_ex_nums__ERD
-};
-
-static const ERD littleEndian_ex_nums__ERD = {
+    &le_uint64_littleEndian_ex_nums_ERD,
+    &le_uint32_littleEndian_ex_nums_ERD,
+    &le_uint16_littleEndian_ex_nums_ERD,
+    &le_uint8_littleEndian_ex_nums_ERD,
+    &le_int64_littleEndian_ex_nums_ERD,
+    &le_int32_littleEndian_ex_nums_ERD,
+    &le_int16_littleEndian_ex_nums_ERD,
+    &le_int8_littleEndian_ex_nums_ERD,
+    &le_float_littleEndian_ex_nums_ERD,
+    &le_double_littleEndian_ex_nums_ERD
+};
+
+static const ERD littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "littleEndian", // namedQName.local
         NULL, // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    10,                               // numChildren
-    littleEndian_offsets,                      // offsets
-    littleEndian_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&littleEndian_initSelf,       // initSelf
-    (ERDParseSelf)&littleEndian_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    10, // numChildren
+    littleEndian_offsets, // offsets
+    littleEndian_childrenERDs, // childrenERDs
+    (ERDInitSelf)&littleEndian_initSelf, // initSelf
+    (ERDParseSelf)&littleEndian_parseSelf, // parseSelf
     (ERDUnparseSelf)&littleEndian_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
 static const ex_nums ex_nums_compute_offsets;
 
-static const ptrdiff_t ex_nums_offsets[3] = {
+static const size_t ex_nums_offsets[3] = {
     (const char *)&ex_nums_compute_offsets.array - (const char *)&ex_nums_compute_offsets,
     (const char *)&ex_nums_compute_offsets.bigEndian - (const char *)&ex_nums_compute_offsets,
     (const char *)&ex_nums_compute_offsets.littleEndian - (const char *)&ex_nums_compute_offsets
 };
 
 static const ERD *ex_nums_childrenERDs[3] = {
-    &array_ex_nums__ERD,
-    &bigEndian_ex_nums__ERD,
-    &littleEndian_ex_nums__ERD
+    &array_ex_nums_ERD,
+    &bigEndian_ex_nums_ERD,
+    &littleEndian_ex_nums_ERD
 };
 
-static const ERD ex_nums__ERD = {
+static const ERD ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
         "ex_nums", // namedQName.local
         "http://example.com", // namedQName.ns
     },
-    COMPLEX,                         // typeCode
-    3,                               // numChildren
-    ex_nums_offsets,                      // offsets
-    ex_nums_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&ex_nums_initSelf,       // initSelf
-    (ERDParseSelf)&ex_nums_parseSelf,     // parseSelf
+    COMPLEX, // typeCode
+    3, // numChildren
+    ex_nums_offsets, // offsets
+    ex_nums_childrenERDs, // childrenERDs
+    (ERDInitSelf)&ex_nums_initSelf, // initSelf
+    (ERDParseSelf)&ex_nums_parseSelf, // parseSelf
     (ERDUnparseSelf)&ex_nums_unparseSelf, // unparseSelf
+    NULL // initChoice
 };
 
 // Return a root element to be used for parsing or unparsing
 
-extern InfosetBase *
+InfosetBase *
 rootElement(void)
 {
-    static ex_nums instance;
-    InfosetBase *root = &instance._base;
-    ex_nums__ERD.initSelf(root);
-    return root;
+    static bool initialized;
+    static ex_nums root;
+    if (!initialized)
+    {
+        ex_nums_initSelf(&root);
+        initialized = true;
+    }
+    return &root._base;
 }
 
 // Methods to initialize, parse, and unparse infoset nodes
@@ -534,13 +433,13 @@ rootElement(void)
 static void
 array_initSelf(array *instance)
 {
+    instance->_base.erd = &array_ex_nums_ERD;
     instance->be_int16[0] = 0xCCCC;
     instance->be_int16[1] = 0xCCCC;
     instance->be_int16[2] = 0xCCCC;
     instance->be_float[0] = NAN;
     instance->be_float[1] = NAN;
     instance->be_float[2] = NAN;
-    instance->_base.erd = &array_ex_nums__ERD;
 }
 
 static void
@@ -568,6 +467,7 @@ array_unparseSelf(const array *instance, UState *ustate)
 static void
 bigEndian_initSelf(bigEndian *instance)
 {
+    instance->_base.erd = &bigEndian_ex_nums_ERD;
     instance->be_double = NAN;
     instance->be_float = NAN;
     instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
@@ -578,7 +478,6 @@ bigEndian_initSelf(bigEndian *instance)
     instance->be_int32 = 0xCCCCCCCC;
     instance->be_int16 = 0xCCCC;
     instance->be_int8 = 0xCC;
-    instance->_base.erd = &bigEndian_ex_nums__ERD;
 }
 
 static void
@@ -614,6 +513,7 @@ bigEndian_unparseSelf(const bigEndian *instance, UState *ustate)
 static void
 littleEndian_initSelf(littleEndian *instance)
 {
+    instance->_base.erd = &littleEndian_ex_nums_ERD;
     instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
     instance->le_uint32 = 0xCCCCCCCC;
     instance->le_uint16 = 0xCCCC;
@@ -624,7 +524,6 @@ littleEndian_initSelf(littleEndian *instance)
     instance->le_int8 = 0xCC;
     instance->le_float = NAN;
     instance->le_double = NAN;
-    instance->_base.erd = &littleEndian_ex_nums__ERD;
 }
 
 static void
@@ -660,10 +559,10 @@ littleEndian_unparseSelf(const littleEndian *instance, UState *ustate)
 static void
 ex_nums_initSelf(ex_nums *instance)
 {
+    instance->_base.erd = &ex_nums_ERD;
     array_initSelf(&instance->array);
     bigEndian_initSelf(&instance->bigEndian);
     littleEndian_initSelf(&instance->littleEndian);
-    instance->_base.erd = &ex_nums__ERD;
 }
 
 static void
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.h b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
index 9e2c1bb..403da6b 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.h
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
@@ -21,7 +21,7 @@
 #include "infoset.h"  // for InfosetBase
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-// Define some infoset structures
+// Define infoset structures
 
 typedef struct array
 {
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
index 385657c..7756780 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
@@ -32,6 +32,11 @@ import org.apache.daffodil.util.Misc
 import org.apache.daffodil.xml.RefQName
 
 /**
+ * We need a mutux object for exclusive access to a code block
+  */
+private object mutex {}
+
+/**
  * Generates and compiles C source files from a DFDL schema encapsulated in a [[Root]].
  * Implements the [[DFDL.CodeGenerator]] trait to allow it to be called by Daffodil code.
  * @param root Provides the DFDL schema for code generation
@@ -43,8 +48,10 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
   private var diagnostics: Seq[Diagnostic] = Nil
   private var errorStatus: Boolean = false
 
-  // Writes C source files into a "c" subdirectory of the given output directory.
-  // Removes the "c" subdirectory if it existed before.  Returns the "c" subdirectory.
+  /**
+   * Writes C source files into a "c" subdirectory of the given output directory.
+   * Removes the "c" subdirectory if it existed before.  Returns the "c" subdirectory.
+  */
   override def generateCode(rootNS: Option[RefQName], outputDirArg: String): os.Path = {
     // Get the paths of the output directory and its code subdirectory
     val outputDir = os.Path(Paths.get(outputDirArg).toAbsolutePath)
@@ -55,19 +62,22 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     os.remove.all(codeDir)
 
     // Copy our resource directory and all its C source files to our code subdirectory
+    // (using synchronized to avoid calling FileSystems.newFileSystem concurrently)
     val resourceUri = Misc.getRequiredResource("/c")
-    val fileSystem = if (resourceUri.getScheme == "jar") {
-      val env: java.util.Map[String, String] = Collections.emptyMap()
-      FileSystems.newFileSystem(resourceUri, env)
-    } else {
-      null
-    }
-    try {
-      val resourceDir = os.Path(if (fileSystem != null) fileSystem.getPath("/c") else Paths.get(resourceUri))
-      os.copy(resourceDir, codeDir)
+    mutex.synchronized {
+      val fileSystem = if (resourceUri.getScheme == "jar") {
+        val env: java.util.Map[String, String] = Collections.emptyMap()
+        FileSystems.newFileSystem(resourceUri, env)
+      } else {
+        null
+      }
+      try {
+        val resourceDir = os.Path(if (fileSystem != null) fileSystem.getPath("/c") else Paths.get(resourceUri))
+        os.copy(resourceDir, codeDir)
+      }
+      finally
+        if (fileSystem != null) fileSystem.close()
     }
-    finally
-      if (fileSystem != null) fileSystem.close()
 
     // Generate C code from the DFDL schema
     val rootElementName = rootNS.getOrElse(root.refQName).local
@@ -86,8 +96,10 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     codeDir
   }
 
-  // Compiles any C source files inside the given code directory.  Returns the path
-  // of the newly created executable to use in TDML tests or somewhere else.
+  /**
+   * Compiles any C source files inside the given code directory.  Returns the path
+   * of the newly created executable to use in TDML tests or somewhere else.
+   */
   override def compileCode(codeDir: os.Path): os.Path = {
     // Get the path of the executable we will build
     val exe = if (isWindows) codeDir/"daffodil.exe" else codeDir/"daffodil"
@@ -96,7 +108,7 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
       // Assemble the compiler's command line arguments
       val compiler = pickCompiler
       val files = os.walk(codeDir).filter(_.ext == "c")
-      val libs = Seq("-lmxml", if (isWindows) "-largp" else "-lpthread")
+      val libs = if (isWindows) Seq("-largp", "-lmxml") else Seq("-lmxml")
 
       // Run the compiler in the code directory (if we found "zig cc"
       // as a compiler, it will cache previously built files in zig's
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
index 65c2c1c..633cc28 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
@@ -51,7 +51,7 @@ object Runtime2CodeGenerator
     with SeqCompCodeGenerator {
 
   @tailrec
-  def generateCode(gram: Gram, state: CodeGeneratorState): Unit =
+  def generateCode(gram: Gram, state: CodeGeneratorState): Unit = {
     gram match {
       case g: RootGrammarMixin => Runtime2CodeGenerator.generateCode(g.documentElement, state)
       case g: Prod if (g.guard) => Runtime2CodeGenerator.generateCode(g.gram, state)
@@ -70,6 +70,7 @@ object Runtime2CodeGenerator
       case _: CaptureValueLengthEnd => noop
       case _ => gram.SDE("Code generation not supported for: %s", Misc.getNameFromClass(gram))
     }
+  }
 
   private def noop: Unit = {
     // Not generating code here, but can use as a breakpoint
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
index a1db02c..5142db7 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -17,14 +17,19 @@
 
 package org.apache.daffodil.runtime2.generators
 
+import org.apache.daffodil.cookers.ChoiceBranchKeyCooker
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.dsom.AbstractElementRef
+import org.apache.daffodil.dsom.Choice
 import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.dsom.GlobalComplexTypeDef
 import org.apache.daffodil.dsom.GlobalElementDecl
 import org.apache.daffodil.dsom.SchemaComponent
 import org.apache.daffodil.exceptions.ThrowsSDE
 import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 
+import java.net.URI
 import scala.collection.mutable
 
 /**
@@ -37,12 +42,13 @@ class CodeGeneratorState {
   private val finalStructs = mutable.ArrayBuffer[String]()
   private val finalImplementation = mutable.ArrayBuffer[String]()
 
-  // Builds a name for the given element that needs to be unique in C file scope
-  private def qualifiedName(context: ElementBase): String = {
+  // Builds an ERD name for the given element that needs to be unique in C file scope
+  private def erdName(context: ElementBase): String = {
     def buildName(sc: SchemaComponent, sb: StringBuilder): StringBuilder = {
       sc match {
-        case gd: GlobalElementDecl => sb ++= gd.namedQName.local += '_'
         case eb: ElementBase => sb ++= eb.namedQName.local += '_'
+        case gd: GlobalElementDecl => sb ++= gd.namedQName.local += '_'
+        case ct: GlobalComplexTypeDef => sb ++= ct.namedQName.local += '_'
         case _ => // don't include other schema components in qualified name
       }
       sc.optLexicalParent.foreach {
@@ -50,7 +56,7 @@ class CodeGeneratorState {
       }
       sb
     }
-    val sb = buildName(context, new StringBuilder)
+    val sb = buildName(context, new StringBuilder) ++= "ERD"
     sb.toString()
   }
 
@@ -60,20 +66,36 @@ class CodeGeneratorState {
   def addImplementation(context: ElementBase): Unit = {
     val C = localName(context)
     val initStatements = structs.top.initStatements.mkString("\n")
+    val initChoiceStatements = structs.top.initChoiceStatements.mkString("\n")
     val parserStatements = structs.top.parserStatements.mkString("\n")
     val unparserStatements = structs.top.unparserStatements.mkString("\n")
+    val hasChoice = structs.top.initChoiceStatements.nonEmpty
+    val root = structs.elems.last.C
+    val prototypeInitChoice = if (hasChoice)
+      s"\nstatic bool ${C}_initChoice($C *instance, const $root *rootElement);"
+    else
+      ""
+    val implementInitChoice = if (hasChoice)
+      s"""
+         |static bool
+         |${C}_initChoice($C *instance, const $root *rootElement)
+         |{
+         |$initChoiceStatements
+         |}
+         |""".stripMargin
+    else
+      ""
     val prototypeFunctions =
-      s"""static void ${C}_initSelf($C *instance);
+      s"""static void ${C}_initSelf($C *instance);$prototypeInitChoice
          |static void ${C}_parseSelf($C *instance, PState *pstate);
          |static void ${C}_unparseSelf(const $C *instance, UState *ustate);""".stripMargin
-    prototypes += prototypeFunctions
     val functions =
       s"""static void
          |${C}_initSelf($C *instance)
          |{
          |$initStatements
          |}
-         |
+         |$implementInitChoice
          |static void
          |${C}_parseSelf($C *instance, PState *pstate)
          |{
@@ -86,6 +108,8 @@ class CodeGeneratorState {
          |$unparserStatements
          |}
          |""".stripMargin
+
+    prototypes += prototypeFunctions
     finalImplementation += functions
   }
 
@@ -105,17 +129,155 @@ class CodeGeneratorState {
     qnameInit
   }
 
+  /**
+   * We want to convert a choiceDispatchKey expression into C struct dot
+   * notation (rootElement->[subElement.field]) which will access the C
+   * struct field containing the choiceDispatchKey's runtime value.
+   *
+   * We make some assumptions to make generating the dot notation easier:
+   * - the expression starts with '{xs:string( and ends with )}'
+   * - the expression returns the value of a previous element without
+   *   changing the value in any way (except converting it to xs:string)
+   * - both the expression and the C code use only local names (for now...)
+   * - we can map the context node's path to a Unix-like slash path
+   * - all dpath operations look like Unix-like relative paths (../tag)
+   * - we can normalize the new path and convert it to C struct dot notation
+   * - we can store the accessed value in an int64_t local variable safely
+   */
+  private def choiceDispatchField(context: ElementBase): String = {
+    // We want to use SchemaComponent.scPath but it's private so duplicate it here (for now...)
+    def scPath(sc: SchemaComponent): Seq[SchemaComponent] = sc.optLexicalParent.map { scPath }.getOrElse(Nil) :+ sc
+    val localNames = scPath(context).map {
+      case er: AbstractElementRef => er.refQName.local
+      case e: ElementBase => e.namedQName.local
+      case ed: GlobalElementDecl => ed.namedQName.local
+      case _ => ""
+    }
+    val absoluteSlashPath = localNames.mkString("/")
+    val dispatchSlashPath = context.complexType.modelGroup match {
+      case choice: Choice if choice.isDirectDispatch =>
+        val expr = choice.choiceDispatchKeyEv.expr.toBriefXML()
+        val before = "'{xs:string("
+        val after = ")}'"
+        val relativePath = if (expr.startsWith(before) && expr.endsWith(after))
+          expr.substring(before.length, expr.length - after.length) else expr
+        val normalizedURI = new URI(absoluteSlashPath + "/" + relativePath).normalize
+        normalizedURI.getPath.substring(1)
+      case _ => ""
+    }
+    // Strip namespace prefixes since C code uses only local names (for now...)
+    val localDispatchSlashPath = dispatchSlashPath.replaceAll("/[^:]+:", "/")
+    val res = localDispatchSlashPath.replace('/', '.')
+    res
+  }
+
+  def addBeforeSwitchStatements(context: ElementBase): Unit = {
+    val erd = erdName(context)
+    val initStatement = s"    instance->_base.erd = &$erd;"
+
+    structs.top.initStatements += initStatement
+
+    val dispatchField = choiceDispatchField(context)
+    if (dispatchField.nonEmpty) {
+      val C = localName(context)
+      val declaration =
+        s"""    size_t      _choice; // choice of which union field to use
+           |    union
+           |    {""".stripMargin
+      val erdDef =
+        s"""static const ERD _choice_$erd = {
+           |    {
+           |        NULL, // namedQName.prefix
+           |        "_choice", // namedQName.local
+           |        NULL, // namedQName.ns
+           |    },
+           |    CHOICE, // typeCode
+           |    0, NULL, NULL, NULL, NULL, NULL, NULL
+           |};
+           |""".stripMargin
+      val offsetComputation = s"    (const char *)&${C}_compute_offsets._choice - (const char *)&${C}_compute_offsets"
+      val erdComputation = s"    &_choice_$erd"
+      val initStatement = s"    instance->_choice = NO_CHOICE;"
+      val initChoiceStatement =
+        s"""    int64_t key = rootElement->$dispatchField;
+           |    switch (key)
+           |    {""".stripMargin
+      val parseStatement =
+        s"""    instance->_base.erd->initChoice(&instance->_base, rootElement());
+           |    switch (instance->_choice)
+           |    {""".stripMargin
+      val unparseStatement =
+        s"""    instance->_base.erd->initChoice(&instance->_base, rootElement());
+           |    switch (instance->_choice)
+           |    {""".stripMargin
+
+      erds += erdDef
+      structs.top.declarations += declaration
+      structs.top.offsetComputations += offsetComputation
+      structs.top.erdComputations += erdComputation
+      structs.top.initStatements += initStatement
+      structs.top.initChoiceStatements += initChoiceStatement
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+  }
+
+  def addAfterSwitchStatements(): Unit = {
+    if (structs.top.initChoiceStatements.nonEmpty) {
+      val declaration = s"    };"
+      val initChoiceStatement =
+        s"""    default:
+           |        instance->_choice = NO_CHOICE;
+           |        break;
+           |    }
+           |
+           |    if (instance->_choice != NO_CHOICE)
+           |    {
+           |        const size_t choice = instance->_choice + 1; // skip the _choice field
+           |        const size_t offset = instance->_base.erd->offsets[choice];
+           |        const ERD *  childERD = instance->_base.erd->childrenERDs[choice];
+           |        InfosetBase *childNode = (InfosetBase *)((const char *)instance + offset);
+           |        childNode->erd = childERD;
+           |        return true;
+           |    }
+           |    else
+           |    {
+           |        return false;
+           |    }""".stripMargin
+      val parseStatement =
+        s"""    default:
+           |        pstate->error_msg =
+           |            "Parse error: no match between choice dispatch key and any branch key";
+           |        break;
+           |    }""".stripMargin
+      val unparseStatement =
+        s"""    default:
+           |        ustate->error_msg =
+           |            "Unparse error: no match between choice dispatch key and any branch key";
+           |        break;
+           |    }""".stripMargin
+
+      structs.top.declarations += declaration
+      structs.top.initChoiceStatements += initChoiceStatement
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+  }
+
   def addComplexTypeERD(context: ElementBase): Unit = {
     val C = localName(context)
-    val qn = qualifiedName(context)
+    val erd = erdName(context)
     val count = structs.top.offsetComputations.length
     val offsetComputations = structs.top.offsetComputations.mkString(",\n")
     val erdComputations = structs.top.erdComputations.mkString(",\n")
     val qnameInit = defineQNameInit(context)
+    val hasChoice = structs.top.initChoiceStatements.nonEmpty
+    val numChildren = if (hasChoice) 2 else count
+    val initChoice = if (hasChoice) s"(InitChoiceRD)&${C}_initChoice" else "NULL"
     val complexERD =
       s"""static const $C ${C}_compute_offsets;
          |
-         |static const ptrdiff_t ${C}_offsets[$count] = {
+         |static const size_t ${C}_offsets[$count] = {
          |$offsetComputations
          |};
          |
@@ -123,23 +285,24 @@ class CodeGeneratorState {
          |$erdComputations
          |};
          |
-         |static const ERD ${qn}_ERD = {
+         |static const ERD $erd = {
          |$qnameInit
-         |    COMPLEX,                         // typeCode
-         |    $count,                               // numChildren
-         |    ${C}_offsets,                      // offsets
-         |    ${C}_childrenERDs,                 // childrenERDs
-         |    (ERDInitSelf)&${C}_initSelf,       // initSelf
-         |    (ERDParseSelf)&${C}_parseSelf,     // parseSelf
+         |    COMPLEX, // typeCode
+         |    $numChildren, // numChildren
+         |    ${C}_offsets, // offsets
+         |    ${C}_childrenERDs, // childrenERDs
+         |    (ERDInitSelf)&${C}_initSelf, // initSelf
+         |    (ERDParseSelf)&${C}_parseSelf, // parseSelf
          |    (ERDUnparseSelf)&${C}_unparseSelf, // unparseSelf
+         |    $initChoice // initChoice
          |};
          |""".stripMargin
+
     erds += complexERD
   }
 
   def addStruct(context: ElementBase): Unit = {
     val C = localName(context)
-    val qn = qualifiedName(context)
     val declarations = structs.top.declarations.mkString("\n")
     val struct =
       s"""typedef struct $C
@@ -148,9 +311,8 @@ class CodeGeneratorState {
          |$declarations
          |} $C;
          |""".stripMargin
+
     finalStructs += struct
-    val initStatement = s"    instance->_base.erd = &${qn}_ERD;"
-    structs.top.initStatements += initStatement
   }
 
   def addSimpleTypeStatements(initStatement: String, parseStatement: String, unparseStatement: String): Unit = {
@@ -162,10 +324,31 @@ class CodeGeneratorState {
   def addComplexTypeStatements(child: ElementBase): Unit = {
     val C = localName(child)
     val e = child.name
+    val hasChoice = structs.top.initChoiceStatements.nonEmpty
+    val offset = if (hasChoice) child.position - 1 else -1
     val initStatement = s"    ${C}_initSelf(&instance->$e);"
-    val parseStatement = s"    ${C}_parseSelf(&instance->$e, pstate);"
-    val unparseStatement = s"    ${C}_unparseSelf(&instance->$e, ustate);"
+    val initChoiceStatement =
+      s"""        instance->_choice = $offset;
+         |        break;""".stripMargin
+    val parseStatement = if (hasChoice)
+      s"""    case $offset:
+         |        ${C}_parseSelf(&instance->$e, pstate);
+         |        break;""".stripMargin
+    else
+      s"    ${C}_parseSelf(&instance->$e, pstate);"
+    val unparseStatement = if (hasChoice)
+      s"""    case $offset:
+         |        ${C}_unparseSelf(&instance->$e, ustate);
+         |        break;""".stripMargin
+    else
+      s"    ${C}_unparseSelf(&instance->$e, ustate);"
+
     structs.top.initStatements += initStatement
+    if (hasChoice) {
+      structs.top.initChoiceStatements ++= ChoiceBranchKeyCooker.convertConstant(
+        child.choiceBranchKey, child, forUnparse = false).map { key => s"    case $key:"}
+      structs.top.initChoiceStatements += initChoiceStatement
+    }
     structs.top.parserStatements += parseStatement
     structs.top.unparserStatements += unparseStatement
   }
@@ -175,12 +358,12 @@ class CodeGeneratorState {
     structs.push(new ComplexCGState(C))
   }
 
-  def popComplexElement(context: ElementBase): Unit = {
+  def popComplexElement(): Unit = {
     structs.pop()
   }
 
   def addSimpleTypeERD(context: ElementBase): Unit = {
-    val qn = qualifiedName(context)
+    val erd = erdName(context)
     val qnameInit = defineQNameInit(context)
     val typeCode = context.optPrimType.get match {
       case PrimType.UnsignedLong => "PRIMITIVE_UINT64"
@@ -195,30 +378,25 @@ class CodeGeneratorState {
       case PrimType.Double => "PRIMITIVE_DOUBLE"
       case p: PrimType => context.SDE("PrimType %s not supported yet.", p.toString)
     }
-    val erd =
-      s"""static const ERD ${qn}_ERD = {
+    val erdDef =
+      s"""static const ERD $erd = {
          |$qnameInit
          |    $typeCode, // typeCode
-         |    0,               // numChildren
-         |    NULL,            // offsets
-         |    NULL,            // childrenERDs
-         |    NULL,            // initSelf
-         |    NULL,            // parseSelf
-         |    NULL,            // unparseSelf
+         |    0, NULL, NULL, NULL, NULL, NULL, NULL
          |};
          |""".stripMargin
-    erds += erd
+    erds += erdDef
     addComputations(context)
   }
 
   def addComputations(child: ElementBase): Unit = {
     val C = structs.top.C
     val e = localName(child)
-    val qn = qualifiedName(child)
+    val erd = erdName(child)
     val arraySize = if (child.occursCountKind == OccursCountKind.Fixed) child.maxOccurs else 0
     def addComputation(deref: String): Unit = {
       val offsetComputation = s"    (const char *)&${C}_compute_offsets.$e$deref - (const char *)&${C}_compute_offsets"
-      val erdComputation = s"    &${qn}_ERD"
+      val erdComputation = s"    &$erd"
       structs.top.offsetComputations += offsetComputation
       structs.top.erdComputations += erdComputation
     }
@@ -250,7 +428,10 @@ class CodeGeneratorState {
     }
     val e = child.name
     val arrayDef = if (child.occursCountKind == OccursCountKind.Fixed) s"[${child.maxOccurs}]" else ""
-    structs.top.declarations += s"    $definition $e$arrayDef;"
+    val indent = if (structs.top.initChoiceStatements.nonEmpty) "    " else ""
+    val declaration = s"$indent    $definition $e$arrayDef;"
+
+    structs.top.declarations += declaration
   }
 
   def generateCodeHeader: String = {
@@ -262,7 +443,7 @@ class CodeGeneratorState {
          |#include "infoset.h"  // for InfosetBase
          |#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-         |// Define some infoset structures
+         |// Define infoset structures
          |
          |$structs
          |#endif // GENERATED_CODE_H
@@ -279,7 +460,8 @@ class CodeGeneratorState {
          |#include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
          |#include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
          |#include <math.h>       // for NAN
-         |#include <stddef.h>     // for NULL, ptrdiff_t
+         |#include <stdbool.h>    // for bool, false, true
+         |#include <stddef.h>     // for NULL, size_t
          |
          |// Prototypes needed for compilation
          |
@@ -290,13 +472,17 @@ class CodeGeneratorState {
          |$erds
          |// Return a root element to be used for parsing or unparsing
          |
-         |extern InfosetBase *
+         |InfosetBase *
          |rootElement(void)
          |{
-         |    static $rootElementName instance;
-         |    InfosetBase *root = &instance._base;
-         |    ${rootElementName}__ERD.initSelf(root);
-         |    return root;
+         |    static bool initialized;
+         |    static $rootElementName root;
+         |    if (!initialized)
+         |    {
+         |        ${rootElementName}_initSelf(&root);
+         |        initialized = true;
+         |    }
+         |    return &root._base;
          |}
          |
          |// Methods to initialize, parse, and unparse infoset nodes
@@ -316,6 +502,7 @@ class ComplexCGState(val C: String) {
   val offsetComputations = mutable.ArrayBuffer[String]()
   val erdComputations = mutable.ArrayBuffer[String]()
   val initStatements = mutable.ArrayBuffer[String]()
+  val initChoiceStatements = mutable.ArrayBuffer[String]()
   val parserStatements = mutable.ArrayBuffer[String]()
   val unparserStatements = mutable.ArrayBuffer[String]()
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
index b1157d1..26203f8 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
@@ -40,6 +40,7 @@ trait ElementParseAndUnspecifiedLengthCodeGenerator {
       Runtime2CodeGenerator.generateCode(elementContentGram, cgState) // initSelf, parseSelf, unparseSelf
     } else {
       cgState.pushComplexElement(context)
+      cgState.addBeforeSwitchStatements(context) // switch statements for choices
       context.elementChildren.foreach { child =>
         if (!child.isSimpleType) {
           cgState.addComplexTypeStatements(child) // recursive calls to parse, unparse, init
@@ -48,10 +49,11 @@ trait ElementParseAndUnspecifiedLengthCodeGenerator {
         cgState.addFieldDeclaration(context, child) // struct member for child
         Runtime2CodeGenerator.generateCode(child.enclosedElement, cgState) // generate children too
       }
+      cgState.addAfterSwitchStatements() // switch statements for choices
       cgState.addStruct(context) // struct definition
       cgState.addImplementation(context) // initSelf, parseSelf, unparseSelf
       cgState.addComplexTypeERD(context) // ERD static initializer
-      cgState.popComplexElement(context)
+      cgState.popComplexElement()
     }
   }
 }
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
similarity index 68%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
index 09021a3..3d12954 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
@@ -18,8 +18,8 @@
 
 <tdml:testSuite
   defaultImplementations="daffodil daffodil-runtime2"
-  defaultRoundTrip="onePass"
-  description="TDML tests for daffodil-runtime2"
+  defaultRoundTrip="none"
+  description="TDML tests for ex_nums"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,27 +37,23 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    config="config-runtime1"
-    description="ex_nums parse test with runtime1"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_parse1"
-    root="ex_nums">
+    name="ex_nums_parse_runtime1"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime1">
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    config="config-runtime1"
-    description="ex_nums unparse test with runtime1"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_unparse1"
-    root="ex_nums">
+    name="ex_nums_unparse_runtime1"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime1">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
@@ -65,27 +61,23 @@
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    config="config-runtime2"
-    description="ex_nums parse test with runtime2"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_parse2"
-    root="ex_nums">
+    name="ex_nums_parse_runtime2"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime2">
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    config="config-runtime2"
-    description="ex_nums unparse test with runtime2"
-    model="TestRuntime2.dfdl.xsd"
-    name="ex_nums_unparse2"
-    root="ex_nums">
+    name="ex_nums_unparse_runtime2"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime2">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
       <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.dfdl.xsd
new file mode 100644
index 0000000..2faebc7
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.dfdl.xsd
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+
+  <xs:simpleType name="double" dfdl:length="64" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:double"/>
+  </xs:simpleType>
+
+  <xs:simpleType name="int32" dfdl:length="32" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:int"/>
+  </xs:simpleType>
+
+  <xs:complexType name="FooType">
+    <xs:sequence>
+      <xs:element name="a" type="idl:int32"/>
+      <xs:element name="b" type="idl:int32"/>
+      <xs:element name="c" type="idl:int32"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="BarType">
+    <xs:sequence>
+      <xs:element name="x" type="idl:double"/>
+      <xs:element name="y" type="idl:double"/>
+      <xs:element name="z" type="idl:double"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="NestedStructType">
+    <xs:sequence>
+      <xs:element name="data">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="foo" type="idl:FooType"/>
+            <xs:element name="bar" type="idl:BarType"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="NestedUnionType">
+    <xs:sequence>
+      <xs:element name="tag" type="idl:int32"/>
+      <xs:element name="data">
+        <xs:complexType>
+          <xs:choice dfdl:choiceDispatchKey="{xs:string(../tag)}">
+            <xs:element name="foo" type="idl:FooType" dfdl:choiceBranchKey="1 2"/>
+            <xs:element name="bar" type="idl:BarType" dfdl:choiceBranchKey="3 4"/>
+          </xs:choice>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:element name="NestedStruct" type="idl:NestedStructType"/>
+
+  <xs:element name="NestedUnion" type="idl:NestedUnionType"/>
+
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.tdml
similarity index 54%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.tdml
index 110322d..91adc0b 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested.tdml
@@ -19,8 +19,8 @@
 <tdml:testSuite
   defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
-  defaultRoundTrip="onePass"
-  description="TDML tests for orion-command"
+  defaultRoundTrip="none"
+  description="TDML tests for nested"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,55 +37,57 @@
     </daf:tunables>
   </tdml:defineConfig>
 
-  <tdml:parserTestCase
-    description="orion-command Command parse test"
-    model="orion-command.dfdl.xsd"
-    name="command_parse"
-    root="Command">
+  <tdml:parserTestCase name="nested_struct_parse" model="nested.dfdl.xsd">
     <tdml:document>
-      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_struct_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_struct_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
-  <tdml:unparserTestCase
-    description="orion-command Command unparse test"
-    model="orion-command.dfdl.xsd"
-    name="command_unparse"
-    root="Command">
+  <tdml:unparserTestCase name="nested_struct_unparse" model="nested.dfdl.xsd">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_struct_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_struct_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
-  <tdml:parserTestCase
-    description="orion-command VideoSettings parse test"
-    model="orion-command.dfdl.xsd"
-    name="video_settings_parse"
-    root="VideoSettings">
+  <tdml:parserTestCase name="nested_union_parse_2" model="nested.dfdl.xsd">
     <tdml:document>
-      <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_union_parse_2.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
-  <tdml:unparserTestCase
-    description="orion-command VideoSettings unparse test"
-    model="orion-command.dfdl.xsd"
-    name="video_settings_unparse"
-    root="VideoSettings">
+  <tdml:unparserTestCase name="nested_union_unparse_2" model="nested.dfdl.xsd">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">nested_union_parse_2.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase name="nested_union_parse_4" model="nested.dfdl.xsd">
+    <tdml:document>
+      <tdml:documentPart type="file">nested_union_parse_4.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_4.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase name="nested_union_unparse_4" model="nested.dfdl.xsd">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">nested_union_unparse_4.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">nested_union_parse_4.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat
new file mode 100644
index 0000000..1782b59
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_unparse.xml
similarity index 75%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_unparse.xml
index 9a1d4a1..89f2902 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_unparse.xml
@@ -16,15 +16,17 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<idl:NestedStruct xmlns:idl="urn:idl:1.0">
+  <data>
+    <foo>
+      <a>1</a>
+      <b>2</b>
+      <c>3</c>
+    </foo>
+    <bar>
+      <x>4.5</x>
+      <y>5.5</y>
+      <z>6.5</z>
+    </bar>
+  </data>
+</idl:NestedStruct>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat
new file mode 100644
index 0000000..08a4355
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat
new file mode 100644
index 0000000..a8d472c
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_2.xml
similarity index 75%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_2.xml
index 9a1d4a1..fe089b3 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_2.xml
@@ -16,15 +16,13 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<idl:NestedUnion xmlns:idl="urn:idl:1.0">
+  <tag>2</tag>
+  <data>
+    <foo>
+      <a>1</a>
+      <b>2</b>
+      <c>3</c>
+    </foo>
+  </data>
+</idl:NestedUnion>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml
similarity index 75%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml
index 9a1d4a1..6688d57 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_unparse_4.xml
@@ -16,15 +16,13 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<idl:NestedUnion xmlns:idl="urn:idl:1.0">
+  <tag>4</tag>
+  <data>
+    <bar>
+      <x>1.5</x>
+      <y>2.5</y>
+      <z>3.5</z>
+    </bar>
+  </data>
+</idl:NestedUnion>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
deleted file mode 100644
index 8b37108..0000000
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
-  <xs:annotation>
-    <xs:appinfo source="http://www.ogf.org/dfdl/">
-      <dfdl:defineFormat name="defaults">
-        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
-      </dfdl:defineFormat>
-      <dfdl:format ref="idl:defaults"/>
-    </xs:appinfo>
-  </xs:annotation>
-  <xs:simpleType name="int8" dfdl:length="8" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:byte"/>
-  </xs:simpleType>
-  <xs:simpleType name="int16" dfdl:length="16" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:short"/>
-  </xs:simpleType>
-  <xs:simpleType name="uint8" dfdl:length="8" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:unsignedByte"/>
-  </xs:simpleType>
-  <xs:simpleType name="uint16" dfdl:length="16" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:unsignedShort"/>
-  </xs:simpleType>
-  <xs:simpleType name="uint32" dfdl:length="32" dfdl:lengthKind="explicit">
-    <xs:restriction base="xs:unsignedInt"/>
-  </xs:simpleType>
-  <xs:element name="Command">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
-        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
-        <xs:element name="id" fixed="1" type="idl:uint8"/>
-        <xs:element name="length" fixed="7" type="idl:uint8"/>
-        <xs:element name="pan" type="idl:int16"/>
-        <xs:element name="tilt">
-          <xs:simpleType>
-            <xs:restriction base="idl:int16">
-              <xs:minInclusive value="-1396"/>
-              <xs:maxInclusive value="733"/>
-            </xs:restriction>
-          </xs:simpleType>
-        </xs:element>
-        <xs:element name="mode" fixed="80" type="idl:uint8"/>
-        <xs:element name="stabilized" fixed="0" type="idl:uint8"/>
-        <xs:element name="impulse" fixed="0" type="idl:uint8"/>
-        <xs:element name="checksum" type="idl:uint16"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-  <xs:element name="CameraState">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
-        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
-        <xs:element name="id" fixed="97" type="idl:uint8"/>
-        <xs:element name="length" fixed="5" type="idl:uint8"/>
-        <xs:element name="zoom" type="idl:int16"/>
-        <xs:element name="focus" type="idl:int16"/>
-        <xs:element name="index" fixed="0" type="idl:uint8"/>
-        <xs:element name="checksum" type="idl:uint16"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-  <xs:element name="VideoSettings">
-    <xs:complexType>
-      <xs:sequence>
-        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
-        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
-        <xs:element name="id" fixed="98" type="idl:uint8"/>
-        <xs:element name="length" fixed="14" type="idl:uint8"/>
-        <xs:element name="destIp">
-          <xs:complexType>
-            <xs:sequence>
-              <xs:element name="item" minOccurs="4" maxOccurs="4" dfdl:occursCountKind="fixed" type="idl:uint8"/>
-            </xs:sequence>
-          </xs:complexType>
-        </xs:element>
-        <xs:element name="port" type="idl:uint16"/>
-        <xs:element name="bitrate" fixed="0" type="idl:uint32"/>
-        <xs:element name="ttl" fixed="0" type="idl:int8"/>
-        <xs:element name="streamType" fixed="0" type="idl:uint8"/>
-        <xs:element name="mjpegQuality" fixed="0" type="idl:uint8"/>
-        <xs:element name="saveSettingsAndTsPacketCount" fixed="0" type="idl:uint8"/>
-        <xs:element name="checksum" type="idl:uint16"/>
-      </xs:sequence>
-    </xs:complexType>
-  </xs:element>
-</xs:schema>
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index f11cd27..cebc082 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -479,7 +479,7 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: DFDLTestSuite)
     // Our TDMLDFDLProcessorFactory implementation is a tunable choice with three values.
     val className = tunableObj.tdmlImplementation match {
       case "daffodil" => "org.apache.daffodil.tdml.processor.TDMLDFDLProcessorFactory"
-      case "daffodil-runtime2" => "org.apache.daffodil.tdml.processor.runtime2.TDMLDFDLProcessorFactory"
+      case "daffodil-runtime2" => "org.apache.daffodil.tdml.processor.Runtime2TDMLDFDLProcessorFactory"
       case "ibm" => "org.apache.daffodil.tdml.processor.ibm.TDMLDFDLProcessorFactory"
     }
 
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
similarity index 92%
rename from daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
rename to daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
index a18698f..f150580 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
+++ b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.tdml.processor.runtime2
+package org.apache.daffodil.tdml.processor
 
 import org.apache.daffodil.api._
 import org.apache.daffodil.compiler.Compiler
@@ -23,13 +23,12 @@ import org.apache.daffodil.externalvars.Binding
 import org.apache.daffodil.runtime2.ParseResult
 import org.apache.daffodil.runtime2.Runtime2DataProcessor
 import org.apache.daffodil.runtime2.UnparseResult
-import org.apache.daffodil.tdml.processor._
 import org.apache.daffodil.xml.QName
 import org.apache.daffodil.xml.XMLUtils
 
 import scala.xml.Node
 
-final class TDMLDFDLProcessorFactory private(
+final class Runtime2TDMLDFDLProcessorFactory private(
   private var compiler: Compiler,
   private var checkAllTopLevel: Boolean,
   validateDFDLSchemasArg: Boolean)
@@ -37,7 +36,7 @@ final class TDMLDFDLProcessorFactory private(
 
   override def validateDFDLSchemas = validateDFDLSchemasArg
 
-  override type R = TDMLDFDLProcessorFactory
+  override type R = Runtime2TDMLDFDLProcessorFactory
 
   override def implementationName = "daffodil-runtime2"
 
@@ -49,7 +48,7 @@ final class TDMLDFDLProcessorFactory private(
     compiler: Compiler = compiler,
     checkAllTopLevel: Boolean = checkAllTopLevel,
     validateDFDLSchemas: Boolean = validateDFDLSchemas) =
-    new TDMLDFDLProcessorFactory(compiler, checkAllTopLevel, validateDFDLSchemas)
+    new Runtime2TDMLDFDLProcessorFactory(compiler, checkAllTopLevel, validateDFDLSchemas)
 
   /**
    * Deprecated methods must be implemented. Some are just stubs though now.
@@ -59,7 +58,7 @@ final class TDMLDFDLProcessorFactory private(
     compiler = compiler.withValidateDFDLSchemas(bool)
   }
 
-  override def withValidateDFDLSchemas(bool: Boolean): TDMLDFDLProcessorFactory = {
+  override def withValidateDFDLSchemas(bool: Boolean): Runtime2TDMLDFDLProcessorFactory = {
     copy(compiler = compiler.withValidateDFDLSchemas(bool))
   }
 
@@ -68,7 +67,7 @@ final class TDMLDFDLProcessorFactory private(
     compiler = compiler.withCheckAllTopLevel(checkAllTopLevel)
   }
 
-  override def withCheckAllTopLevel(checkAllTopLevel: Boolean): TDMLDFDLProcessorFactory = {
+  override def withCheckAllTopLevel(checkAllTopLevel: Boolean): Runtime2TDMLDFDLProcessorFactory = {
     copy(compiler = compiler.withCheckAllTopLevel(checkAllTopLevel))
   }
 
@@ -76,14 +75,14 @@ final class TDMLDFDLProcessorFactory private(
   override def setTunables(tunables: Map[String, String]): Unit =
     compiler = compiler.withTunables(tunables)
 
-  override def withTunables(tunables: Map[String, String]): TDMLDFDLProcessorFactory =
+  override def withTunables(tunables: Map[String, String]): Runtime2TDMLDFDLProcessorFactory =
     copy(compiler = compiler.withTunables(tunables))
 
   @deprecated("Use DaffodilTDMLDFDLProcessor.setExternalDFDLVariables.", "2.6.0")
   override def setExternalDFDLVariables(externalVarBindings: Seq[Binding]): Unit =
     compiler = compiler.withExternalDFDLVariablesImpl(externalVarBindings)
 
-  override def withExternalDFDLVariables(externalVarBindings: Seq[Binding]): TDMLDFDLProcessorFactory =
+  override def withExternalDFDLVariables(externalVarBindings: Seq[Binding]): Runtime2TDMLDFDLProcessorFactory =
     copy(compiler = compiler.withExternalDFDLVariablesImpl(externalVarBindings))
 
   @deprecated("Use arguments to getProcessor()", "2.6.0")
@@ -130,10 +129,10 @@ final class TDMLDFDLProcessorFactory private(
 }
 
 /**
- * Delegates all execution, error gathering, error access to the [[Runtime2DataProcessor]].
- * The responsibility of this class is just for TDML matching up. That is dealing with TDML
- * XML Infosets, feeding to the unparser, creating XML from the result created by the
- * [[Runtime2DataProcessor]]. All the "real work" is done by [[Runtime2DataProcessor]].
+ * Delegates all execution, error gathering, error access to the Runtime2DataProcessor.
+ * The responsibility of this class is just for TDML matching up. That is dealing with
+ * TDML XML Infosets, feeding to the unparser, creating XML from the result created by
+ * the Runtime2DataProcessor. All the "real work" is done by Runtime2DataProcessor.
  */
 class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path) extends TDMLDFDLProcessor {
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat
new file mode 100644
index 0000000..83b308f
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
similarity index 82%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
index 9a1d4a1..01f3fd0 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
@@ -16,15 +16,13 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
+<idl:CameraState xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
+  <id>97</id>
+  <length>5</length>
+  <zoom>10</zoom>
+  <focus>10</focus>
+  <index>0</index>
   <checksum>30149</checksum>
-</idl:Command>
+</idl:CameraState>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
similarity index 100%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl.xsd
new file mode 100644
index 0000000..c847079
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl.xsd
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:gma="urn:gma:1.0" targetNamespace="urn:gma:1.0">
+
+ <xs:annotation>  
+  <xs:appinfo source="http://www.ogf.org/dfdl/">   
+   <dfdl:defineVariable name="ByteOrder" type="xs:string"/>   
+   <dfdl:defineFormat name="defaults">    
+    <dfdl:format alignment="1" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryCalendarEpoch="1970-01-01T00:00:00+00:00" binaryCalendarRep="bcd" binaryDecimalVirtualPoint="0" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" binaryPackedSignCodes="C D F C" calendarCenturyStart="53" calendarCheckPolicy="lax" calendarDaysInFirstWeek="4" calendarFirstDayOfWeek="Monday" calendarLanguage="en-US" calendarObserveDST="yes" calendarPattern [...]
+   </dfdl:defineFormat>   
+   <dfdl:format ref="gma:defaults" byteOrder="bigEndian"/>   
+  </xs:appinfo>  
+ </xs:annotation> 
+
+ <xs:element name="GapsPDU">  
+  <xs:complexType>   
+   <xs:choice>         <!-- no way to discriminate SDHBW or SDHBE, so uncomment one -->    
+    <!-- <xs:element ref="gma:SDHBEPDU" /> -->    
+    <xs:element ref="gma:SDHBWPDU"/>    
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWPDU">  
+  <xs:complexType>   
+   <xs:sequence>    
+    <xs:element ref="gma:SDHBWHeader"/>    
+    <xs:element ref="gma:ApplicationData"/>    
+    <xs:element ref="gma:GapsTrailer"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWHeader">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="tag0" type="gma:gapsuint8"/>    
+    <xs:element name="tagm" type="gma:gapsuint8"/>    
+    <xs:element name="tags" type="gma:gapsuint8"/>    
+    <xs:element name="tagt" type="gma:gapsuint8"/>    
+    <xs:element name="len" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+
+ <xs:simpleType name="gapsdouble" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:double"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsfloat" dfdl:lengthKind="explicit" dfdl:length="4" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:float"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedLong"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedInt"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedShort"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedByte"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:long"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:int"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:short"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:byte"/>  
+ </xs:simpleType> 
+
+ <xs:element name="GapsTrailer">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="seq" type="gma:gapsuint32"/>    
+    <xs:element name="rqr" type="gma:gapsuint32"/>    
+    <xs:element name="oid" type="gma:gapsuint32"/>    
+    <xs:element name="mid" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+ <xs:element name="ApplicationData">  
+  <xs:complexType>   
+   <xs:choice dfdl:choiceDispatchKey="{xs:string(../gma:SDHBWHeader/tagt)}">
+    <xs:element dfdl:choiceBranchKey="11" ref="gma:NextRPC"/>
+    <xs:element dfdl:choiceBranchKey="12" ref="gma:Okay"/>
+    <xs:element dfdl:choiceBranchKey="13" ref="gma:Request_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="14" ref="gma:Response_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="15" ref="gma:Request_echo_pnt"/>
+    <xs:element dfdl:choiceBranchKey="16" ref="gma:Response_echo_pnt"/>
+    <xs:element dfdl:choiceBranchKey="17" ref="gma:Request_echo_requestISRMDetections"/>
+    <xs:element dfdl:choiceBranchKey="18" ref="gma:Response_echo_requestISRMDetections"/>
+    <xs:element dfdl:choiceBranchKey="19" ref="gma:Request_echo_updateMissionPlan"/>
+    <xs:element dfdl:choiceBranchKey="20" ref="gma:Response_echo_updateMissionPlan"/>
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="NextRPC">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="mux" type="gma:gapsint32"/>    
+    <xs:element name="sec" type="gma:gapsint32"/>    
+    <xs:element name="typ" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Okay">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="x" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ss" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="st" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_pnt">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="alt" type="gma:gapsdouble"/>    
+    <xs:element name="lat" type="gma:gapsdouble"/>    
+    <xs:element name="lon" type="gma:gapsdouble"/>    
+    <xs:element name="time" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_pnt">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_requestISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="phase" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_requestISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_updateMissionPlan">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="missionPlanId" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionsActiveCnt" type="gma:gapsint32"/>    
+    <xs:element name="actionsMaxCnt" type="gma:gapsint32"/>    
+    <xs:element name="actionId0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionId1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionId2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionType0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionType1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="actionType2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="numberOfSensorWayPoints" type="gma:gapsint32"/>    
+    <xs:element name="sensorPlanId" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="vehiclePlanId" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="numberOfWayPoints" type="gma:gapsint32"/>    
+    <xs:element name="vehiclePlanId1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointsActiveCnt" type="gma:gapsint32"/>    
+    <xs:element name="wayPointsMaxCnt" type="gma:gapsint32"/>    
+    <xs:element name="wayPointId20" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId21" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId22" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId23" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="wayPointId24" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="x" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="5" maxOccurs="5"/>    
+    <xs:element name="y" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="5" maxOccurs="5"/>    
+    <xs:element name="z" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="5" maxOccurs="5"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_updateMissionPlan">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+</xs:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.tdml
new file mode 100644
index 0000000..2917c47
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.tdml
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<tdml:testSuite
+  defaultConfig="config-runtime2"
+  defaultImplementations="daffodil daffodil-runtime2"
+  defaultRoundTrip="none"
+  description="TDML tests for egress_xdcc_bw"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+  <tdml:defineConfig name="config-runtime1">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:defineConfig name="config-runtime2">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 11"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_11"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_11.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_11.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 11"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_11"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_11.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_11.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 12"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_12"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_12.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_12.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 12"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_12"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_12.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_12.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 13"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_13"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_13.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_13.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 13"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_13"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_13.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_13.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 14"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_14"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_14.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_14.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 14"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_14"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_14.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_14.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 15"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_15"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_15.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_15.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 15"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_15"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_15.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_15.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 16"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_16"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_16.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_16.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 16"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_16"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_16.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_16.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 17"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_17"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_17.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_17.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 17"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_17"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_17.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_17.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 18"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_18"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_18.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_18.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 18"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_18"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_18.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_18.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 19"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_19"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_19.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_19.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 19"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_19"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_19.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_19.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="egress_xdcc_bw parse test 20"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_parse_20"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_20.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_20.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="egress_xdcc_bw unparse test 20"
+    model="egress_xdcc_bw.dfdl.xsd"
+    name="egress_xdcc_bw_unparse_20"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">egress_xdcc_bw_unparse_20.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">egress_xdcc_bw_parse_20.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat
new file mode 100644
index 0000000..c1ffcc0
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat
new file mode 100644
index 0000000..121889b
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat
new file mode 100644
index 0000000..b69f70a
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat
new file mode 100644
index 0000000..1ee953f
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat
new file mode 100644
index 0000000..8e0a836
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat
new file mode 100644
index 0000000..dea81cd
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat
new file mode 100644
index 0000000..95080f1
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat
new file mode 100644
index 0000000..a911bdb
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat
new file mode 100644
index 0000000..b25d46e
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat
new file mode 100644
index 0000000..f5a69c1
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_11.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_11.xml
index 9a1d4a1..b9470e9 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_11.xml
@@ -16,15 +16,29 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>11</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:NextRPC>
+        <mux>6</mux>
+        <sec>7</sec>
+        <typ>8</typ>
+      </gma:NextRPC>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>9</seq>
+      <rqr>10</rqr>
+      <oid>11</oid>
+      <mid>12</mid>
+      <crc>13</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_12.xml
similarity index 62%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_12.xml
index 9a1d4a1..cb39c26 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_12.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>12</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Okay>
+        <x>6</x>
+      </gma:Okay>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_13.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_13.xml
new file mode 100644
index 0000000..5255b8b
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_13.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>13</tagt>
+      <len>112</len>
+      <crc>39795</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_component_heartbeats>
+        <ss>77</ss>
+        <ss>80</ss>
+        <ss>88</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <st>114</st>
+        <st>101</st>
+        <st>97</st>
+        <st>100</st>
+        <st>121</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+      </gma:Request_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>2743063952</seq>
+      <rqr>32652</rqr>
+      <oid>5</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_14.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_14.xml
index 9a1d4a1..43927ab 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_14.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>14</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_component_heartbeats>
+        <ret>6</ret>
+      </gma:Response_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_15.xml
similarity index 55%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_15.xml
index 0307283..51edd01 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_15.xml
@@ -16,22 +16,30 @@
   limitations under the License.
 -->
 
-<idl:VideoSettings xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>98</id>
-  <length>14</length>
-  <destIp>
-    <item>1</item>
-    <item>2</item>
-    <item>3</item>
-    <item>4</item>
-  </destIp>
-  <port>8080</port>
-  <bitrate>0</bitrate>
-  <ttl>0</ttl>
-  <streamType>0</streamType>
-  <mjpegQuality>0</mjpegQuality>
-  <saveSettingsAndTsPacketCount>0</saveSettingsAndTsPacketCount>
-  <checksum>3073</checksum>
-</idl:VideoSettings>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>15</tagt>
+      <len>44</len>
+      <crc>46626</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_pnt>
+        <alt>0.10000000000000001</alt>
+        <lat>29.50464225007952</lat>
+        <lon>-116.00761807405785</lon>
+        <time>1611604087</time>
+      </gma:Request_echo_pnt>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>0</seq>
+      <rqr>2415922672</rqr>
+      <oid>32652</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_16.xml
similarity index 60%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_16.xml
index 9a1d4a1..dc3838a 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_16.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>16</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_pnt>
+        <ret>6</ret>
+      </gma:Response_echo_pnt>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_17.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_17.xml
new file mode 100644
index 0000000..89cbd87
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_17.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>17</tagt>
+      <len>48</len>
+      <crc>63809</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_requestISRMDetections>
+        <phase>102</phase>
+        <phase>105</phase>
+        <phase>110</phase>
+        <phase>100</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+        <phase>0</phase>
+      </gma:Request_echo_requestISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>4</seq>
+      <rqr>0</rqr>
+      <oid>1684957542</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_18.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_18.xml
index 9a1d4a1..0351bf4 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_18.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>18</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_requestISRMDetections>
+        <ret>6</ret>
+      </gma:Response_echo_requestISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_19.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_19.xml
new file mode 100644
index 0000000..8322148
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_19.xml
@@ -0,0 +1,638 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>12</tagm>
+      <tags>12</tags>
+      <tagt>19</tagt>
+      <len>736</len>
+      <crc>43460</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_updateMissionPlan>
+        <missionPlanId>105</missionPlanId>
+        <missionPlanId>100</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <missionPlanId>0</missionPlanId>
+        <actionsActiveCnt>2</actionsActiveCnt>
+        <actionsMaxCnt>3</actionsMaxCnt>
+        <actionId0>97</actionId0>
+        <actionId0>99</actionId0>
+        <actionId0>49</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId0>0</actionId0>
+        <actionId1>97</actionId1>
+        <actionId1>99</actionId1>
+        <actionId1>50</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId1>0</actionId1>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionId2>0</actionId2>
+        <actionType0>102</actionType0>
+        <actionType0>105</actionType0>
+        <actionType0>110</actionType0>
+        <actionType0>100</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType0>0</actionType0>
+        <actionType1>102</actionType1>
+        <actionType1>105</actionType1>
+        <actionType1>120</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType1>0</actionType1>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <actionType2>0</actionType2>
+        <wayPointId0>119</wayPointId0>
+        <wayPointId0>112</wayPointId0>
+        <wayPointId0>49</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId0>0</wayPointId0>
+        <wayPointId1>119</wayPointId1>
+        <wayPointId1>112</wayPointId1>
+        <wayPointId1>50</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId1>0</wayPointId1>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <wayPointId2>0</wayPointId2>
+        <numberOfSensorWayPoints>1</numberOfSensorWayPoints>
+        <sensorPlanId>105</sensorPlanId>
+        <sensorPlanId>100</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <sensorPlanId>0</sensorPlanId>
+        <vehiclePlanId>105</vehiclePlanId>
+        <vehiclePlanId>100</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <vehiclePlanId>0</vehiclePlanId>
+        <numberOfWayPoints>3</numberOfWayPoints>
+        <vehiclePlanId1>105</vehiclePlanId1>
+        <vehiclePlanId1>100</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <vehiclePlanId1>0</vehiclePlanId1>
+        <wayPointsActiveCnt>4</wayPointsActiveCnt>
+        <wayPointsMaxCnt>5</wayPointsMaxCnt>
+        <wayPointId20>119</wayPointId20>
+        <wayPointId20>112</wayPointId20>
+        <wayPointId20>48</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId20>0</wayPointId20>
+        <wayPointId21>119</wayPointId21>
+        <wayPointId21>112</wayPointId21>
+        <wayPointId21>49</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId21>0</wayPointId21>
+        <wayPointId22>119</wayPointId22>
+        <wayPointId22>112</wayPointId22>
+        <wayPointId22>50</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId22>0</wayPointId22>
+        <wayPointId23>119</wayPointId23>
+        <wayPointId23>112</wayPointId23>
+        <wayPointId23>51</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId23>0</wayPointId23>
+        <wayPointId24>96</wayPointId24>
+        <wayPointId24>69</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>127</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>80</wayPointId24>
+        <wayPointId24>69</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>-116</wayPointId24>
+        <wayPointId24>127</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <wayPointId24>0</wayPointId24>
+        <x>29.800000000000001</x>
+        <x>30</x>
+        <x>30.300000000000001</x>
+        <x>30.5</x>
+        <x>-1</x>
+        <y>-116.5</y>
+        <y>-117</y>
+        <y>-117.5</y>
+        <y>-117.7</y>
+        <y>-2.2392049343947951E+307</y>
+        <z>0.10000000000000001</z>
+        <z>0.20000000000000001</z>
+        <z>0.29999999999999999</z>
+        <z>0.40000000000000002</z>
+        <z>-2.2392049343935337E+307</z>
+      </gma:Request_echo_updateMissionPlan>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>25705</seq>
+      <rqr>0</rqr>
+      <oid>0</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_20.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_20.xml
index 9a1d4a1..484a0cd 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_unparse_20.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>20</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_updateMissionPlan>
+        <ret>6</ret>
+      </gma:Response_echo_updateMissionPlan>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd
new file mode 100644
index 0000000..3460b20
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl.xsd
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext" xmlns:gma="urn:gma:1.0" targetNamespace="urn:gma:1.0"> 
+
+ <xs:annotation>  
+  <xs:appinfo source="http://www.ogf.org/dfdl/">   
+   <dfdl:defineVariable name="ByteOrder" type="xs:string"/>   
+   <dfdl:defineFormat name="defaults">    
+    <dfdl:format alignment="1" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryCalendarEpoch="1970-01-01T00:00:00+00:00" binaryCalendarRep="bcd" binaryDecimalVirtualPoint="0" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" binaryPackedSignCodes="C D F C" calendarCenturyStart="53" calendarCheckPolicy="lax" calendarDaysInFirstWeek="4" calendarFirstDayOfWeek="Monday" calendarLanguage="en-US" calendarObserveDST="yes" calendarPattern [...]
+   </dfdl:defineFormat>   
+   <dfdl:format ref="gma:defaults" byteOrder="bigEndian"/>   
+  </xs:appinfo>  
+ </xs:annotation> 
+
+ <xs:element name="GapsPDU">  
+  <xs:complexType>   
+   <xs:choice>         <!-- no way to discriminate SDHBW or SDHBE, so uncomment one -->    
+    <!-- <xs:element ref="gma:SDHBEPDU" /> -->    
+    <xs:element ref="gma:SDHBWPDU"/>    
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWPDU">  
+  <xs:complexType>   
+   <xs:sequence>    
+    <xs:element ref="gma:SDHBWHeader"/>    
+    <xs:element ref="gma:ApplicationData"/>    
+    <xs:element ref="gma:GapsTrailer"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="SDHBWHeader">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="tag0" type="gma:gapsuint8"/>    
+    <xs:element name="tagm" type="gma:gapsuint8"/>    
+    <xs:element name="tags" type="gma:gapsuint8"/>    
+    <xs:element name="tagt" type="gma:gapsuint8"/>    
+    <xs:element name="len" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+
+ <xs:simpleType name="gapsdouble" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:double"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsfloat" dfdl:lengthKind="explicit" dfdl:length="4" dfdl:lengthUnits="bytes" dfdl:byteOrder="littleEndian">  
+  <xs:restriction base="xs:float"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedLong"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedInt"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedShort"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsuint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:unsignedByte"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint64" dfdl:lengthKind="explicit" dfdl:length="64" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:long"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint32" dfdl:lengthKind="explicit" dfdl:length="32" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:int"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint16" dfdl:lengthKind="explicit" dfdl:length="16" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:short"/>  
+ </xs:simpleType> 
+
+ <xs:simpleType name="gapsint8" dfdl:lengthKind="explicit" dfdl:length="8" dfdl:lengthUnits="bits">  
+  <xs:restriction base="xs:byte"/>  
+ </xs:simpleType> 
+
+ <xs:element name="GapsTrailer">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="seq" type="gma:gapsuint32"/>    
+    <xs:element name="rqr" type="gma:gapsuint32"/>    
+    <xs:element name="oid" type="gma:gapsuint32"/>    
+    <xs:element name="mid" type="gma:gapsuint16"/>    
+    <xs:element name="crc" type="gma:gapsuint16"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+ <xs:element name="ApplicationData">  
+  <xs:complexType>   
+   <xs:choice dfdl:choiceDispatchKey="{xs:string(../gma:SDHBWHeader/tagt)}">
+    <xs:element dfdl:choiceBranchKey="111" ref="gma:NextRPC"/>
+    <xs:element dfdl:choiceBranchKey="112" ref="gma:Okay"/>
+    <xs:element dfdl:choiceBranchKey="113" ref="gma:Request_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="114" ref="gma:Response_echo_component_heartbeats"/>
+    <xs:element dfdl:choiceBranchKey="115" ref="gma:Request_echo_recieveISRMDetections"/>
+    <xs:element dfdl:choiceBranchKey="116" ref="gma:Response_echo_recieveISRMDetections"/>
+   </xs:choice>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="NextRPC">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="mux" type="gma:gapsint32"/>    
+    <xs:element name="sec" type="gma:gapsint32"/>    
+    <xs:element name="typ" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Okay">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="x" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ss" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="st" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_component_heartbeats">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Request_echo_recieveISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="detectsActiveCnt" type="gma:gapsint32"/>    
+    <xs:element name="detectsMaxCnt" type="gma:gapsint32"/>    
+    <xs:element name="TGT_ISRM_ID0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID3" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID4" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID5" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID6" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="TGT_ISRM_ID7" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="32" maxOccurs="32"/>    
+    <xs:element name="alt" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="bearing" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="classification0" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification1" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification2" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification3" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification4" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification5" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification6" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="classification7" type="gma:gapsint8" dfdl:occursCountKind="fixed" minOccurs="64" maxOccurs="64"/>    
+    <xs:element name="confidence" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="lat" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="lon" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+    <xs:element name="speed" type="gma:gapsdouble" dfdl:occursCountKind="fixed" minOccurs="8" maxOccurs="8"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+ <xs:element name="Response_echo_recieveISRMDetections">  
+  <xs:complexType>   
+   <xs:sequence dfdl:byteOrder="bigEndian">    
+    <xs:element name="ret" type="gma:gapsint32"/>    
+   </xs:sequence>   
+  </xs:complexType>  
+ </xs:element> 
+
+</xs:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.tdml
new file mode 100644
index 0000000..9fbadfd
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.tdml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<tdml:testSuite
+  defaultConfig="config-runtime2"
+  defaultImplementations="daffodil daffodil-runtime2"
+  defaultRoundTrip="none"
+  description="TDML tests for ingress_xdcc_bw"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+  <tdml:defineConfig name="config-runtime1">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:defineConfig name="config-runtime2">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 111"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_111"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_111.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_111.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 111"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_111"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_111.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_111.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 112"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_112"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_112.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_112.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 112"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_112"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_112.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_112.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 113"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_113"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_113.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_113.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 113"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_113"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_113.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_113.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 114"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_114"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_114.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_114.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 114"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_114"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_114.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_114.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 115"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_115"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_115.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_115.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 115"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_115"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_115.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_115.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="ingress_xdcc_bw parse test 116"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_parse_116"
+    root="GapsPDU">
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_116.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_116.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="ingress_xdcc_bw unparse test 116"
+    model="ingress_xdcc_bw.dfdl.xsd"
+    name="ingress_xdcc_bw_unparse_116"
+    root="GapsPDU">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ingress_xdcc_bw_unparse_116.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">ingress_xdcc_bw_parse_116.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat
new file mode 100644
index 0000000..db1d6df
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat
new file mode 100644
index 0000000..98e6287
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat
new file mode 100644
index 0000000..233baae
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat
new file mode 100644
index 0000000..b24e8d4
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat
new file mode 100644
index 0000000..b3e5ce3
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat
new file mode 100644
index 0000000..c2dcc79
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_111.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_111.xml
index 9a1d4a1..8c085be 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_111.xml
@@ -16,15 +16,29 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>111</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:NextRPC>
+        <mux>6</mux>
+        <sec>7</sec>
+        <typ>8</typ>
+      </gma:NextRPC>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>9</seq>
+      <rqr>10</rqr>
+      <oid>11</oid>
+      <mid>12</mid>
+      <crc>13</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_112.xml
similarity index 62%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_112.xml
index 9a1d4a1..fc690e8 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_112.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>112</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Okay>
+        <x>6</x>
+      </gma:Okay>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_113.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_113.xml
new file mode 100644
index 0000000..2585bac
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_113.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>111</tagm>
+      <tags>111</tags>
+      <tagt>113</tagt>
+      <len>112</len>
+      <crc>48734</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_component_heartbeats>
+        <ss>82</ss>
+        <ss>68</ss>
+        <ss>82</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <ss>0</ss>
+        <st>114</st>
+        <st>101</st>
+        <st>97</st>
+        <st>100</st>
+        <st>121</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+        <st>0</st>
+      </gma:Request_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>4076848528</seq>
+      <rqr>32610</rqr>
+      <oid>5</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_114.xml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_114.xml
index 9a1d4a1..e1457db 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_114.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>114</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_component_heartbeats>
+        <ret>6</ret>
+      </gma:Response_echo_component_heartbeats>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_115.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_115.xml
new file mode 100644
index 0000000..c84d1dd
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_115.xml
@@ -0,0 +1,859 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>0</tag0>
+      <tagm>111</tagm>
+      <tags>111</tags>
+      <tagt>115</tagt>
+      <len>1176</len>
+      <crc>1984</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Request_echo_recieveISRMDetections>
+        <detectsActiveCnt>2</detectsActiveCnt>
+        <detectsMaxCnt>8</detectsMaxCnt>
+        <TGT_ISRM_ID0>49</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>55</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>53</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>57</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>56</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>48</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID0>0</TGT_ISRM_ID0>
+        <TGT_ISRM_ID1>52</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>50</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>50</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>56</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>55</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>50</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID1>0</TGT_ISRM_ID1>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID2>0</TGT_ISRM_ID2>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID3>0</TGT_ISRM_ID3>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID4>0</TGT_ISRM_ID4>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID5>0</TGT_ISRM_ID5>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID6>0</TGT_ISRM_ID6>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <TGT_ISRM_ID7>0</TGT_ISRM_ID7>
+        <alt>0</alt>
+        <alt>0</alt>
+        <alt>-2.2363310143334415E+307</alt>
+        <alt>-2.236435215127047E+307</alt>
+        <alt>-2.2363310143043182E+307</alt>
+        <alt>-1.5966722476277758E+293</alt>
+        <alt>-2.2363220410727081E+307</alt>
+        <alt>-2.2363310143063459E+307</alt>
+        <bearing>-1</bearing>
+        <bearing>-1</bearing>
+        <bearing>-2.2363310143048291E+307</bearing>
+        <bearing>-3.3189020416553621E+148</bearing>
+        <bearing>0</bearing>
+        <bearing>-5.1093511924088827E+294</bearing>
+        <bearing>-2.2363310143043182E+307</bearing>
+        <bearing>-7.0592328879678846E+299</bearing>
+        <classification0>99</classification0>
+        <classification0>97</classification0>
+        <classification0>114</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification0>0</classification0>
+        <classification1>112</classification1>
+        <classification1>101</classification1>
+        <classification1>114</classification1>
+        <classification1>115</classification1>
+        <classification1>111</classification1>
+        <classification1>110</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification1>0</classification1>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification2>0</classification2>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>-128</classification3>
+        <classification3>119</classification3>
+        <classification3>58</classification3>
+        <classification3>61</classification3>
+        <classification3>100</classification3>
+        <classification3>127</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>46</classification3>
+        <classification3>115</classification3>
+        <classification3>112</classification3>
+        <classification3>101</classification3>
+        <classification3>101</classification3>
+        <classification3>100</classification3>
+        <classification3>100</classification3>
+        <classification3>101</classification3>
+        <classification3>110</classification3>
+        <classification3>99</classification3>
+        <classification3>101</classification3>
+        <classification3>116</classification3>
+        <classification3>105</classification3>
+        <classification3>111</classification3>
+        <classification3>110</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification3>0</classification3>
+        <classification4>-32</classification4>
+        <classification4>49</classification4>
+        <classification4>0</classification4>
+        <classification4>-104</classification4>
+        <classification4>98</classification4>
+        <classification4>127</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>-48</classification4>
+        <classification4>49</classification4>
+        <classification4>0</classification4>
+        <classification4>-104</classification4>
+        <classification4>98</classification4>
+        <classification4>127</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>45</classification4>
+        <classification4>49</classification4>
+        <classification4>46</classification4>
+        <classification4>48</classification4>
+        <classification4>46</classification4>
+        <classification4>49</classification4>
+        <classification4>51</classification4>
+        <classification4>56</classification4>
+        <classification4>51</classification4>
+        <classification4>55</classification4>
+        <classification4>52</classification4>
+        <classification4>52</classification4>
+        <classification4>52</classification4>
+        <classification4>51</classification4>
+        <classification4>49</classification4>
+        <classification4>50</classification4>
+        <classification4>56</classification4>
+        <classification4>48</classification4>
+        <classification4>49</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification4>0</classification4>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>32</classification5>
+        <classification5>-109</classification5>
+        <classification5>127</classification5>
+        <classification5>-71</classification5>
+        <classification5>-1</classification5>
+        <classification5>-1</classification5>
+        <classification5>-1</classification5>
+        <classification5>-1</classification5>
+        <classification5>-48</classification5>
+        <classification5>-106</classification5>
+        <classification5>127</classification5>
+        <classification5>-71</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>96</classification5>
+        <classification5>-106</classification5>
+        <classification5>127</classification5>
+        <classification5>-71</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>-32</classification5>
+        <classification5>49</classification5>
+        <classification5>0</classification5>
+        <classification5>-104</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>-48</classification5>
+        <classification5>49</classification5>
+        <classification5>0</classification5>
+        <classification5>-104</classification5>
+        <classification5>98</classification5>
+        <classification5>127</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification5>0</classification5>
+        <classification6>-40</classification6>
+        <classification6>-30</classification6>
+        <classification6>82</classification6>
+        <classification6>62</classification6>
+        <classification6>100</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>-96</classification6>
+        <classification6>-109</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>80</classification6>
+        <classification6>-109</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>-62</classification6>
+        <classification6>35</classification6>
+        <classification6>122</classification6>
+        <classification6>62</classification6>
+        <classification6>100</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>96</classification6>
+        <classification6>118</classification6>
+        <classification6>67</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>-96</classification6>
+        <classification6>-109</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>64</classification6>
+        <classification6>-106</classification6>
+        <classification6>127</classification6>
+        <classification6>-71</classification6>
+        <classification6>98</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification6>23</classification6>
+        <classification6>37</classification6>
+        <classification6>122</classification6>
+        <classification6>62</classification6>
+        <classification6>100</classification6>
+        <classification6>127</classification6>
+        <classification6>0</classification6>
+        <classification6>0</classification6>
+        <classification7>-48</classification7>
+        <classification7>-106</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>-88</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>16</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>80</classification7>
+        <classification7>35</classification7>
+        <classification7>122</classification7>
+        <classification7>62</classification7>
+        <classification7>100</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>-112</classification7>
+        <classification7>42</classification7>
+        <classification7>0</classification7>
+        <classification7>-104</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>-96</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>48</classification7>
+        <classification7>-109</classification7>
+        <classification7>127</classification7>
+        <classification7>-71</classification7>
+        <classification7>98</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <classification7>112</classification7>
+        <classification7>35</classification7>
+        <classification7>122</classification7>
+        <classification7>62</classification7>
+        <classification7>100</classification7>
+        <classification7>127</classification7>
+        <classification7>0</classification7>
+        <classification7>0</classification7>
+        <confidence>0.8304254412651062</confidence>
+        <confidence>0.84350341558456421</confidence>
+        <confidence>-2.236331014302019E+307</confidence>
+        <confidence>0</confidence>
+        <confidence>-2.2363310143025299E+307</confidence>
+        <confidence>-7.0592328879678846E+299</confidence>
+        <confidence>-2.2364351717587783E+307</confidence>
+        <confidence>-2.236435215244131E+307</confidence>
+        <lat>32.730128382409546</lat>
+        <lat>30.730832492300745</lat>
+        <lat>0</lat>
+        <lat>-2.229577558811266E+307</lat>
+        <lat>-2.2363220410652995E+307</lat>
+        <lat>-2.2363310143107049E+307</lat>
+        <lat>-2.236331014301508E+307</lat>
+        <lat>-2.236435213899717E+307</lat>
+        <lon>-117.14324935960397</lon>
+        <lon>-117.13837444312801</lon>
+        <lon>-2.2363310143002307E+307</lon>
+        <lon>-2.2364352132486419E+307</lon>
+        <lon>-1</lon>
+        <lon>-2.2363310143107049E+307</lon>
+        <lon>-2.3316027292373177E+304</lon>
+        <lon>-3.3189020416553621E+148</lon>
+        <speed>-1</speed>
+        <speed>-1</speed>
+        <speed>-2.2363310143109603E+307</speed>
+        <speed>-2.2363220410729635E+307</speed>
+        <speed>-2.2363310142994643E+307</speed>
+        <speed>-2.2364352136680718E+307</speed>
+        <speed>-1</speed>
+        <speed>-2.2363310143107049E+307</speed>
+      </gma:Request_echo_recieveISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>0</seq>
+      <rqr>0</rqr>
+      <oid>0</oid>
+      <mid>0</mid>
+      <crc>0</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_116.xml
similarity index 59%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_116.xml
index 9a1d4a1..b7010c5 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_unparse_116.xml
@@ -16,15 +16,27 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>1</id>
-  <length>7</length>
-  <pan>-999</pan>
-  <tilt>-1231</tilt>
-  <mode>80</mode>
-  <stabilized>0</stabilized>
-  <impulse>0</impulse>
-  <checksum>30149</checksum>
-</idl:Command>
+<gma:GapsPDU xmlns:gma="urn:gma:1.0">
+  <gma:SDHBWPDU>
+    <gma:SDHBWHeader>
+      <tag0>1</tag0>
+      <tagm>2</tagm>
+      <tags>3</tags>
+      <tagt>116</tagt>
+      <len>4</len>
+      <crc>5</crc>
+    </gma:SDHBWHeader>
+    <gma:ApplicationData>
+      <gma:Response_echo_recieveISRMDetections>
+        <ret>6</ret>
+      </gma:Response_echo_recieveISRMDetections>
+    </gma:ApplicationData>
+    <gma:GapsTrailer>
+      <seq>7</seq>
+      <rqr>8</rqr>
+      <oid>9</oid>
+      <mid>10</mid>
+      <crc>11</crc>
+    </gma:GapsTrailer>
+  </gma:SDHBWPDU>
+</gma:GapsPDU>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
new file mode 100644
index 0000000..4034d39
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="int8" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="16" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="16" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="32" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:complexType name="CommandType">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="1" type="idl:uint8"/>
+      <xs:element name="length" fixed="7" type="idl:uint8"/>
+      <xs:element name="pan" type="idl:int16"/>
+      <xs:element name="tilt">
+        <xs:simpleType>
+          <xs:restriction base="idl:int16">
+            <xs:minInclusive value="-1396"/>
+            <xs:maxInclusive value="733"/>
+          </xs:restriction>
+        </xs:simpleType>
+      </xs:element>
+      <xs:element name="mode" fixed="80" type="idl:uint8"/>
+      <xs:element name="stabilized" fixed="0" type="idl:uint8"/>
+      <xs:element name="impulse" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="Command" type="idl:CommandType"/>
+  <xs:complexType name="CameraStateType">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="97" type="idl:uint8"/>
+      <xs:element name="length" fixed="5" type="idl:uint8"/>
+      <xs:element name="zoom" type="idl:int16"/>
+      <xs:element name="focus" type="idl:int16"/>
+      <xs:element name="index" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="CameraState" type="idl:CameraStateType"/>
+  <xs:complexType name="VideoSettingsType">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="98" type="idl:uint8"/>
+      <xs:element name="length" fixed="14" type="idl:uint8"/>
+      <xs:element name="destIp">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="4" maxOccurs="4" dfdl:occursCountKind="fixed" type="idl:uint8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="port" type="idl:uint16"/>
+      <xs:element name="bitrate" fixed="0" type="idl:uint32"/>
+      <xs:element name="ttl" fixed="0" type="idl:int8"/>
+      <xs:element name="streamType" fixed="0" type="idl:uint8"/>
+      <xs:element name="mjpegQuality" fixed="0" type="idl:uint8"/>
+      <xs:element name="saveSettingsAndTsPacketCount" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="VideoSettings" type="idl:VideoSettingsType"/>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
similarity index 78%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
index 110322d..4b44391 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
@@ -19,7 +19,7 @@
 <tdml:testSuite
   defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
-  defaultRoundTrip="onePass"
+  defaultRoundTrip="none"
   description="TDML tests for orion-command"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
@@ -38,6 +38,32 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
+    description="orion-command CameraState parse test"
+    model="orion-command.dfdl.xsd"
+    name="camera_state_parse"
+    root="CameraState">
+    <tdml:document>
+      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="orion-command CameraState unparse test"
+    model="orion-command.dfdl.xsd"
+    name="camera_state_unparse"
+    root="CameraState">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
     description="orion-command Command parse test"
     model="orion-command.dfdl.xsd"
     name="command_parse"
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
rename to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
index 921ee19..6939000 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/section15/choice_groups/choice-unparse2.tdml
@@ -24,7 +24,7 @@
   xmlns:fn="http://www.w3.org/2005/xpath-functions" 
   xmlns:ex="http://example.com">
 
-  <tdml:defineSchema name="c" elementFormDefault="unqualified">
+  <tdml:defineSchema name="c1" elementFormDefault="unqualified">
     
     <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
     <dfdl:format ref="ex:GeneralFormat" lengthKind="delimited"/>
@@ -48,7 +48,7 @@
 
 
     
-<tdml:unparserTestCase name="choice_with_array_branch1" root="e" model="c">
+<tdml:unparserTestCase name="choice_with_array_branch1" root="e" model="c1">
 
   <tdml:document>1;</tdml:document>
 
@@ -62,7 +62,7 @@
   
 </tdml:unparserTestCase>
 
-<tdml:unparserTestCase name="choice_with_array_branch2" root="e" model="c">
+<tdml:unparserTestCase name="choice_with_array_branch2" root="e" model="c1">
 
   <tdml:document>1;2;</tdml:document>
 
@@ -77,7 +77,7 @@
   
 </tdml:unparserTestCase>
 
-<tdml:unparserTestCase name="choice_with_array_branch3" root="e" model="c">
+<tdml:unparserTestCase name="choice_with_array_branch3" root="e" model="c1">
 
   <tdml:document>b</tdml:document>
 
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestEgressXdccBw.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestEgressXdccBw.scala
new file mode 100644
index 0000000..9865d40
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestEgressXdccBw.scala
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestEgressXdccBw {
+  val testDir = "/org/apache/daffodil/runtime2/"
+  val runner = Runner(testDir, "egress_xdcc_bw.tdml")
+
+  @AfterClass def shutDown(): Unit = { runner.reset }
+}
+
+class TestEgressXdccBw {
+  import TestEgressXdccBw._
+
+  @Test def test_egress_xdcc_bw_parse_11(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_11") }
+  @Test def test_egress_xdcc_bw_unparse_11(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_11") }
+  @Test def test_egress_xdcc_bw_parse_12(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_12") }
+  @Test def test_egress_xdcc_bw_unparse_12(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_12") }
+  @Test def test_egress_xdcc_bw_parse_13(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_13") }
+  @Test def test_egress_xdcc_bw_unparse_13(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_13") }
+  @Test def test_egress_xdcc_bw_parse_14(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_14") }
+  @Test def test_egress_xdcc_bw_unparse_14(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_14") }
+  @Test def test_egress_xdcc_bw_parse_15(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_15") }
+  @Test def test_egress_xdcc_bw_unparse_15(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_15") }
+  @Test def test_egress_xdcc_bw_parse_16(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_16") }
+  @Test def test_egress_xdcc_bw_unparse_16(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_16") }
+  @Test def test_egress_xdcc_bw_parse_17(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_17") }
+  @Test def test_egress_xdcc_bw_unparse_17(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_17") }
+  @Test def test_egress_xdcc_bw_parse_18(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_18") }
+  @Test def test_egress_xdcc_bw_unparse_18(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_18") }
+  @Test def test_egress_xdcc_bw_parse_19(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_19") }
+  @Test def test_egress_xdcc_bw_unparse_19(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_19") }
+  @Test def test_egress_xdcc_bw_parse_20(): Unit = { runner.runOneTest("egress_xdcc_bw_parse_20") }
+  @Test def test_egress_xdcc_bw_unparse_20(): Unit = { runner.runOneTest("egress_xdcc_bw_unparse_20") }
+}
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
similarity index 67%
copy from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
copy to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
index 719acae..ba5a060 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
@@ -21,18 +21,18 @@ import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
 
-object TestRuntime2 {
+object TestExNums {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "TestRuntime2.tdml")
+  val runner = Runner(testDir, "ex_nums.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestRuntime2 {
-  import TestRuntime2._
+class TestExNums {
+  import TestExNums._
 
-  @Test def test_ex_nums_parse1(): Unit = { runner.runOneTest("ex_nums_parse1") }
-  @Test def test_ex_nums_unparse1(): Unit = { runner.runOneTest("ex_nums_unparse1") }
-  @Test def test_ex_nums_parse2(): Unit = { runner.runOneTest("ex_nums_parse2") }
-  @Test def test_ex_nums_unparse2(): Unit = { runner.runOneTest("ex_nums_unparse2") }
+  @Test def test_ex_nums_parse_runtime1(): Unit = { runner.runOneTest("ex_nums_parse_runtime1") }
+  @Test def test_ex_nums_unparse_runtime1(): Unit = { runner.runOneTest("ex_nums_unparse_runtime1") }
+  @Test def test_ex_nums_parse_runtime2(): Unit = { runner.runOneTest("ex_nums_parse_runtime2") }
+  @Test def test_ex_nums_unparse_runtime2(): Unit = { runner.runOneTest("ex_nums_unparse_runtime2") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIngressXdccBw.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIngressXdccBw.scala
new file mode 100644
index 0000000..f612f17
--- /dev/null
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIngressXdccBw.scala
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information ringarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
+import org.junit.Test
+
+object TestIngressXdccBw {
+  val testDir = "/org/apache/daffodil/runtime2/"
+  val runner = Runner(testDir, "ingress_xdcc_bw.tdml")
+
+  @AfterClass def shutDown(): Unit = { runner.reset }
+}
+
+class TestIngressXdccBw {
+  import TestIngressXdccBw._
+
+  @Test def test_ingress_xdcc_bw_parse_111(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_111") }
+  @Test def test_ingress_xdcc_bw_unparse_111(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_111") }
+  @Test def test_ingress_xdcc_bw_parse_112(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_112") }
+  @Test def test_ingress_xdcc_bw_unparse_112(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_112") }
+  @Test def test_ingress_xdcc_bw_parse_113(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_113") }
+  @Test def test_ingress_xdcc_bw_unparse_113(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_113") }
+  @Test def test_ingress_xdcc_bw_parse_114(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_114") }
+  @Test def test_ingress_xdcc_bw_unparse_114(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_114") }
+  @Test def test_ingress_xdcc_bw_parse_115(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_115") }
+  @Test def test_ingress_xdcc_bw_unparse_115(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_115") }
+  @Test def test_ingress_xdcc_bw_parse_116(): Unit = { runner.runOneTest("ingress_xdcc_bw_parse_116") }
+  @Test def test_ingress_xdcc_bw_unparse_116(): Unit = { runner.runOneTest("ingress_xdcc_bw_unparse_116") }
+}
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestNested.scala
similarity index 60%
rename from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
rename to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestNested.scala
index 719acae..08201e2 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestNested.scala
@@ -17,22 +17,24 @@
 
 package org.apache.daffodil.runtime2
 
-import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
+import org.junit.Test
 
-object TestRuntime2 {
+object TestNested {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "TestRuntime2.tdml")
+  val runner: Runner = Runner(testDir, "nested.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestRuntime2 {
-  import TestRuntime2._
+class TestNested {
+  import TestNested._
 
-  @Test def test_ex_nums_parse1(): Unit = { runner.runOneTest("ex_nums_parse1") }
-  @Test def test_ex_nums_unparse1(): Unit = { runner.runOneTest("ex_nums_unparse1") }
-  @Test def test_ex_nums_parse2(): Unit = { runner.runOneTest("ex_nums_parse2") }
-  @Test def test_ex_nums_unparse2(): Unit = { runner.runOneTest("ex_nums_unparse2") }
+  @Test def test_nested_struct_parse(): Unit = { runner.runOneTest("nested_struct_parse") }
+  @Test def test_nested_struct_unparse(): Unit = { runner.runOneTest("nested_struct_unparse") }
+  @Test def test_nested_union_parse_2(): Unit = { runner.runOneTest("nested_union_parse_2") }
+  @Test def test_nested_union_unparse_2(): Unit = { runner.runOneTest("nested_union_unparse_2") }
+  @Test def test_nested_union_parse_4(): Unit = { runner.runOneTest("nested_union_parse_4") }
+  @Test def test_nested_union_unparse_4(): Unit = { runner.runOneTest("nested_union_unparse_4") }
 }
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
similarity index 89%
rename from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
rename to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
index 939d9ca..9cf4546 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
@@ -31,6 +31,8 @@ object TestOrionCommand {
 class TestOrionCommand {
   import TestOrionCommand._
 
+  @Test def test_camera_state_parse(): Unit = { runner.runOneTest("camera_state_parse") }
+  @Test def test_camera_state_unparse(): Unit = { runner.runOneTest("camera_state_unparse") }
   @Test def test_command_parse(): Unit = { runner.runOneTest("command_parse") }
   @Test def test_command_unparse(): Unit = { runner.runOneTest("command_unparse") }
   @Test def test_video_settings_parse(): Unit = { runner.runOneTest("video_settings_parse") }
diff --git a/project/Rat.scala b/project/Rat.scala
index 2b646d2..4c88ef5 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -107,9 +107,10 @@ object Rat {
     file("daffodil-japi/src/test/resources/test/japi/myData16.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myData19.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myDataBroken.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat"),
     file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_struct_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_2.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/nested_union_parse_4.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/01very_simple.txt"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData2.dat"),
@@ -123,6 +124,27 @@ object Rat {
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_11.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_12.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_13.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_14.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_15.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_16.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_17.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_18.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_19.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw_parse_20.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.dfdl"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_111.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_112.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_113.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file.txt"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file2.txt"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_01.bin"),

[daffodil] 07/09: Support booleans, arrays of complex types, fixed values, fill bytes

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 48858f83995f69026dcfa367604ba6a5cb343e70
Author: John Interrante <in...@research.ge.com>
AuthorDate: Tue Feb 16 12:30:15 2021 -0500

    Support booleans, arrays of complex types, fixed values, fill bytes
    
    In order to handle more collaborators' schemas, add support for
    boolean fields, empty sequences, arrays of complex types, validation
    of fixed values, and padding of explicit length complex elements with
    fill bytes.  Add new collaborator schemas, test cases, and data files
    to daffodil-test and update existing tests to improve code coverage.
    
    Changelog:
    
    In ElementBase.scala, give hasFixedLengthOf explicit Boolean type to
    make its type clearer (IDE didn't infer type when I once called it).
    
    In daffodil_main.c, initialize new PState/UState position field.
    
    In xml_reader.c, add strtobool function to convert an XML element's
    text to a boolean.  Sort strtobool, strtodnum, strtofnum, strtonum,
    and strtounum functions and PRIMITIVE_* cases in xmlNumberElem into
    alphabetical order.  Use assert macro to check strtonum's
    pre-condition invariant (minval < maxval).  Use UNUSED macro instead
    of (void) in xmlEndComplex to suppress unused variable compiler
    warnings.  Rename xmlNumberElem's third parameter from numLocation to
    number.  Add PRIMITIVE_BOOLEAN case to xmlNumberElem.
    
    In xml_writer.c, drop (void) and use assert macro to suppress unused
    variable warning in xmlEndComplex.  Rename xmlNumberElem's third
    parameter from numLocation to number.  Sort PRIMITIVE_* cases in
    xmlNumberElem into alphabetical order.  Add PRIMITIVE_BOOLEAN case to
    xmlNumberElem.
    
    In infoset.c, rename walkInfosetNode local variable from numLocation
    to number.  Sort typeCode cases in walkInfosetNode into alphabetical
    order.  Add PRIMITIVE_BOOLEAN case to walkInfosetNode.  Clarify
    eof_or_error_msg error messages to say "Found [eof or error] indicator
    in stream, stopping now" instead of "after reading stream".
    
    In infoset.h, rename VisitNumberElem's third parameter from
    numLocation to number.  Sort TypeCode enumerations into alphabetical
    order.  Add PRIMITIVE_BOOLEAN to TypeCode enumerations.  Add "size_t
    position" fields to both PState and UState structs.  Define UNUSED
    macro to suppress compiler warnings about unused variables.
    
    In parsers.[ch], refactor common C code to read stream, update
    position, and check for errors into a read_stream_update_position
    helper macro.  Add big-endian and little-endian 8, 16, and 32-bit
    parse_<endian>_bool<length> functions to parse binary booleans with
    true_rep and false_rep as additional arguments.  Since DFDL spec says
    true_rep value must fit in uint32_t but we need to know whether
    true_rep is defined or not, pass true_rep as int64_t instead of
    uint32_t, ignore true_rep if negative, and cast true_rep to uint32_t
    before using it.  Swap boolean bytes for endianness after parsing and
    before comparing with true_rep and false_rep.  Use same comparison
    logic as in runtime1's BinaryBooleanParserBase.parse method to conform
    to DFDL spec 13.10 on parsing boolean with binary representation.  Add
    parse_validate_fixed function to validate number is same as fixed
    value after parse.  Make all parser functions update PState's position
    field.  Add parse_fill_bytes function to skip fill bytes until end
    position is reached (like runtime1, does not perform strict check that
    skipped bytes have same value as fill byte).  Reorder parser functions
    into alphabetical order.
    
    In unparsers.[ch], refactor common C code to write stream, update
    position, and check for errors into a write_stream_update_position
    helper macro.  Add big-endian and little-endian 8, 16, and 32-bit
    unparse_<endian>_bool<length> functions to unparse binary booleans
    with true_rep and false_rep as additional arguments.  Use same
    comparison logic as in runtime1's BinaryBooleanUnparserBase.unparse
    method to conform to DFDL spec 13.10 on unparsing boolean with binary
    representation.  Swap boolean bytes for endianness before writing
    their values.  Add unparse_validate_fixed function to validate number
    is same as fixed value during unparse.  Make all unparser functions
    update UState's position field.  Add unparse_fill_bytes function to
    unparse fill bytes until end position is reached.  Reorder unparser
    functions into alphabetical order.
    
    In NestedUnion.h, replace with freshly generated code.
    
    In ex_nums.[ch], replace with newly generated code showing that
    runtime2 will pass true_rep and false_rep values to all parse and
    unparse boolean calls and these values will differ depending on how
    schema defines binaryBooleanFalseRep and binaryBooleanTrueRep for each
    element.  Also show fixed attribute checks for boolean, float, and
    integer elements.
    
    In CodeGenerator.scala, append any code generator warnings to
    CodeGenerator's diagnostics.
    
    In Runtime2CodeGenerator.scala, add BinaryBoolean case to generateCode
    method and extend BinaryBooleanCodeGenerator in order to call
    binaryBooleanGenerateCode method.  Reorder extends/with clauses and
    case expressions into alphabetical order.
    
    In BinaryBooleanCodeGenerator.scala, add binaryBooleanGenerateCode
    method to generate C code to handle 8, 16, and 32-bit
    big-endian/little-endian binary boolean fields.  Run invariant checks
    on binaryBooleanFalseRep and binaryBooleanTrueRep, define trueRep as
    -1 if binaryBooleanTrueRep is not defined and pass both it and
    falseRep to parse_<endian>_bit<bits> calls.  Meanwhile, define
    unparseTrueRep as either trueRep or ~falseRep and pass both it and
    falseRep to unparse_<endian>_bool<bits> calls.  Also add validation of
    boolean fixed values and make code more similar in preparation for
    refactoring duplicated common code from Binary*CodeGenerator traits
    later.
    
    In BinaryFloatCodeGenerator.scala, add validation of floating point
    fixed values and make code more similar for refactoring later.
    
    In BinaryIntegerKnownLengthCodeGenerator.scala, generate code to check
    that the corresponding C struct member has the same value as the value
    of the 'fixed' attribute during parse and unparse if there is any
    'fixed' attribute.  Make code more similar for refactoring later.
    
    In CodeGeneratorState.scala, modify addImplementation to emit UNUSED
    macro calls to avoid compiler warnings for empty sequences which
    produce empty C structs with no members to parse or unparse.  Make
    addBeforeSwitchStatements and addAfterSwitchStatements support padding
    complex elements to explicit lengths with fill bytes in addition to
    supporting choice groups.  Modify addSimpleTypeStatements to ignore
    empty string arguments.  Modify addComplexTypeStatements to handle
    arrays of complex types.  Because schema authors don't always get base
    types right, add private methods getLengthInBits and getPrimType and
    use them to return what types schema authors actually want if simple
    elemnts' explicit lengths don't match their base types' implicit
    lengths.  Make getPrimType generate a schema definition warning if it
    returns a different primType than an element's original primType
    definition.  Call getPrimType in addSimpleTypeERD and
    addFieldDeclaration to select correct ERD type codes and C types for
    simple elements.  Add PrimType.Boolean case to addSimpleTypeERD and
    addFieldDeclaration and sort their cases into alphabetical order.  Add
    stdbool.h header to generateCodeHeader.
    
    In ElementParseAndUnspecifiedLengthCodeGenerator.scala, need to pass
    element to addAfterSwitchStatements to let it get element's explicit
    length and fill byte.
    
    In ex_nums.dfdl.xsd, test both binaryBooleanTrueRep="" and
    binaryBooleanTrueRep="1".  Add array, bigEndian, and littleEndian
    boolean elements to ensure all variations of 8, 16, and 32-bit boolean
    elements are tested.  Also add integer & nonNegativeInteger elements
    with explicit lengths to test these types of integer elements work
    too.  Sort all elements in alphabetical order by their names.  Add new
    elements to validate fixed values for boolean, float, and integer
    numbers.
    
    In ex_nums.tdml, add unparse_errors test and corresponding
    ex_nums_unparse_errors.xml data file to verify error message when
    unparsing incorrect fixed values.
    
    In ex_nums_parse* and ex_nums_unparse*, add data for all new elements.
    
    In Runtime2TDMLDFDLProcessor.scala, pass generator diagnostics to
    Runtime2TDMLDFDLProcessor so we don't lose them (sadly, TDMLRunner
    never checks diagnostics in "Right" tuples containing both diagnostics
    and processor).  Ensure these diagnostics will be passed to
    Runtime2TDMLParseResult and Runtime2TDMLUnparseResult as well,
    However, TDMLRunner won't check any error or warning diagnostics in
    runtime2's TDML tests because it considers them cross tests.  I had to
    set defaultShouldDoWarningComparisonOnCrossTests true in RunnerFactory
    while running runtime2's ex_nums.tdml tests to verify that I could get
    `<tdml:warnings>` in them checked appropriately; otherwise the
    warnings are never checked.  Still, we will see generator warnings
    when we run "daffodil generate c -s ex_nums.dfdl.xsd" now:
    
        [warning] Schema Definition Warning: Ignoring PrimType integer, using short
        Schema context: be_integer16 Location line 81 column 30 in file:/home/interran/apache/daffodil-runtime2/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
        [warning] Schema Definition Warning: Ignoring PrimType nonNegativeInteger, using unsignedInt
        Schema context: be_nonNegativeInteger32 Location line 88 column 30 in file:/home/interran/apache/daffodil-runtime2/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
        [warning] Schema Definition Warning: Ignoring PrimType integer, using long
        Schema context: le_integer64 Location line 124 column 30 in file:/home/interran/apache/daffodil-runtime2/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
        [warning] Schema Definition Warning: Ignoring PrimType nonNegativeInteger, using unsignedByte
        Schema context: le_nonNegativeInteger8 Location line 136 column 30 in file:/home/interran/apache/daffodil-runtime2/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
    
    Add the following new collaborator schemas, test cases, and data files
    to daffodil-test:
     - ISRM_green_to_orange_60000*
     - ISRM_orange_to_green_60002*
     - MPU_green_to_orange_60004*
     - MPU_orange_to_green_60006*
     - TestIsrmGreenToOrange60000.scala
     - TestIsrmOrangeToGreen60002.scala
     - TestMpuGreenToOrange60004.scala
     - TestMpuOrangeToGreen60006.scala
    
    In aptina_settings_* and limits_*, add new binary data and unparse XML
    files for new elements added to orion-command.dfdl.xsd.
    
    In camera_state_unparse.xml, command_unparse.xml, and
    video_settings_unparse.xml, append "Decl" to root element names to
    accommodate renamed element names in orion-command.dfdl.xsd.
    
    In orion-command.dfdl.xsd, update to latest version from collaborator
    with new messages AptinaSettings and Limits and all root elements
    renamed to end with "Decl" instead of having types end with "Type".
    
    In orion-command.tdml, append "Decl" to all root element names, add
    test cases for new messages AptinaSettings and Limits, and reorder
    test cases to follow same order as orion-command.dfdl.xsd.
    
    In TestExNums.scala, add new unparse_errors test.
    
    In TestOrionCommand.scala, add test cases for new messages
    AptinaSettings and Limits and reorder test cases to follow same order
    as orion-command.tdml.
    
    In Rat.scala, ignore the newly added binary data files.
---
 .../org/apache/daffodil/dsom/ElementBase.scala     |   2 +-
 .../src/main/resources/c/libcli/daffodil_main.c    |   4 +-
 .../src/main/resources/c/libcli/xml_reader.c       | 180 +++---
 .../src/main/resources/c/libcli/xml_writer.c       |  75 +--
 .../src/main/resources/c/libruntime/infoset.c      |  43 +-
 .../src/main/resources/c/libruntime/infoset.h      |  29 +-
 .../src/main/resources/c/libruntime/parsers.c      | 143 +++--
 .../src/main/resources/c/libruntime/parsers.h      |  50 +-
 .../src/main/resources/c/libruntime/unparsers.c    | 122 ++--
 .../src/main/resources/c/libruntime/unparsers.h    |  51 +-
 .../src/main/resources/examples/NestedUnion.h      |   1 +
 .../src/main/resources/examples/ex_nums.c          | 620 ++++++++++++++++-----
 .../src/main/resources/examples/ex_nums.h          |  54 +-
 .../apache/daffodil/runtime2/CodeGenerator.scala   |   3 +-
 .../daffodil/runtime2/Runtime2CodeGenerator.scala  |  16 +-
 ...ator.scala => BinaryBooleanCodeGenerator.scala} |  64 ++-
 .../generators/BinaryFloatCodeGenerator.scala      |  24 +-
 .../BinaryIntegerKnownLengthCodeGenerator.scala    |  23 +-
 .../runtime2/generators/CodeGeneratorState.scala   | 201 +++++--
 ...entParseAndUnspecifiedLengthCodeGenerator.scala |   2 +-
 .../org/apache/daffodil/runtime2/ex_nums.dfdl.xsd  | 154 +++--
 .../org/apache/daffodil/runtime2/ex_nums.tdml      |  15 +
 .../org/apache/daffodil/runtime2/ex_nums_parse.dat | Bin 102 -> 159 bytes
 ...rse_runtime1.xml => ex_nums_unparse_errors.xml} |  54 +-
 .../daffodil/runtime2/ex_nums_unparse_runtime1.xml |  54 +-
 .../daffodil/runtime2/ex_nums_unparse_runtime2.xml |  54 +-
 .../tdml/processor/Runtime2TDMLDFDLProcessor.scala |  16 +-
 .../runtime2/ISRM_green_to_orange_60000.dfdl.xsd   | 107 ++++
 .../runtime2/ISRM_green_to_orange_60000.tdml       |  44 +-
 .../ISRM_green_to_orange_60000_parse_0.dat         | Bin 0 -> 212 bytes
 .../ISRM_green_to_orange_60000_parse_1.dat         | Bin 0 -> 212 bytes
 .../ISRM_green_to_orange_60000_unparse_0.xml       | 195 +++++++
 ...ml => ISRM_green_to_orange_60000_unparse_1.xml} |  16 +-
 .../runtime2/ISRM_orange_to_green_60002.dfdl.xsd   |  73 +++
 .../runtime2/ISRM_orange_to_green_60002.tdml       |  48 +-
 .../runtime2/ISRM_orange_to_green_60002_parse.dat  | Bin 0 -> 80 bytes
 .../ISRM_orange_to_green_60002_unparse.xml         | 102 ++++
 .../runtime2/MPU_green_to_orange_60004.dfdl.xsd    |  74 +++
 .../runtime2/MPU_green_to_orange_60004.tdml        |  48 +-
 .../runtime2/MPU_green_to_orange_60004_parse.dat   | Bin 0 -> 81 bytes
 .../runtime2/MPU_green_to_orange_60004_unparse.xml | 103 ++++
 .../runtime2/MPU_orange_to_green_60006.dfdl.xsd    | 163 ++++++
 .../runtime2/MPU_orange_to_green_60006.tdml        |  44 +-
 .../runtime2/MPU_orange_to_green_60006_parse_0.dat | Bin 0 -> 240 bytes
 .../runtime2/MPU_orange_to_green_60006_parse_1.dat | Bin 0 -> 240 bytes
 .../MPU_orange_to_green_60006_unparse_0.xml        | 219 ++++++++
 ...xml => MPU_orange_to_green_60006_unparse_1.xml} |  16 +-
 .../daffodil/runtime2/aptina_settings_parse.dat    | Bin 0 -> 21 bytes
 ...ate_unparse.xml => aptina_settings_unparse.xml} |  22 +-
 .../daffodil/runtime2/camera_state_unparse.xml     |   4 +-
 .../apache/daffodil/runtime2/command_unparse.xml   |   4 +-
 .../org/apache/daffodil/runtime2/limits_parse.dat  | Bin 0 -> 6 bytes
 ...camera_state_unparse.xml => limits_unparse.xml} |  13 +-
 .../daffodil/runtime2/orion-command.dfdl.xsd       |  43 +-
 .../apache/daffodil/runtime2/orion-command.tdml    |  91 ++-
 .../daffodil/runtime2/video_settings_unparse.xml   |   4 +-
 .../org/apache/daffodil/runtime2/TestExNums.scala  |   1 +
 ...mand.scala => TestIsrmGreenToOrange60000.scala} |  22 +-
 ...Nums.scala => TestIsrmOrangeToGreen60002.scala} |  18 +-
 ...xNums.scala => TestMpuGreenToOrange60004.scala} |  18 +-
 ...xNums.scala => TestMpuOrangeToGreen60006.scala} |  20 +-
 .../daffodil/runtime2/TestOrionCommand.scala       |   8 +-
 project/Rat.scala                                  |   8 +
 63 files changed, 2753 insertions(+), 829 deletions(-)

diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
index 965dfd9..58d2b46 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
@@ -608,7 +608,7 @@ trait ElementBase
     }
   }
 
-  final def hasFixedLengthOf(n: Int) = {
+  final def hasFixedLengthOf(n: Int): Boolean = {
     // FIXME: needs to work in lengthUnits. If length units is bytes/bits
     // and encoding is variable-width charset, what should this return?
     // (Perhaps should be usage error?)
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
index 56320ff..fa53b57 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
@@ -85,7 +85,7 @@ main(int argc, char *argv[])
             output = fopen_or_exit(output, daffodil_parse.outfile, "w");
 
             // Parse the input file into our infoset.
-            PState pstate = {input, NULL};
+            PState pstate = {input, 0, NULL};
             root->erd->parseSelf(root, &pstate);
             continue_or_exit(pstate.error_msg);
 
@@ -126,7 +126,7 @@ main(int argc, char *argv[])
             }
 
             // Unparse our infoset to the output file.
-            UState ustate = {output, NULL};
+            UState ustate = {output, 0, NULL};
             root->erd->unparseSelf(root, &ustate);
             continue_or_exit(ustate.error_msg);
         }
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
index 226b015..3688933 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
@@ -16,30 +16,66 @@
  */
 
 #include "xml_reader.h"
+#include <assert.h>    // for assert
 #include <errno.h>     // for errno
 #include <inttypes.h>  // for strtoimax, strtoumax
 #include <mxml.h>      // for mxmlWalkNext, mxmlGetType, mxmlGetElement, MXML_DESCEND, MXML_OPAQUE, mxmlDelete, mxmlGetOpaque, mxmlLoadFile, MXML_OPAQUE_CALLBACK
+#include <stdbool.h>   // for bool, false, true
 #include <stdint.h>    // for intmax_t, uintmax_t, int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t, INT16_MAX, INT16_MIN, INT32_MAX, INT32_MIN, INT64_MAX, INT64_MIN, INT8_MAX, INT8_MIN, UINT16_MAX, UINT32_MAX, UINT64_MAX, UINT8_MAX
 #include <stdlib.h>    // for strtod, strtof
 #include <string.h>    // for strcmp, strlen, strncmp
 
-// Convert an XML element's text to a signed integer (BSD function not
-// widely available, so call strtoimax with our own error checking)
+// Convert an XML element's text to a boolean with error checking
 
-static intmax_t
-strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
-         const char **errstrp)
+static bool
+strtobool(const char *numptr, const char **errstrp)
+{
+    // The lexical space of xs:boolean accepts true, false, 1, and 0
+    bool        value = false;
+    const char *error_msg = NULL;
+
+    // Report any issues converting the string to a boolean
+    if (strcmp(numptr, "true") == 0)
+    {
+        value = true;
+    }
+    else if (strcmp(numptr, "false") == 0)
+    {
+        value = false;
+    }
+    else if (strcmp(numptr, "1") == 0)
+    {
+        value = true;
+    }
+    else if (strcmp(numptr, "0") == 0)
+    {
+        value = false;
+    }
+    else
+    {
+        error_msg = "Error converting XML data to boolean";
+    }
+
+    *errstrp = error_msg;
+    return value;
+}
+
+// Convert an XML element's text to a double (call strtod with our own
+// error checking)
+
+static double
+strtodnum(const char *numptr, const char **errstrp)
 {
     char *endptr = NULL;
 
-    // Clear errno to detect error after calling strtoimax
+    // Clear errno to detect error after calling strtod
     errno = 0;
-    const intmax_t value = strtoimax(numptr, &endptr, 10);
+    const double value = strtod(numptr, &endptr);
 
     // Report any issues converting the string to a number
     if (errno != 0)
     {
-        *errstrp = "Error converting XML data to integer";
+        *errstrp = "Error converting XML data to number";
     }
     else if (endptr == numptr)
     {
@@ -49,10 +85,6 @@ strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
     {
         *errstrp = "Found non-number characters in XML data";
     }
-    else if (value < minval || value > maxval || maxval < minval)
-    {
-        *errstrp = "Number in XML data out of range";
-    }
     else
     {
         *errstrp = NULL;
@@ -61,22 +93,22 @@ strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
     return value;
 }
 
-// Convert an XML element's text to an unsigned integer (call strtoumax
-// with our own error checking)
+// Convert an XML element's text to a float (call strtof with our own
+// error checking)
 
-static uintmax_t
-strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
+static float
+strtofnum(const char *numptr, const char **errstrp)
 {
     char *endptr = NULL;
 
-    // Clear errno to detect error after calling strtoumax
+    // Clear errno to detect error after calling strtof
     errno = 0;
-    const uintmax_t value = strtoumax(numptr, &endptr, 10);
+    const float value = strtof(numptr, &endptr);
 
     // Report any issues converting the string to a number
     if (errno != 0)
     {
-        *errstrp = "Error converting XML data to integer";
+        *errstrp = "Error converting XML data to number";
     }
     else if (endptr == numptr)
     {
@@ -86,10 +118,6 @@ strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
     {
         *errstrp = "Found non-number characters in XML data";
     }
-    else if (value > maxval)
-    {
-        *errstrp = "Number in XML data out of range";
-    }
     else
     {
         *errstrp = NULL;
@@ -98,22 +126,24 @@ strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
     return value;
 }
 
-// Convert an XML element's text to a float (call strtof with our own
-// error checking)
+// Convert an XML element's text to a signed integer (BSD function not
+// widely available, so call strtoimax with our own error checking)
 
-static float
-strtofnum(const char *numptr, const char **errstrp)
+static intmax_t
+strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
+         const char **errstrp)
 {
     char *endptr = NULL;
+    assert(minval < maxval);
 
-    // Clear errno to detect error after calling strtof
+    // Clear errno to detect error after calling strtoimax
     errno = 0;
-    const float value = strtof(numptr, &endptr);
+    const intmax_t value = strtoimax(numptr, &endptr, 10);
 
     // Report any issues converting the string to a number
     if (errno != 0)
     {
-        *errstrp = "Error converting XML data to number";
+        *errstrp = "Error converting XML data to integer";
     }
     else if (endptr == numptr)
     {
@@ -123,6 +153,10 @@ strtofnum(const char *numptr, const char **errstrp)
     {
         *errstrp = "Found non-number characters in XML data";
     }
+    else if (value < minval || value > maxval)
+    {
+        *errstrp = "Number in XML data out of range";
+    }
     else
     {
         *errstrp = NULL;
@@ -131,22 +165,22 @@ strtofnum(const char *numptr, const char **errstrp)
     return value;
 }
 
-// Convert an XML element's text to a double (call strtod with our own
-// error checking)
+// Convert an XML element's text to an unsigned integer (call strtoumax
+// with our own error checking)
 
-static double
-strtodnum(const char *numptr, const char **errstrp)
+static uintmax_t
+strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
 {
     char *endptr = NULL;
 
-    // Clear errno to detect error after calling strtod
+    // Clear errno to detect error after calling strtoumax
     errno = 0;
-    const double value = strtod(numptr, &endptr);
+    const uintmax_t value = strtoumax(numptr, &endptr, 10);
 
     // Report any issues converting the string to a number
     if (errno != 0)
     {
-        *errstrp = "Error converting XML data to number";
+        *errstrp = "Error converting XML data to integer";
     }
     else if (endptr == numptr)
     {
@@ -156,6 +190,10 @@ strtodnum(const char *numptr, const char **errstrp)
     {
         *errstrp = "Found non-number characters in XML data";
     }
+    else if (value > maxval)
+    {
+        *errstrp = "Number in XML data out of range";
+    }
     else
     {
         *errstrp = NULL;
@@ -261,16 +299,16 @@ xmlStartComplex(XMLReader *reader, const InfosetBase *base)
 static const char *
 xmlEndComplex(XMLReader *reader, const InfosetBase *base)
 {
-    (void)reader;
-    (void)base;
+    UNUSED(reader); // because nothing to read
+    UNUSED(base); // because nothing to check
     return NULL;
 }
 
-// Read 8, 16, 32, or 64-bit signed/unsigned integer number or floating point
-// number from XML data
+// Read a boolean, 32-bit or 64-bit real number, or 8, 16, 32, or
+// 64-bit signed or unsigned integer from XML data
 
 static const char *
-xmlNumberElem(XMLReader *reader, const ERD *erd, void *numLocation)
+xmlNumberElem(XMLReader *reader, const ERD *erd, void *number)
 {
     // Consume any newlines or whitespace before the element
     while (mxmlGetType(reader->node) == MXML_OPAQUE)
@@ -292,48 +330,50 @@ xmlNumberElem(XMLReader *reader, const ERD *erd, void *numLocation)
             // Check for any errors getting the number
             const char *errstr = NULL;
 
-            // Handle varying bit lengths of both signed & unsigned integers and
-            // floating point numbers
+            // Handle varying bit lengths of both signed & unsigned numbers
             const enum TypeCode typeCode = erd->typeCode;
             switch (typeCode)
             {
-            case PRIMITIVE_UINT64:
-                *(uint64_t *)numLocation =
-                    (uint64_t)strtounum(number_from_xml, UINT64_MAX, &errstr);
-                break;
-            case PRIMITIVE_UINT32:
-                *(uint32_t *)numLocation =
-                    (uint32_t)strtounum(number_from_xml, UINT32_MAX, &errstr);
+            case PRIMITIVE_BOOLEAN:
+                *(bool *)number = strtobool(number_from_xml, &errstr);
                 break;
-            case PRIMITIVE_UINT16:
-                *(uint16_t *)numLocation =
-                    (uint16_t)strtounum(number_from_xml, UINT16_MAX, &errstr);
+            case PRIMITIVE_FLOAT:
+                *(float *)number = strtofnum(number_from_xml, &errstr);
                 break;
-            case PRIMITIVE_UINT8:
-                *(uint8_t *)numLocation =
-                    (uint8_t)strtounum(number_from_xml, UINT8_MAX, &errstr);
+            case PRIMITIVE_DOUBLE:
+                *(double *)number = strtodnum(number_from_xml, &errstr);
                 break;
-            case PRIMITIVE_INT64:
-                *(int64_t *)numLocation = (int64_t)strtonum(
-                    number_from_xml, INT64_MIN, INT64_MAX, &errstr);
+            case PRIMITIVE_INT16:
+                *(int16_t *)number = (int16_t)strtonum(
+                    number_from_xml, INT16_MIN, INT16_MAX, &errstr);
                 break;
             case PRIMITIVE_INT32:
-                *(int32_t *)numLocation = (int32_t)strtonum(
+                *(int32_t *)number = (int32_t)strtonum(
                     number_from_xml, INT32_MIN, INT32_MAX, &errstr);
                 break;
-            case PRIMITIVE_INT16:
-                *(int16_t *)numLocation = (int16_t)strtonum(
-                    number_from_xml, INT16_MIN, INT16_MAX, &errstr);
+            case PRIMITIVE_INT64:
+                *(int64_t *)number = (int64_t)strtonum(
+                    number_from_xml, INT64_MIN, INT64_MAX, &errstr);
                 break;
             case PRIMITIVE_INT8:
-                *(int8_t *)numLocation = (int8_t)strtonum(
-                    number_from_xml, INT8_MIN, INT8_MAX, &errstr);
+                *(int8_t *)number = (int8_t)strtonum(number_from_xml, INT8_MIN,
+                                                     INT8_MAX, &errstr);
                 break;
-            case PRIMITIVE_FLOAT:
-                *(float *)numLocation = strtofnum(number_from_xml, &errstr);
+            case PRIMITIVE_UINT16:
+                *(uint16_t *)number =
+                    (uint16_t)strtounum(number_from_xml, UINT16_MAX, &errstr);
                 break;
-            case PRIMITIVE_DOUBLE:
-                *(double *)numLocation = strtodnum(number_from_xml, &errstr);
+            case PRIMITIVE_UINT32:
+                *(uint32_t *)number =
+                    (uint32_t)strtounum(number_from_xml, UINT32_MAX, &errstr);
+                break;
+            case PRIMITIVE_UINT64:
+                *(uint64_t *)number =
+                    (uint64_t)strtounum(number_from_xml, UINT64_MAX, &errstr);
+                break;
+            case PRIMITIVE_UINT8:
+                *(uint8_t *)number =
+                    (uint8_t)strtounum(number_from_xml, UINT8_MAX, &errstr);
                 break;
             default:
                 errstr = "Unexpected ERD typeCode while reading number from "
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
index 073423e..4f609ce 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
@@ -16,11 +16,13 @@
  */
 
 #include "xml_writer.h"
-#include "stack.h"   // for stack_is_empty, stack_pop, stack_push, stack_top, stack_init, stack_is_full
-#include <assert.h>  // for assert
-#include <mxml.h>    // for mxmlNewOpaquef, mxml_node_t, mxmlElementSetAttr, mxmlNewElement, mxmlDelete, mxmlNewXML, mxmlSaveFile, MXML_NO_CALLBACK
-#include <stdint.h>  // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
-#include <stdio.h>   // for NULL, fflush
+#include "stack.h"    // for stack_is_empty, stack_pop, stack_push, stack_top, stack_init, stack_is_full
+#include <assert.h>   // for assert
+#include <mxml.h>     // for mxmlNewOpaquef, mxml_node_t, mxmlElementSetAttr, mxmlNewElement, mxmlDelete, mxmlNewXML, mxmlSaveFile, MXML_NO_CALLBACK
+#include <stdbool.h>  // for bool
+#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
+#include <stdio.h>    // for NULL, fflush
+#include <string.h>   // for strcmp
 
 // Push new XML document on stack.  This function is not
 // thread-safe since it uses static storage.
@@ -85,12 +87,15 @@ xmlEndComplex(XMLWriter *writer, const InfosetBase *base)
     if (!stack_is_empty(&writer->stack))
     {
         complex = stack_pop(&writer->stack);
-        (void)base;
+
+        const char *name_from_xml = mxmlGetElement(complex);
+        const char *name_from_erd = get_erd_name(base->erd);
+        assert(strcmp(name_from_xml, name_from_erd) == 0);
     }
     return complex ? NULL : "Underflowed the XML stack";
 }
 
-// Fix a floating point number to conform to xsd:float syntax if needed
+// Fix a real number to conform to xsd:float syntax if needed
 
 static void
 fixNumberIfNeeded(const char *text)
@@ -106,11 +111,11 @@ fixNumberIfNeeded(const char *text)
     //  - Add .0 to 1 to get 1.0 (not worth it)
 }
 
-// Write 8, 16, 32, or 64-bit signed/unsigned Number or floating point number as
-// element
+// Write a boolean, 32-bit or 64-bit real number, or 8, 16, 32, or
+// 64-bit signed or unsigned integer as an XML element's value
 
 static const char *
-xmlNumberElem(XMLWriter *writer, const ERD *erd, const void *numLocation)
+xmlNumberElem(XMLWriter *writer, const ERD *erd, const void *number)
 {
     mxml_node_t *parent = stack_top(&writer->stack);
     const char * name = get_erd_name(erd);
@@ -129,39 +134,43 @@ xmlNumberElem(XMLWriter *writer, const ERD *erd, const void *numLocation)
     mxml_node_t *       text = NULL;
     switch (typeCode)
     {
-    case PRIMITIVE_UINT64:
-        text = mxmlNewOpaquef(simple, "%lu", *(const uint64_t *)numLocation);
-        break;
-    case PRIMITIVE_UINT32:
-        text = mxmlNewOpaquef(simple, "%u", *(const uint32_t *)numLocation);
+    case PRIMITIVE_BOOLEAN:
+        text = mxmlNewOpaquef(simple, "%s",
+                              *(const bool *)number ? "true" : "false");
         break;
-    case PRIMITIVE_UINT16:
-        text = mxmlNewOpaquef(simple, "%hu", *(const uint16_t *)numLocation);
+    case PRIMITIVE_FLOAT:
+        // Round-trippable float, shortest possible
+        text = mxmlNewOpaquef(simple, "%.9G", *(const float *)number);
+        fixNumberIfNeeded(mxmlGetOpaque(text));
         break;
-    case PRIMITIVE_UINT8:
-        text = mxmlNewOpaquef(simple, "%hhu", *(const uint8_t *)numLocation);
+    case PRIMITIVE_DOUBLE:
+        // Round-trippable double, shortest possible
+        text = mxmlNewOpaquef(simple, "%.17lG", *(const double *)number);
+        fixNumberIfNeeded(mxmlGetOpaque(text));
         break;
-    case PRIMITIVE_INT64:
-        text = mxmlNewOpaquef(simple, "%li", *(const int64_t *)numLocation);
+    case PRIMITIVE_INT16:
+        text = mxmlNewOpaquef(simple, "%hi", *(const int16_t *)number);
         break;
     case PRIMITIVE_INT32:
-        text = mxmlNewOpaquef(simple, "%i", *(const int32_t *)numLocation);
+        text = mxmlNewOpaquef(simple, "%i", *(const int32_t *)number);
         break;
-    case PRIMITIVE_INT16:
-        text = mxmlNewOpaquef(simple, "%hi", *(const int16_t *)numLocation);
+    case PRIMITIVE_INT64:
+        text = mxmlNewOpaquef(simple, "%li", *(const int64_t *)number);
         break;
     case PRIMITIVE_INT8:
-        text = mxmlNewOpaquef(simple, "%hhi", *(const int8_t *)numLocation);
+        text = mxmlNewOpaquef(simple, "%hhi", *(const int8_t *)number);
         break;
-    case PRIMITIVE_FLOAT:
-        // Round-trippable float, shortest possible
-        text = mxmlNewOpaquef(simple, "%.9G", *(const float *)numLocation);
-        fixNumberIfNeeded(mxmlGetOpaque(text));
+    case PRIMITIVE_UINT16:
+        text = mxmlNewOpaquef(simple, "%hu", *(const uint16_t *)number);
         break;
-    case PRIMITIVE_DOUBLE:
-        // Round-trippable double, shortest possible
-        text = mxmlNewOpaquef(simple, "%.17lG", *(const double *)numLocation);
-        fixNumberIfNeeded(mxmlGetOpaque(text));
+    case PRIMITIVE_UINT32:
+        text = mxmlNewOpaquef(simple, "%u", *(const uint32_t *)number);
+        break;
+    case PRIMITIVE_UINT64:
+        text = mxmlNewOpaquef(simple, "%lu", *(const uint64_t *)number);
+        break;
+    case PRIMITIVE_UINT8:
+        text = mxmlNewOpaquef(simple, "%hhu", *(const uint8_t *)number);
         break;
     default:
         // Let text remain NULL and report error below
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
index 9377b87..4f102f1 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
@@ -136,37 +136,36 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
         // We use only one of these variables below depending on typeCode
         const InfosetBase *childNode =
             (const InfosetBase *)((const char *)infoNode + offset);
-        const void *numLocation =
-            (const void *)((const char *)infoNode + offset);
+        const void *number = (const void *)((const char *)infoNode + offset);
 
         // Will need to handle more element types
         const enum TypeCode typeCode = childERD->typeCode;
         switch (typeCode)
         {
-        case COMPLEX:
-            error_msg = walkInfosetNode(handler, childNode);
-            break;
-        case PRIMITIVE_UINT64:
-        case PRIMITIVE_UINT32:
-        case PRIMITIVE_UINT16:
-        case PRIMITIVE_UINT8:
-        case PRIMITIVE_INT64:
-        case PRIMITIVE_INT32:
-        case PRIMITIVE_INT16:
-        case PRIMITIVE_INT8:
-        case PRIMITIVE_FLOAT:
-        case PRIMITIVE_DOUBLE:
-            error_msg =
-                handler->visitNumberElem(handler, childERD, numLocation);
-            break;
         case CHOICE:
             // Point next ERD to choice of alternative elements' ERDs
             if (!infoNode->erd->initChoice(infoNode, rootElement()))
             {
-                error_msg =
-                    "Walk error: no match between choice dispatch key and any branch key";
+                error_msg = "Walk error: no match between choice dispatch key "
+                            "and any branch key";
             }
             break;
+        case COMPLEX:
+            error_msg = walkInfosetNode(handler, childNode);
+            break;
+        case PRIMITIVE_BOOLEAN:
+        case PRIMITIVE_DOUBLE:
+        case PRIMITIVE_FLOAT:
+        case PRIMITIVE_INT16:
+        case PRIMITIVE_INT32:
+        case PRIMITIVE_INT64:
+        case PRIMITIVE_INT8:
+        case PRIMITIVE_UINT16:
+        case PRIMITIVE_UINT32:
+        case PRIMITIVE_UINT64:
+        case PRIMITIVE_UINT8:
+            error_msg = handler->visitNumberElem(handler, childERD, number);
+            break;
         }
     }
 
@@ -209,11 +208,11 @@ eof_or_error_msg(FILE *stream)
 {
     if (feof(stream))
     {
-        return "Found eof indicator after reading stream";
+        return "Found eof indicator in stream, stopping now";
     }
     else if (ferror(stream))
     {
-        return "Found error indicator after reading stream";
+        return "Found error indicator in stream, stopping now";
     }
     else
     {
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
index 404bf6d..bc4315e 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
@@ -43,7 +43,7 @@ typedef const char *(*VisitStartComplex)(const VisitEventHandler *handler,
 typedef const char *(*VisitEndComplex)(const VisitEventHandler *handler,
                                        const InfosetBase *      base);
 typedef const char *(*VisitNumberElem)(const VisitEventHandler *handler,
-                                       const ERD *erd, const void *numLocation);
+                                       const ERD *erd, const void *number);
 
 // NamedQName - name of an infoset element
 
@@ -58,18 +58,19 @@ typedef struct NamedQName
 
 enum TypeCode
 {
+    CHOICE,
     COMPLEX,
-    PRIMITIVE_UINT64,
-    PRIMITIVE_UINT32,
-    PRIMITIVE_UINT16,
-    PRIMITIVE_UINT8,
-    PRIMITIVE_INT64,
-    PRIMITIVE_INT32,
+    PRIMITIVE_BOOLEAN,
+    PRIMITIVE_DOUBLE,
+    PRIMITIVE_FLOAT,
     PRIMITIVE_INT16,
+    PRIMITIVE_INT32,
+    PRIMITIVE_INT64,
     PRIMITIVE_INT8,
-    PRIMITIVE_FLOAT,
-    PRIMITIVE_DOUBLE,
-    CHOICE
+    PRIMITIVE_UINT16,
+    PRIMITIVE_UINT32,
+    PRIMITIVE_UINT64,
+    PRIMITIVE_UINT8
 };
 
 // ERD - element runtime data needed to parse/unparse objects
@@ -100,6 +101,7 @@ typedef struct InfosetBase
 typedef struct PState
 {
     FILE *      stream;    // input to read data from
+    size_t      position;  // 0-based position in stream
     const char *error_msg; // to stop if an error happens
 } PState;
 
@@ -108,6 +110,7 @@ typedef struct PState
 typedef struct UState
 {
     FILE *      stream;    // output to write data to
+    size_t      position;  // 0-based position in stream
     const char *error_msg; // to stop if an error happens
 } UState;
 
@@ -144,8 +147,12 @@ extern const char *walkInfoset(const VisitEventHandler *handler,
 
 extern const char *eof_or_error_msg(FILE *stream);
 
-// NO_CHOICE - value stored in an uninitialized _choice field
+// NO_CHOICE - define value stored in uninitialized _choice field
 
 static const size_t NO_CHOICE = (size_t)-1;
 
+// UNUSED - suppress compiler warning about unused variable
+
+#define UNUSED(x) (void)(x)
+
 #endif // INFOSET_H
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
index 8d97b99..db3a783 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
@@ -16,8 +16,9 @@
  */
 
 #include "parsers.h"
-#include <endian.h>  // for be32toh, be64toh, le32toh, le64toh, be16toh, le16toh
-#include <stdio.h>   // for fread, size_t
+#include <endian.h>   // for be32toh, be64toh, le32toh, le64toh, be16toh, le16toh
+#include <stdbool.h>  // for bool
+#include <stdio.h>    // for fread, size_t
 
 // Macros that are not defined by <endian.h>
 
@@ -25,8 +26,52 @@
 
 #define le8toh(var) var
 
+// Helper macro to reduce duplication of C code reading stream,
+// updating position, and checking for errors
+
+#define read_stream_update_position                                            \
+    size_t count = fread(&buffer.c_val, 1, sizeof(buffer), pstate->stream);    \
+    pstate->position += count;                                                 \
+    if (count < sizeof(buffer))                                                \
+    {                                                                          \
+        pstate->error_msg = eof_or_error_msg(pstate->stream);                  \
+    }
+
 // Macros to define parse_<endian>_<type> functions
 
+#define define_parse_endian_bool(endian, bits)                                 \
+    void parse_##endian##_bool##bits(bool *number, int64_t true_rep,           \
+                                     uint32_t false_rep, PState *pstate)       \
+    {                                                                          \
+        if (!pstate->error_msg)                                                \
+        {                                                                      \
+            union                                                              \
+            {                                                                  \
+                char           c_val[sizeof(uint##bits##_t)];                  \
+                uint##bits##_t i_val;                                          \
+            } buffer;                                                          \
+                                                                               \
+            read_stream_update_position;                                       \
+            buffer.i_val = endian##bits##toh(buffer.i_val);                    \
+            if (true_rep < 0)                                                  \
+            {                                                                  \
+                *number = (buffer.i_val != false_rep);                         \
+            }                                                                  \
+            else if (buffer.i_val == (uint32_t)true_rep)                       \
+            {                                                                  \
+                *number = true;                                                \
+            }                                                                  \
+            else if (buffer.i_val == false_rep)                                \
+            {                                                                  \
+                *number = false;                                               \
+            }                                                                  \
+            else                                                               \
+            {                                                                  \
+                pstate->error_msg = "Unable to parse boolean";                 \
+            }                                                                  \
+        }                                                                      \
+    }
+
 #define define_parse_endian_real(endian, type, bits)                           \
     void parse_##endian##_##type(type *number, PState *pstate)                 \
     {                                                                          \
@@ -38,12 +83,8 @@
                 type           f_val;                                          \
                 uint##bits##_t i_val;                                          \
             } buffer;                                                          \
-            size_t count =                                                     \
-                fread(&buffer.c_val, 1, sizeof(buffer), pstate->stream);       \
-            if (count < sizeof(buffer))                                        \
-            {                                                                  \
-                pstate->error_msg = eof_or_error_msg(pstate->stream);          \
-            }                                                                  \
+                                                                               \
+            read_stream_update_position;                                       \
             buffer.i_val = endian##bits##toh(buffer.i_val);                    \
             *number = buffer.f_val;                                            \
         }                                                                      \
@@ -59,54 +100,78 @@
                 char           c_val[sizeof(type##bits##_t)];                  \
                 type##bits##_t i_val;                                          \
             } buffer;                                                          \
-            size_t count =                                                     \
-                fread(&buffer.c_val, 1, sizeof(buffer), pstate->stream);       \
-            if (count < sizeof(buffer))                                        \
-            {                                                                  \
-                pstate->error_msg = eof_or_error_msg(pstate->stream);          \
-            }                                                                  \
+                                                                               \
+            read_stream_update_position;                                       \
             *number = endian##bits##toh(buffer.i_val);                         \
         }                                                                      \
     }
 
-// Define functions to parse binary real and integer numbers
+// Define functions to parse binary real numbers and integers
 
-define_parse_endian_real(be, double, 64)
+define_parse_endian_bool(be, 16);
+define_parse_endian_bool(be, 32);
+define_parse_endian_bool(be, 8);
 
+define_parse_endian_real(be, double, 64)
 define_parse_endian_real(be, float, 32)
 
-define_parse_endian_integer(be, uint, 64)
-
-define_parse_endian_integer(be, uint, 32)
+define_parse_endian_integer(be, int, 16)
+define_parse_endian_integer(be, int, 32)
+define_parse_endian_integer(be, int, 64)
+define_parse_endian_integer(be, int, 8)
 
 define_parse_endian_integer(be, uint, 16)
-
+define_parse_endian_integer(be, uint, 32)
+define_parse_endian_integer(be, uint, 64)
 define_parse_endian_integer(be, uint, 8)
 
-define_parse_endian_integer(be, int, 64)
-
-define_parse_endian_integer(be, int, 32)
-
-define_parse_endian_integer(be, int, 16)
-
-define_parse_endian_integer(be, int, 8)
+define_parse_endian_bool(le, 16);
+define_parse_endian_bool(le, 32);
+define_parse_endian_bool(le, 8);
 
 define_parse_endian_real(le, double, 64)
-
 define_parse_endian_real(le, float, 32)
 
-define_parse_endian_integer(le, uint, 64)
-
-define_parse_endian_integer(le, uint, 32)
+define_parse_endian_integer(le, int, 16)
+define_parse_endian_integer(le, int, 32)
+define_parse_endian_integer(le, int, 64)
+define_parse_endian_integer(le, int, 8)
 
 define_parse_endian_integer(le, uint, 16)
-
+define_parse_endian_integer(le, uint, 32)
+define_parse_endian_integer(le, uint, 64)
 define_parse_endian_integer(le, uint, 8)
 
-define_parse_endian_integer(le, int, 64)
-
-define_parse_endian_integer(le, int, 32)
-
-define_parse_endian_integer(le, int, 16)
-
-define_parse_endian_integer(le, int, 8)
+// Define function to parse fill bytes until end position is reached
+
+void
+parse_fill_bytes(size_t end_position, PState *pstate)
+{
+    while (!pstate->error_msg && pstate->position < end_position)
+    {
+        char   buffer;
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+
+        pstate->position += count;
+        if (count < sizeof(buffer))
+        {
+            pstate->error_msg = eof_or_error_msg(pstate->stream);
+        }
+    }
+}
+
+// Define function to validate number is same as fixed value after parse
+
+void
+parse_validate_fixed(bool same, const char *element, PState *pstate)
+{
+    UNUSED(element); // because managing strings hard in embedded C
+    if (!pstate->error_msg && !same)
+    {
+        // Error message would be easier to assemble and
+        // internationalize if we used an error struct with multiple
+        // fields instead of a const char string.
+        pstate->error_msg = "Parse: Value of element does not match value of "
+                            "its 'fixed' attribute";
+    }
+}
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h
index 1a4f831..42b8d9a 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h
@@ -19,34 +19,58 @@
 #define PARSERS_H
 
 #include "infoset.h"  // for PState
+#include <stdbool.h>  // for bool
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-// Functions to parse binary floating point numbers and integers
+// Functions to parse binary booleans, real numbers, and integers
+
+extern void parse_be_bool16(bool *number, int64_t true_rep, uint32_t false_rep,
+                            PState *pstate);
+extern void parse_be_bool32(bool *number, int64_t true_rep, uint32_t false_rep,
+                            PState *pstate);
+extern void parse_be_bool8(bool *number, int64_t true_rep, uint32_t false_rep,
+                           PState *pstate);
 
 extern void parse_be_double(double *number, PState *pstate);
 extern void parse_be_float(float *number, PState *pstate);
 
-extern void parse_be_uint64(uint64_t *number, PState *pstate);
-extern void parse_be_uint32(uint32_t *number, PState *pstate);
+extern void parse_be_int16(int16_t *number, PState *pstate);
+extern void parse_be_int32(int32_t *number, PState *pstate);
+extern void parse_be_int64(int64_t *number, PState *pstate);
+extern void parse_be_int8(int8_t *number, PState *pstate);
+
 extern void parse_be_uint16(uint16_t *number, PState *pstate);
+extern void parse_be_uint32(uint32_t *number, PState *pstate);
+extern void parse_be_uint64(uint64_t *number, PState *pstate);
 extern void parse_be_uint8(uint8_t *number, PState *pstate);
 
-extern void parse_be_int64(int64_t *number, PState *pstate);
-extern void parse_be_int32(int32_t *number, PState *pstate);
-extern void parse_be_int16(int16_t *number, PState *pstate);
-extern void parse_be_int8(int8_t *number, PState *pstate);
+extern void parse_le_bool16(bool *number, int64_t true_rep, uint32_t false_rep,
+                            PState *pstate);
+extern void parse_le_bool32(bool *number, int64_t true_rep, uint32_t false_rep,
+                            PState *pstate);
+extern void parse_le_bool8(bool *number, int64_t true_rep, uint32_t false_rep,
+                           PState *pstate);
 
 extern void parse_le_double(double *number, PState *pstate);
 extern void parse_le_float(float *number, PState *pstate);
 
-extern void parse_le_uint64(uint64_t *number, PState *pstate);
-extern void parse_le_uint32(uint32_t *number, PState *pstate);
+extern void parse_le_int16(int16_t *number, PState *pstate);
+extern void parse_le_int32(int32_t *number, PState *pstate);
+extern void parse_le_int64(int64_t *number, PState *pstate);
+extern void parse_le_int8(int8_t *number, PState *pstate);
+
 extern void parse_le_uint16(uint16_t *number, PState *pstate);
+extern void parse_le_uint32(uint32_t *number, PState *pstate);
+extern void parse_le_uint64(uint64_t *number, PState *pstate);
 extern void parse_le_uint8(uint8_t *number, PState *pstate);
 
-extern void parse_le_int64(int64_t *number, PState *pstate);
-extern void parse_le_int32(int32_t *number, PState *pstate);
-extern void parse_le_int16(int16_t *number, PState *pstate);
-extern void parse_le_int8(int8_t *number, PState *pstate);
+// Function to parse fill bytes until end position is reached
+
+extern void parse_fill_bytes(size_t end_position, PState *pstate);
+
+// Function to validate number is same as fixed value after parse
+
+extern void parse_validate_fixed(bool same, const char *element,
+                                 PState *pstate);
 
 #endif // PARSERS_H
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
index b48bb5d..90bdd17 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
@@ -16,8 +16,9 @@
  */
 
 #include "unparsers.h"
-#include <endian.h>  // for htobe32, htobe64, htole32, htole64, htobe16, htole16
-#include <stdio.h>   // for fwrite, size_t
+#include <endian.h>   // for htobe32, htobe64, htole32, htole64, htobe16, htole16
+#include <stdbool.h>  // for bool
+#include <stdio.h>    // for fwrite, size_t
 
 // Macros that are not defined by <endian.h>
 
@@ -25,8 +26,36 @@
 
 #define htole8(var) var
 
+// Helper macro to reduce duplication of C code writing stream,
+// updating position, and checking for errors
+
+#define write_stream_update_position                                           \
+    size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);    \
+    ustate->position += count;                                                 \
+    if (count < sizeof(buffer))                                                \
+    {                                                                          \
+        ustate->error_msg = eof_or_error_msg(ustate->stream);                  \
+    }
+
 // Macros to define unparse_<endian>_<type> functions
 
+#define define_unparse_endian_bool(endian, bits)                               \
+    void unparse_##endian##_bool##bits(bool number, uint32_t true_rep,         \
+                                       uint32_t false_rep, UState *ustate)     \
+    {                                                                          \
+        if (!ustate->error_msg)                                                \
+        {                                                                      \
+            union                                                              \
+            {                                                                  \
+                char           c_val[sizeof(uint##bits##_t)];                  \
+                uint##bits##_t i_val;                                          \
+            } buffer;                                                          \
+                                                                               \
+            buffer.i_val = hto##endian##bits(number ? true_rep : false_rep);   \
+            write_stream_update_position;                                      \
+        }                                                                      \
+    }
+
 #define define_unparse_endian_real(endian, type, bits)                         \
     void unparse_##endian##_##type(type number, UState *ustate)                \
     {                                                                          \
@@ -38,14 +67,10 @@
                 type           f_val;                                          \
                 uint##bits##_t i_val;                                          \
             } buffer;                                                          \
+                                                                               \
             buffer.f_val = number;                                             \
             buffer.i_val = hto##endian##bits(buffer.i_val);                    \
-            size_t count =                                                     \
-                fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);       \
-            if (count < sizeof(buffer))                                        \
-            {                                                                  \
-                ustate->error_msg = eof_or_error_msg(ustate->stream);          \
-            }                                                                  \
+            write_stream_update_position;                                      \
         }                                                                      \
     }
 
@@ -60,54 +85,77 @@
                 char           c_val[sizeof(type##bits##_t)];                  \
                 type##bits##_t i_val;                                          \
             } buffer;                                                          \
+                                                                               \
             buffer.i_val = hto##endian##bits(number);                          \
-            size_t count =                                                     \
-                fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);       \
-            if (count < sizeof(buffer))                                        \
-            {                                                                  \
-                ustate->error_msg = eof_or_error_msg(ustate->stream);          \
-            }                                                                  \
+            write_stream_update_position;                                      \
         }                                                                      \
     }
 
-// Define functions to unparse binary real and integer numbers
+// Define functions to unparse binary real numbers and integers
 
-define_unparse_endian_real(be, double, 64)
+define_unparse_endian_bool(be, 16);
+define_unparse_endian_bool(be, 32);
+define_unparse_endian_bool(be, 8);
 
+define_unparse_endian_real(be, double, 64)
 define_unparse_endian_real(be, float, 32)
 
-define_unparse_endian_integer(be, uint, 64)
-
-define_unparse_endian_integer(be, uint, 32)
+define_unparse_endian_integer(be, int, 16)
+define_unparse_endian_integer(be, int, 32)
+define_unparse_endian_integer(be, int, 64)
+define_unparse_endian_integer(be, int, 8)
 
 define_unparse_endian_integer(be, uint, 16)
-
+define_unparse_endian_integer(be, uint, 32)
+define_unparse_endian_integer(be, uint, 64)
 define_unparse_endian_integer(be, uint, 8)
 
-define_unparse_endian_integer(be, int, 64)
-
-define_unparse_endian_integer(be, int, 32)
-
-define_unparse_endian_integer(be, int, 16)
-
-define_unparse_endian_integer(be, int, 8)
+define_unparse_endian_bool(le, 16);
+define_unparse_endian_bool(le, 32);
+define_unparse_endian_bool(le, 8);
 
 define_unparse_endian_real(le, double, 64)
-
 define_unparse_endian_real(le, float, 32)
 
-define_unparse_endian_integer(le, uint, 64)
-
-define_unparse_endian_integer(le, uint, 32)
+define_unparse_endian_integer(le, int, 16)
+define_unparse_endian_integer(le, int, 32)
+define_unparse_endian_integer(le, int, 64)
+define_unparse_endian_integer(le, int, 8)
 
 define_unparse_endian_integer(le, uint, 16)
-
+define_unparse_endian_integer(le, uint, 32)
+define_unparse_endian_integer(le, uint, 64)
 define_unparse_endian_integer(le, uint, 8)
 
-define_unparse_endian_integer(le, int, 64)
+// Define function to unparse fill bytes until end position is reached
 
-define_unparse_endian_integer(le, int, 32)
-
-define_unparse_endian_integer(le, int, 16)
+void
+unparse_fill_bytes(size_t end_position, const char fill_byte, UState *ustate)
+{
+    while (!ustate->error_msg && ustate->position < end_position)
+    {
+        size_t count = fwrite(&fill_byte, 1, sizeof(fill_byte), ustate->stream);
 
-define_unparse_endian_integer(le, int, 8)
+        ustate->position += count;
+        if (count < sizeof(fill_byte))
+        {
+            ustate->error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+}
+
+// Define function to validate number is same as fixed value during unparse
+
+void
+unparse_validate_fixed(bool same, const char *element, UState *ustate)
+{
+    if (!ustate->error_msg && !same)
+    {
+        // Error message would be easier to assemble and
+        // internationalize if we used an error struct with multiple
+        // fields instead of a const char string.
+        ustate->error_msg = "Unparse: Value of element does not match value of "
+                            "its 'fixed' attribute";
+        UNUSED(element); // unused because managing strings hard in embedded C
+    }
+}
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h
index 1d2eabd..b676f7a 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h
@@ -19,34 +19,59 @@
 #define UNPARSERS_H
 
 #include "infoset.h"  // for UState
+#include <stdbool.h>  // for bool
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
-// Functions to unparse binary floating point numbers and integers
+// Functions to unparse binary booleans, real numbers, and integers
+
+extern void unparse_be_bool16(bool number, uint32_t true_rep,
+                              uint32_t false_rep, UState *ustate);
+extern void unparse_be_bool32(bool number, uint32_t true_rep,
+                              uint32_t false_rep, UState *ustate);
+extern void unparse_be_bool8(bool number, uint32_t true_rep, uint32_t false_rep,
+                             UState *ustate);
 
 extern void unparse_be_double(double number, UState *ustate);
 extern void unparse_be_float(float number, UState *ustate);
 
-extern void unparse_be_uint64(uint64_t number, UState *ustate);
-extern void unparse_be_uint32(uint32_t number, UState *ustate);
+extern void unparse_be_int16(int16_t number, UState *ustate);
+extern void unparse_be_int32(int32_t number, UState *ustate);
+extern void unparse_be_int64(int64_t number, UState *ustate);
+extern void unparse_be_int8(int8_t number, UState *ustate);
+
 extern void unparse_be_uint16(uint16_t number, UState *ustate);
+extern void unparse_be_uint32(uint32_t number, UState *ustate);
+extern void unparse_be_uint64(uint64_t number, UState *ustate);
 extern void unparse_be_uint8(uint8_t number, UState *ustate);
 
-extern void unparse_be_int64(int64_t number, UState *ustate);
-extern void unparse_be_int32(int32_t number, UState *ustate);
-extern void unparse_be_int16(int16_t number, UState *ustate);
-extern void unparse_be_int8(int8_t number, UState *ustate);
+extern void unparse_le_bool16(bool number, uint32_t true_rep,
+                              uint32_t false_rep, UState *ustate);
+extern void unparse_le_bool32(bool number, uint32_t true_rep,
+                              uint32_t false_rep, UState *ustate);
+extern void unparse_le_bool8(bool number, uint32_t true_rep, uint32_t false_rep,
+                             UState *ustate);
 
 extern void unparse_le_double(double number, UState *ustate);
 extern void unparse_le_float(float number, UState *ustate);
 
-extern void unparse_le_uint64(uint64_t number, UState *ustate);
-extern void unparse_le_uint32(uint32_t number, UState *ustate);
+extern void unparse_le_int16(int16_t number, UState *ustate);
+extern void unparse_le_int32(int32_t number, UState *ustate);
+extern void unparse_le_int64(int64_t number, UState *ustate);
+extern void unparse_le_int8(int8_t number, UState *ustate);
+
 extern void unparse_le_uint16(uint16_t number, UState *ustate);
+extern void unparse_le_uint32(uint32_t number, UState *ustate);
+extern void unparse_le_uint64(uint64_t number, UState *ustate);
 extern void unparse_le_uint8(uint8_t number, UState *ustate);
 
-extern void unparse_le_int64(int64_t number, UState *ustate);
-extern void unparse_le_int32(int32_t number, UState *ustate);
-extern void unparse_le_int16(int16_t number, UState *ustate);
-extern void unparse_le_int8(int8_t number, UState *ustate);
+// Function to unparse fill bytes until end position is reached
+
+extern void unparse_fill_bytes(size_t end_position, const char fill_byte,
+                               UState *ustate);
+
+// Function to validate number is same as fixed value during unparse
+
+extern void unparse_validate_fixed(bool same, const char *element,
+                                   UState *ustate);
 
 #endif // UNPARSERS_H
diff --git a/daffodil-runtime2/src/main/resources/examples/NestedUnion.h b/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
index 4396cd7..620e1b5 100644
--- a/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
+++ b/daffodil-runtime2/src/main/resources/examples/NestedUnion.h
@@ -19,6 +19,7 @@
 #define GENERATED_CODE_H
 
 #include "infoset.h"  // for InfosetBase
+#include <stdbool.h>  // for bool
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
 // Define infoset structures
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.c b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
index fb6f98f..88b7247 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.c
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
@@ -33,19 +33,22 @@ static void bigEndian_unparseSelf(const bigEndian *instance, UState *ustate);
 static void littleEndian_initSelf(littleEndian *instance);
 static void littleEndian_parseSelf(littleEndian *instance, PState *pstate);
 static void littleEndian_unparseSelf(const littleEndian *instance, UState *ustate);
+static void fixed_initSelf(fixed *instance);
+static void fixed_parseSelf(fixed *instance, PState *pstate);
+static void fixed_unparseSelf(const fixed *instance, UState *ustate);
 static void ex_nums_initSelf(ex_nums *instance);
 static void ex_nums_parseSelf(ex_nums *instance, PState *pstate);
 static void ex_nums_unparseSelf(const ex_nums *instance, UState *ustate);
 
 // Metadata singletons
 
-static const ERD be_int16_array_ex_nums_ERD = {
+static const ERD be_bool16_array_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_int16", // namedQName.local
+        "be_bool16", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_INT16, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
@@ -59,24 +62,38 @@ static const ERD be_float_array_ex_nums_ERD = {
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
+static const ERD be_int16_array_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
 static const array array_compute_offsets;
 
-static const size_t array_offsets[6] = {
-    (const char *)&array_compute_offsets.be_int16[0] - (const char *)&array_compute_offsets,
-    (const char *)&array_compute_offsets.be_int16[1] - (const char *)&array_compute_offsets,
-    (const char *)&array_compute_offsets.be_int16[2] - (const char *)&array_compute_offsets,
+static const size_t array_offsets[8] = {
+    (const char *)&array_compute_offsets.be_bool16[0] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_bool16[1] - (const char *)&array_compute_offsets,
     (const char *)&array_compute_offsets.be_float[0] - (const char *)&array_compute_offsets,
     (const char *)&array_compute_offsets.be_float[1] - (const char *)&array_compute_offsets,
-    (const char *)&array_compute_offsets.be_float[2] - (const char *)&array_compute_offsets
+    (const char *)&array_compute_offsets.be_float[2] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_int16[0] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_int16[1] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_int16[2] - (const char *)&array_compute_offsets
 };
 
-static const ERD *array_childrenERDs[6] = {
-    &be_int16_array_ex_nums_ERD,
-    &be_int16_array_ex_nums_ERD,
-    &be_int16_array_ex_nums_ERD,
+static const ERD *array_childrenERDs[8] = {
+    &be_bool16_array_ex_nums_ERD,
+    &be_bool16_array_ex_nums_ERD,
     &be_float_array_ex_nums_ERD,
     &be_float_array_ex_nums_ERD,
-    &be_float_array_ex_nums_ERD
+    &be_float_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD,
+    &be_int16_array_ex_nums_ERD
 };
 
 static const ERD array_ex_nums_ERD = {
@@ -86,7 +103,7 @@ static const ERD array_ex_nums_ERD = {
         NULL, // namedQName.ns
     },
     COMPLEX, // typeCode
-    6, // numChildren
+    8, // numChildren
     array_offsets, // offsets
     array_childrenERDs, // childrenERDs
     (ERDInitSelf)&array_initSelf, // initSelf
@@ -95,73 +112,73 @@ static const ERD array_ex_nums_ERD = {
     NULL // initChoice
 };
 
-static const ERD be_double_bigEndian_ex_nums_ERD = {
+static const ERD be_bool16_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_double", // namedQName.local
+        "be_bool16", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_DOUBLE, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_float_bigEndian_ex_nums_ERD = {
+static const ERD be_bool32_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_float", // namedQName.local
+        "be_bool32", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_FLOAT, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint64_bigEndian_ex_nums_ERD = {
+static const ERD be_bool8_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_uint64", // namedQName.local
+        "be_bool8", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT64, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint32_bigEndian_ex_nums_ERD = {
+static const ERD be_boolean_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_uint32", // namedQName.local
+        "be_boolean", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT32, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint16_bigEndian_ex_nums_ERD = {
+static const ERD be_double_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_uint16", // namedQName.local
+        "be_double", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT16, // typeCode
+    PRIMITIVE_DOUBLE, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_uint8_bigEndian_ex_nums_ERD = {
+static const ERD be_float_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_uint8", // namedQName.local
+        "be_float", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT8, // typeCode
+    PRIMITIVE_FLOAT, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int64_bigEndian_ex_nums_ERD = {
+static const ERD be_int16_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_int64", // namedQName.local
+        "be_int16", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_INT64, // typeCode
+    PRIMITIVE_INT16, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
@@ -175,13 +192,13 @@ static const ERD be_int32_bigEndian_ex_nums_ERD = {
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD be_int16_bigEndian_ex_nums_ERD = {
+static const ERD be_int64_bigEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "be_int16", // namedQName.local
+        "be_int64", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_INT16, // typeCode
+    PRIMITIVE_INT64, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
@@ -195,32 +212,104 @@ static const ERD be_int8_bigEndian_ex_nums_ERD = {
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
+static const ERD be_integer16_bigEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_integer16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD be_uint16_bigEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT16, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD be_uint32_bigEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD be_uint64_bigEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT64, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD be_uint8_bigEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD be_nonNegativeInteger32_bigEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_nonNegativeInteger32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
 static const bigEndian bigEndian_compute_offsets;
 
-static const size_t bigEndian_offsets[10] = {
+static const size_t bigEndian_offsets[16] = {
+    (const char *)&bigEndian_compute_offsets.be_bool16 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_bool32 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_bool8 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_boolean - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_double - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_float - (const char *)&bigEndian_compute_offsets,
-    (const char *)&bigEndian_compute_offsets.be_uint64 - (const char *)&bigEndian_compute_offsets,
-    (const char *)&bigEndian_compute_offsets.be_uint32 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int16 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int32 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int64 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int8 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_integer16 - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_uint16 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_uint32 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_uint64 - (const char *)&bigEndian_compute_offsets,
     (const char *)&bigEndian_compute_offsets.be_uint8 - (const char *)&bigEndian_compute_offsets,
-    (const char *)&bigEndian_compute_offsets.be_int64 - (const char *)&bigEndian_compute_offsets,
-    (const char *)&bigEndian_compute_offsets.be_int32 - (const char *)&bigEndian_compute_offsets,
-    (const char *)&bigEndian_compute_offsets.be_int16 - (const char *)&bigEndian_compute_offsets,
-    (const char *)&bigEndian_compute_offsets.be_int8 - (const char *)&bigEndian_compute_offsets
+    (const char *)&bigEndian_compute_offsets.be_nonNegativeInteger32 - (const char *)&bigEndian_compute_offsets
 };
 
-static const ERD *bigEndian_childrenERDs[10] = {
+static const ERD *bigEndian_childrenERDs[16] = {
+    &be_bool16_bigEndian_ex_nums_ERD,
+    &be_bool32_bigEndian_ex_nums_ERD,
+    &be_bool8_bigEndian_ex_nums_ERD,
+    &be_boolean_bigEndian_ex_nums_ERD,
     &be_double_bigEndian_ex_nums_ERD,
     &be_float_bigEndian_ex_nums_ERD,
-    &be_uint64_bigEndian_ex_nums_ERD,
-    &be_uint32_bigEndian_ex_nums_ERD,
+    &be_int16_bigEndian_ex_nums_ERD,
+    &be_int32_bigEndian_ex_nums_ERD,
+    &be_int64_bigEndian_ex_nums_ERD,
+    &be_int8_bigEndian_ex_nums_ERD,
+    &be_integer16_bigEndian_ex_nums_ERD,
     &be_uint16_bigEndian_ex_nums_ERD,
+    &be_uint32_bigEndian_ex_nums_ERD,
+    &be_uint64_bigEndian_ex_nums_ERD,
     &be_uint8_bigEndian_ex_nums_ERD,
-    &be_int64_bigEndian_ex_nums_ERD,
-    &be_int32_bigEndian_ex_nums_ERD,
-    &be_int16_bigEndian_ex_nums_ERD,
-    &be_int8_bigEndian_ex_nums_ERD
+    &be_nonNegativeInteger32_bigEndian_ex_nums_ERD
 };
 
 static const ERD bigEndian_ex_nums_ERD = {
@@ -230,7 +319,7 @@ static const ERD bigEndian_ex_nums_ERD = {
         NULL, // namedQName.ns
     },
     COMPLEX, // typeCode
-    10, // numChildren
+    16, // numChildren
     bigEndian_offsets, // offsets
     bigEndian_childrenERDs, // childrenERDs
     (ERDInitSelf)&bigEndian_initSelf, // initSelf
@@ -239,63 +328,63 @@ static const ERD bigEndian_ex_nums_ERD = {
     NULL // initChoice
 };
 
-static const ERD le_uint64_littleEndian_ex_nums_ERD = {
+static const ERD le_bool16_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_uint64", // namedQName.local
+        "le_bool16", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT64, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint32_littleEndian_ex_nums_ERD = {
+static const ERD le_bool32_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_uint32", // namedQName.local
+        "le_bool32", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT32, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint16_littleEndian_ex_nums_ERD = {
+static const ERD le_bool8_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_uint16", // namedQName.local
+        "le_bool8", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT16, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_uint8_littleEndian_ex_nums_ERD = {
+static const ERD le_boolean_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_uint8", // namedQName.local
+        "le_boolean", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_UINT8, // typeCode
+    PRIMITIVE_BOOLEAN, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int64_littleEndian_ex_nums_ERD = {
+static const ERD le_double_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_int64", // namedQName.local
+        "le_double", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_INT64, // typeCode
+    PRIMITIVE_DOUBLE, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_int32_littleEndian_ex_nums_ERD = {
+static const ERD le_float_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_int32", // namedQName.local
+        "le_float", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_INT32, // typeCode
+    PRIMITIVE_FLOAT, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
@@ -309,6 +398,26 @@ static const ERD le_int16_littleEndian_ex_nums_ERD = {
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
+static const ERD le_int32_littleEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD le_int64_littleEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT64, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
 static const ERD le_int8_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
@@ -319,52 +428,104 @@ static const ERD le_int8_littleEndian_ex_nums_ERD = {
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_float_littleEndian_ex_nums_ERD = {
+static const ERD le_integer64_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_float", // namedQName.local
+        "le_integer64", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_FLOAT, // typeCode
+    PRIMITIVE_INT64, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-static const ERD le_double_littleEndian_ex_nums_ERD = {
+static const ERD le_uint16_littleEndian_ex_nums_ERD = {
     {
         NULL, // namedQName.prefix
-        "le_double", // namedQName.local
+        "le_uint16", // namedQName.local
         NULL, // namedQName.ns
     },
-    PRIMITIVE_DOUBLE, // typeCode
+    PRIMITIVE_UINT16, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD le_uint32_littleEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD le_uint64_littleEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT64, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD le_uint8_littleEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD le_nonNegativeInteger8_littleEndian_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_nonNegativeInteger8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
     0, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 static const littleEndian littleEndian_compute_offsets;
 
-static const size_t littleEndian_offsets[10] = {
-    (const char *)&littleEndian_compute_offsets.le_uint64 - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_uint32 - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_uint16 - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_uint8 - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_int64 - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_int32 - (const char *)&littleEndian_compute_offsets,
+static const size_t littleEndian_offsets[16] = {
+    (const char *)&littleEndian_compute_offsets.le_bool16 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_bool32 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_bool8 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_boolean - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_double - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_float - (const char *)&littleEndian_compute_offsets,
     (const char *)&littleEndian_compute_offsets.le_int16 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_int32 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_int64 - (const char *)&littleEndian_compute_offsets,
     (const char *)&littleEndian_compute_offsets.le_int8 - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_float - (const char *)&littleEndian_compute_offsets,
-    (const char *)&littleEndian_compute_offsets.le_double - (const char *)&littleEndian_compute_offsets
+    (const char *)&littleEndian_compute_offsets.le_integer64 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint16 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint32 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint64 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint8 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_nonNegativeInteger8 - (const char *)&littleEndian_compute_offsets
 };
 
-static const ERD *littleEndian_childrenERDs[10] = {
-    &le_uint64_littleEndian_ex_nums_ERD,
-    &le_uint32_littleEndian_ex_nums_ERD,
-    &le_uint16_littleEndian_ex_nums_ERD,
-    &le_uint8_littleEndian_ex_nums_ERD,
-    &le_int64_littleEndian_ex_nums_ERD,
-    &le_int32_littleEndian_ex_nums_ERD,
+static const ERD *littleEndian_childrenERDs[16] = {
+    &le_bool16_littleEndian_ex_nums_ERD,
+    &le_bool32_littleEndian_ex_nums_ERD,
+    &le_bool8_littleEndian_ex_nums_ERD,
+    &le_boolean_littleEndian_ex_nums_ERD,
+    &le_double_littleEndian_ex_nums_ERD,
+    &le_float_littleEndian_ex_nums_ERD,
     &le_int16_littleEndian_ex_nums_ERD,
+    &le_int32_littleEndian_ex_nums_ERD,
+    &le_int64_littleEndian_ex_nums_ERD,
     &le_int8_littleEndian_ex_nums_ERD,
-    &le_float_littleEndian_ex_nums_ERD,
-    &le_double_littleEndian_ex_nums_ERD
+    &le_integer64_littleEndian_ex_nums_ERD,
+    &le_uint16_littleEndian_ex_nums_ERD,
+    &le_uint32_littleEndian_ex_nums_ERD,
+    &le_uint64_littleEndian_ex_nums_ERD,
+    &le_uint8_littleEndian_ex_nums_ERD,
+    &le_nonNegativeInteger8_littleEndian_ex_nums_ERD
 };
 
 static const ERD littleEndian_ex_nums_ERD = {
@@ -374,7 +535,7 @@ static const ERD littleEndian_ex_nums_ERD = {
         NULL, // namedQName.ns
     },
     COMPLEX, // typeCode
-    10, // numChildren
+    16, // numChildren
     littleEndian_offsets, // offsets
     littleEndian_childrenERDs, // childrenERDs
     (ERDInitSelf)&littleEndian_initSelf, // initSelf
@@ -383,18 +544,92 @@ static const ERD littleEndian_ex_nums_ERD = {
     NULL // initChoice
 };
 
+static const ERD boolean_false_fixed_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "boolean_false", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_BOOLEAN, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD boolean_true_fixed_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "boolean_true", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_BOOLEAN, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD float_1_5_fixed_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "float_1_5", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_FLOAT, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const ERD int_32_fixed_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "int_32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+static const fixed fixed_compute_offsets;
+
+static const size_t fixed_offsets[4] = {
+    (const char *)&fixed_compute_offsets.boolean_false - (const char *)&fixed_compute_offsets,
+    (const char *)&fixed_compute_offsets.boolean_true - (const char *)&fixed_compute_offsets,
+    (const char *)&fixed_compute_offsets.float_1_5 - (const char *)&fixed_compute_offsets,
+    (const char *)&fixed_compute_offsets.int_32 - (const char *)&fixed_compute_offsets
+};
+
+static const ERD *fixed_childrenERDs[4] = {
+    &boolean_false_fixed_ex_nums_ERD,
+    &boolean_true_fixed_ex_nums_ERD,
+    &float_1_5_fixed_ex_nums_ERD,
+    &int_32_fixed_ex_nums_ERD
+};
+
+static const ERD fixed_ex_nums_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "fixed", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX, // typeCode
+    4, // numChildren
+    fixed_offsets, // offsets
+    fixed_childrenERDs, // childrenERDs
+    (ERDInitSelf)&fixed_initSelf, // initSelf
+    (ERDParseSelf)&fixed_parseSelf, // parseSelf
+    (ERDUnparseSelf)&fixed_unparseSelf, // unparseSelf
+    NULL // initChoice
+};
+
 static const ex_nums ex_nums_compute_offsets;
 
-static const size_t ex_nums_offsets[3] = {
+static const size_t ex_nums_offsets[4] = {
     (const char *)&ex_nums_compute_offsets.array - (const char *)&ex_nums_compute_offsets,
     (const char *)&ex_nums_compute_offsets.bigEndian - (const char *)&ex_nums_compute_offsets,
-    (const char *)&ex_nums_compute_offsets.littleEndian - (const char *)&ex_nums_compute_offsets
+    (const char *)&ex_nums_compute_offsets.littleEndian - (const char *)&ex_nums_compute_offsets,
+    (const char *)&ex_nums_compute_offsets.fixed - (const char *)&ex_nums_compute_offsets
 };
 
-static const ERD *ex_nums_childrenERDs[3] = {
+static const ERD *ex_nums_childrenERDs[4] = {
     &array_ex_nums_ERD,
     &bigEndian_ex_nums_ERD,
-    &littleEndian_ex_nums_ERD
+    &littleEndian_ex_nums_ERD,
+    &fixed_ex_nums_ERD
 };
 
 static const ERD ex_nums_ERD = {
@@ -404,7 +639,7 @@ static const ERD ex_nums_ERD = {
         "http://example.com", // namedQName.ns
     },
     COMPLEX, // typeCode
-    3, // numChildren
+    4, // numChildren
     ex_nums_offsets, // offsets
     ex_nums_childrenERDs, // childrenERDs
     (ERDInitSelf)&ex_nums_initSelf, // initSelf
@@ -434,126 +669,204 @@ static void
 array_initSelf(array *instance)
 {
     instance->_base.erd = &array_ex_nums_ERD;
-    instance->be_int16[0] = 0xCCCC;
-    instance->be_int16[1] = 0xCCCC;
-    instance->be_int16[2] = 0xCCCC;
+    instance->be_bool16[0] = true;
+    instance->be_bool16[1] = true;
     instance->be_float[0] = NAN;
     instance->be_float[1] = NAN;
     instance->be_float[2] = NAN;
+    instance->be_int16[0] = 0xCCCC;
+    instance->be_int16[1] = 0xCCCC;
+    instance->be_int16[2] = 0xCCCC;
 }
 
 static void
 array_parseSelf(array *instance, PState *pstate)
 {
-    parse_be_int16(&instance->be_int16[0], pstate);
-    parse_be_int16(&instance->be_int16[1], pstate);
-    parse_be_int16(&instance->be_int16[2], pstate);
+    parse_be_bool16(&instance->be_bool16[0], -1, 0, pstate);
+    parse_be_bool16(&instance->be_bool16[1], -1, 0, pstate);
     parse_be_float(&instance->be_float[0], pstate);
     parse_be_float(&instance->be_float[1], pstate);
     parse_be_float(&instance->be_float[2], pstate);
+    parse_be_int16(&instance->be_int16[0], pstate);
+    parse_be_int16(&instance->be_int16[1], pstate);
+    parse_be_int16(&instance->be_int16[2], pstate);
 }
 
 static void
 array_unparseSelf(const array *instance, UState *ustate)
 {
-    unparse_be_int16(instance->be_int16[0], ustate);
-    unparse_be_int16(instance->be_int16[1], ustate);
-    unparse_be_int16(instance->be_int16[2], ustate);
+    unparse_be_bool16(instance->be_bool16[0], ~0, 0, ustate);
+    unparse_be_bool16(instance->be_bool16[1], ~0, 0, ustate);
     unparse_be_float(instance->be_float[0], ustate);
     unparse_be_float(instance->be_float[1], ustate);
     unparse_be_float(instance->be_float[2], ustate);
+    unparse_be_int16(instance->be_int16[0], ustate);
+    unparse_be_int16(instance->be_int16[1], ustate);
+    unparse_be_int16(instance->be_int16[2], ustate);
 }
 
 static void
 bigEndian_initSelf(bigEndian *instance)
 {
     instance->_base.erd = &bigEndian_ex_nums_ERD;
+    instance->be_bool16 = true;
+    instance->be_bool32 = true;
+    instance->be_bool8 = true;
+    instance->be_boolean = true;
     instance->be_double = NAN;
     instance->be_float = NAN;
-    instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
-    instance->be_uint32 = 0xCCCCCCCC;
-    instance->be_uint16 = 0xCCCC;
-    instance->be_uint8 = 0xCC;
-    instance->be_int64 = 0xCCCCCCCCCCCCCCCC;
-    instance->be_int32 = 0xCCCCCCCC;
     instance->be_int16 = 0xCCCC;
+    instance->be_int32 = 0xCCCCCCCC;
+    instance->be_int64 = 0xCCCCCCCCCCCCCCCC;
     instance->be_int8 = 0xCC;
+    instance->be_integer16 = 0xCCCC;
+    instance->be_uint16 = 0xCCCC;
+    instance->be_uint32 = 0xCCCCCCCC;
+    instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
+    instance->be_uint8 = 0xCC;
+    instance->be_nonNegativeInteger32 = 0xCCCCCCCC;
 }
 
 static void
 bigEndian_parseSelf(bigEndian *instance, PState *pstate)
 {
+    parse_be_bool16(&instance->be_bool16, 1, 0, pstate);
+    parse_be_bool32(&instance->be_bool32, -1, 0, pstate);
+    parse_be_bool8(&instance->be_bool8, -1, 0, pstate);
+    parse_be_bool32(&instance->be_boolean, -1, 0, pstate);
     parse_be_double(&instance->be_double, pstate);
     parse_be_float(&instance->be_float, pstate);
-    parse_be_uint64(&instance->be_uint64, pstate);
-    parse_be_uint32(&instance->be_uint32, pstate);
-    parse_be_uint16(&instance->be_uint16, pstate);
-    parse_be_uint8(&instance->be_uint8, pstate);
-    parse_be_int64(&instance->be_int64, pstate);
-    parse_be_int32(&instance->be_int32, pstate);
     parse_be_int16(&instance->be_int16, pstate);
+    parse_be_int32(&instance->be_int32, pstate);
+    parse_be_int64(&instance->be_int64, pstate);
     parse_be_int8(&instance->be_int8, pstate);
+    parse_be_int16(&instance->be_integer16, pstate);
+    parse_be_uint16(&instance->be_uint16, pstate);
+    parse_be_uint32(&instance->be_uint32, pstate);
+    parse_be_uint64(&instance->be_uint64, pstate);
+    parse_be_uint8(&instance->be_uint8, pstate);
+    parse_be_uint32(&instance->be_nonNegativeInteger32, pstate);
 }
 
 static void
 bigEndian_unparseSelf(const bigEndian *instance, UState *ustate)
 {
+    unparse_be_bool16(instance->be_bool16, 1, 0, ustate);
+    unparse_be_bool32(instance->be_bool32, ~0, 0, ustate);
+    unparse_be_bool8(instance->be_bool8, ~0, 0, ustate);
+    unparse_be_bool32(instance->be_boolean, ~0, 0, ustate);
     unparse_be_double(instance->be_double, ustate);
     unparse_be_float(instance->be_float, ustate);
-    unparse_be_uint64(instance->be_uint64, ustate);
-    unparse_be_uint32(instance->be_uint32, ustate);
-    unparse_be_uint16(instance->be_uint16, ustate);
-    unparse_be_uint8(instance->be_uint8, ustate);
-    unparse_be_int64(instance->be_int64, ustate);
-    unparse_be_int32(instance->be_int32, ustate);
     unparse_be_int16(instance->be_int16, ustate);
+    unparse_be_int32(instance->be_int32, ustate);
+    unparse_be_int64(instance->be_int64, ustate);
     unparse_be_int8(instance->be_int8, ustate);
+    unparse_be_int16(instance->be_integer16, ustate);
+    unparse_be_uint16(instance->be_uint16, ustate);
+    unparse_be_uint32(instance->be_uint32, ustate);
+    unparse_be_uint64(instance->be_uint64, ustate);
+    unparse_be_uint8(instance->be_uint8, ustate);
+    unparse_be_uint32(instance->be_nonNegativeInteger32, ustate);
 }
 
 static void
 littleEndian_initSelf(littleEndian *instance)
 {
     instance->_base.erd = &littleEndian_ex_nums_ERD;
-    instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
-    instance->le_uint32 = 0xCCCCCCCC;
-    instance->le_uint16 = 0xCCCC;
-    instance->le_uint8 = 0xCC;
-    instance->le_int64 = 0xCCCCCCCCCCCCCCCC;
-    instance->le_int32 = 0xCCCCCCCC;
+    instance->le_bool16 = true;
+    instance->le_bool32 = true;
+    instance->le_bool8 = true;
+    instance->le_boolean = true;
+    instance->le_double = NAN;
+    instance->le_float = NAN;
     instance->le_int16 = 0xCCCC;
+    instance->le_int32 = 0xCCCCCCCC;
+    instance->le_int64 = 0xCCCCCCCCCCCCCCCC;
     instance->le_int8 = 0xCC;
-    instance->le_float = NAN;
-    instance->le_double = NAN;
+    instance->le_integer64 = 0xCCCCCCCCCCCCCCCC;
+    instance->le_uint16 = 0xCCCC;
+    instance->le_uint32 = 0xCCCCCCCC;
+    instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
+    instance->le_uint8 = 0xCC;
+    instance->le_nonNegativeInteger8 = 0xCC;
 }
 
 static void
 littleEndian_parseSelf(littleEndian *instance, PState *pstate)
 {
-    parse_le_uint64(&instance->le_uint64, pstate);
-    parse_le_uint32(&instance->le_uint32, pstate);
-    parse_le_uint16(&instance->le_uint16, pstate);
-    parse_le_uint8(&instance->le_uint8, pstate);
-    parse_le_int64(&instance->le_int64, pstate);
-    parse_le_int32(&instance->le_int32, pstate);
+    parse_le_bool16(&instance->le_bool16, 1, 0, pstate);
+    parse_le_bool32(&instance->le_bool32, -1, 0, pstate);
+    parse_le_bool8(&instance->le_bool8, -1, 0, pstate);
+    parse_le_bool32(&instance->le_boolean, -1, 0, pstate);
+    parse_le_double(&instance->le_double, pstate);
+    parse_le_float(&instance->le_float, pstate);
     parse_le_int16(&instance->le_int16, pstate);
+    parse_le_int32(&instance->le_int32, pstate);
+    parse_le_int64(&instance->le_int64, pstate);
     parse_le_int8(&instance->le_int8, pstate);
-    parse_le_float(&instance->le_float, pstate);
-    parse_le_double(&instance->le_double, pstate);
+    parse_le_int64(&instance->le_integer64, pstate);
+    parse_le_uint16(&instance->le_uint16, pstate);
+    parse_le_uint32(&instance->le_uint32, pstate);
+    parse_le_uint64(&instance->le_uint64, pstate);
+    parse_le_uint8(&instance->le_uint8, pstate);
+    parse_le_uint8(&instance->le_nonNegativeInteger8, pstate);
 }
 
 static void
 littleEndian_unparseSelf(const littleEndian *instance, UState *ustate)
 {
-    unparse_le_uint64(instance->le_uint64, ustate);
-    unparse_le_uint32(instance->le_uint32, ustate);
-    unparse_le_uint16(instance->le_uint16, ustate);
-    unparse_le_uint8(instance->le_uint8, ustate);
-    unparse_le_int64(instance->le_int64, ustate);
-    unparse_le_int32(instance->le_int32, ustate);
+    unparse_le_bool16(instance->le_bool16, 1, 0, ustate);
+    unparse_le_bool32(instance->le_bool32, ~0, 0, ustate);
+    unparse_le_bool8(instance->le_bool8, ~0, 0, ustate);
+    unparse_le_bool32(instance->le_boolean, ~0, 0, ustate);
+    unparse_le_double(instance->le_double, ustate);
+    unparse_le_float(instance->le_float, ustate);
     unparse_le_int16(instance->le_int16, ustate);
+    unparse_le_int32(instance->le_int32, ustate);
+    unparse_le_int64(instance->le_int64, ustate);
     unparse_le_int8(instance->le_int8, ustate);
-    unparse_le_float(instance->le_float, ustate);
-    unparse_le_double(instance->le_double, ustate);
+    unparse_le_int64(instance->le_integer64, ustate);
+    unparse_le_uint16(instance->le_uint16, ustate);
+    unparse_le_uint32(instance->le_uint32, ustate);
+    unparse_le_uint64(instance->le_uint64, ustate);
+    unparse_le_uint8(instance->le_uint8, ustate);
+    unparse_le_uint8(instance->le_nonNegativeInteger8, ustate);
+}
+
+static void
+fixed_initSelf(fixed *instance)
+{
+    instance->_base.erd = &fixed_ex_nums_ERD;
+    instance->boolean_false = true;
+    instance->boolean_true = true;
+    instance->float_1_5 = NAN;
+    instance->int_32 = 0xCCCCCCCC;
+}
+
+static void
+fixed_parseSelf(fixed *instance, PState *pstate)
+{
+    parse_be_bool32(&instance->boolean_false, -1, 0, pstate);
+    parse_validate_fixed(instance->boolean_false == false, "boolean_false", pstate);
+    parse_be_bool32(&instance->boolean_true, -1, 0, pstate);
+    parse_validate_fixed(instance->boolean_true == true, "boolean_true", pstate);
+    parse_be_float(&instance->float_1_5, pstate);
+    parse_validate_fixed(instance->float_1_5 == 1.5, "float_1_5", pstate);
+    parse_be_int32(&instance->int_32, pstate);
+    parse_validate_fixed(instance->int_32 == 32, "int_32", pstate);
+}
+
+static void
+fixed_unparseSelf(const fixed *instance, UState *ustate)
+{
+    unparse_be_bool32(instance->boolean_false, ~0, 0, ustate);
+    unparse_validate_fixed(instance->boolean_false == false, "boolean_false", ustate);
+    unparse_be_bool32(instance->boolean_true, ~0, 0, ustate);
+    unparse_validate_fixed(instance->boolean_true == true, "boolean_true", ustate);
+    unparse_be_float(instance->float_1_5, ustate);
+    unparse_validate_fixed(instance->float_1_5 == 1.5, "float_1_5", ustate);
+    unparse_be_int32(instance->int_32, ustate);
+    unparse_validate_fixed(instance->int_32 == 32, "int_32", ustate);
 }
 
 static void
@@ -563,6 +876,7 @@ ex_nums_initSelf(ex_nums *instance)
     array_initSelf(&instance->array);
     bigEndian_initSelf(&instance->bigEndian);
     littleEndian_initSelf(&instance->littleEndian);
+    fixed_initSelf(&instance->fixed);
 }
 
 static void
@@ -571,6 +885,7 @@ ex_nums_parseSelf(ex_nums *instance, PState *pstate)
     array_parseSelf(&instance->array, pstate);
     bigEndian_parseSelf(&instance->bigEndian, pstate);
     littleEndian_parseSelf(&instance->littleEndian, pstate);
+    fixed_parseSelf(&instance->fixed, pstate);
 }
 
 static void
@@ -579,5 +894,6 @@ ex_nums_unparseSelf(const ex_nums *instance, UState *ustate)
     array_unparseSelf(&instance->array, ustate);
     bigEndian_unparseSelf(&instance->bigEndian, ustate);
     littleEndian_unparseSelf(&instance->littleEndian, ustate);
+    fixed_unparseSelf(&instance->fixed, ustate);
 }
 
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.h b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
index 403da6b..ae33283 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_nums.h
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
@@ -19,6 +19,7 @@
 #define GENERATED_CODE_H
 
 #include "infoset.h"  // for InfosetBase
+#include <stdbool.h>  // for bool
 #include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
 // Define infoset structures
@@ -26,46 +27,69 @@
 typedef struct array
 {
     InfosetBase _base;
-    int16_t     be_int16[3];
+    bool        be_bool16[2];
     float       be_float[3];
+    int16_t     be_int16[3];
 } array;
 
 typedef struct bigEndian
 {
     InfosetBase _base;
+    bool        be_bool16;
+    bool        be_bool32;
+    bool        be_bool8;
+    bool        be_boolean;
     double      be_double;
     float       be_float;
-    uint64_t    be_uint64;
-    uint32_t    be_uint32;
-    uint16_t    be_uint16;
-    uint8_t     be_uint8;
-    int64_t     be_int64;
-    int32_t     be_int32;
     int16_t     be_int16;
+    int32_t     be_int32;
+    int64_t     be_int64;
     int8_t      be_int8;
+    int16_t     be_integer16;
+    uint16_t    be_uint16;
+    uint32_t    be_uint32;
+    uint64_t    be_uint64;
+    uint8_t     be_uint8;
+    uint32_t    be_nonNegativeInteger32;
 } bigEndian;
 
 typedef struct littleEndian
 {
     InfosetBase _base;
-    uint64_t    le_uint64;
-    uint32_t    le_uint32;
-    uint16_t    le_uint16;
-    uint8_t     le_uint8;
-    int64_t     le_int64;
-    int32_t     le_int32;
+    bool        le_bool16;
+    bool        le_bool32;
+    bool        le_bool8;
+    bool        le_boolean;
+    double      le_double;
+    float       le_float;
     int16_t     le_int16;
+    int32_t     le_int32;
+    int64_t     le_int64;
     int8_t      le_int8;
-    float       le_float;
-    double      le_double;
+    int64_t     le_integer64;
+    uint16_t    le_uint16;
+    uint32_t    le_uint32;
+    uint64_t    le_uint64;
+    uint8_t     le_uint8;
+    uint8_t     le_nonNegativeInteger8;
 } littleEndian;
 
+typedef struct fixed
+{
+    InfosetBase _base;
+    bool        boolean_false;
+    bool        boolean_true;
+    float       float_1_5;
+    int32_t     int_32;
+} fixed;
+
 typedef struct ex_nums
 {
     InfosetBase _base;
     array array;
     bigEndian bigEndian;
     littleEndian littleEndian;
+    fixed fixed;
 } ex_nums;
 
 #endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
index 7756780..ad6cc53 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
@@ -79,10 +79,11 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
         if (fileSystem != null) fileSystem.close()
     }
 
-    // Generate C code from the DFDL schema
+    // Generate C code from the DFDL schema, appending any warnings to our diagnostics
     val rootElementName = rootNS.getOrElse(root.refQName).local
     val codeGeneratorState = new CodeGeneratorState()
     Runtime2CodeGenerator.generateCode(root.document, codeGeneratorState)
+    diagnostics = diagnostics ++ root.warnings
     val codeHeaderText = codeGeneratorState.generateCodeHeader
     val codeFileText = codeGeneratorState.generateCodeFile(rootElementName)
 
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
index 633cc28..ce494c5 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
@@ -21,6 +21,7 @@ import org.apache.daffodil.grammar.Gram
 import org.apache.daffodil.grammar.Prod
 import org.apache.daffodil.grammar.RootGrammarMixin
 import org.apache.daffodil.grammar.SeqComp
+import org.apache.daffodil.grammar.primitives.BinaryBoolean
 import org.apache.daffodil.grammar.primitives.BinaryDouble
 import org.apache.daffodil.grammar.primitives.BinaryFloat
 import org.apache.daffodil.grammar.primitives.BinaryIntegerKnownLength
@@ -33,6 +34,7 @@ import org.apache.daffodil.grammar.primitives.ElementParseAndUnspecifiedLength
 import org.apache.daffodil.grammar.primitives.OrderedSequence
 import org.apache.daffodil.grammar.primitives.ScalarOrderedSequenceChild
 import org.apache.daffodil.grammar.primitives.SpecifiedLengthImplicit
+import org.apache.daffodil.runtime2.generators.BinaryBooleanCodeGenerator
 import org.apache.daffodil.runtime2.generators.BinaryFloatCodeGenerator
 import org.apache.daffodil.runtime2.generators.BinaryIntegerKnownLengthCodeGenerator
 import org.apache.daffodil.runtime2.generators.CodeGeneratorState
@@ -44,7 +46,8 @@ import org.apache.daffodil.util.Misc
 import scala.annotation.tailrec
 
 object Runtime2CodeGenerator
-  extends BinaryIntegerKnownLengthCodeGenerator
+  extends BinaryBooleanCodeGenerator
+    with BinaryIntegerKnownLengthCodeGenerator
     with BinaryFloatCodeGenerator
     with ElementParseAndUnspecifiedLengthCodeGenerator
     with OrderedSequenceCodeGenerator
@@ -58,12 +61,13 @@ object Runtime2CodeGenerator
       case g: ElementCombinator => Runtime2CodeGenerator.generateCode(g.subComb, state)
       case g: SpecifiedLengthImplicit => Runtime2CodeGenerator.generateCode(g.eGram, state)
       case g: ScalarOrderedSequenceChild => Runtime2CodeGenerator.generateCode(g.term.termContentBody, state)
-      case g: SeqComp => seqCompGenerateCode(g, state)
-      case g: OrderedSequence => orderedSequenceGenerateCode(g, state)
-      case g: ElementParseAndUnspecifiedLength => elementParseAndUnspecifiedLengthGenerateCode(g, state)
-      case g: BinaryIntegerKnownLength => binaryIntegerKnownLengthGenerateCode(g, state)
-      case g: BinaryFloat => binaryFloatGenerateCode(g.e, 32, state)
+      case g: BinaryBoolean => binaryBooleanGenerateCode(g.e, state)
       case g: BinaryDouble => binaryFloatGenerateCode(g.e, 64, state)
+      case g: BinaryFloat => binaryFloatGenerateCode(g.e, 32, state)
+      case g: BinaryIntegerKnownLength => binaryIntegerKnownLengthGenerateCode(g, state)
+      case g: ElementParseAndUnspecifiedLength => elementParseAndUnspecifiedLengthGenerateCode(g, state)
+      case g: OrderedSequence => orderedSequenceGenerateCode(g, state)
+      case g: SeqComp => seqCompGenerateCode(g, state)
       case _: CaptureContentLengthStart => noop
       case _: CaptureContentLengthEnd => noop
       case _: CaptureValueLengthStart => noop
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryBooleanCodeGenerator.scala
similarity index 51%
copy from daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
copy to daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryBooleanCodeGenerator.scala
index c3ac488..e5a7d3a 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryBooleanCodeGenerator.scala
@@ -17,52 +17,62 @@
 
 package org.apache.daffodil.runtime2.generators
 
-import org.apache.daffodil.grammar.primitives.BinaryIntegerKnownLength
+import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.exceptions.Assert
+import org.apache.daffodil.schema.annotation.props.gen.BitOrder
+import org.apache.daffodil.schema.annotation.props.gen.ByteOrder
 import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
-import org.apache.daffodil.schema.annotation.props.gen.{ BitOrder, ByteOrder }
+import passera.unsigned.ULong
 
-trait BinaryIntegerKnownLengthCodeGenerator {
+trait BinaryBooleanCodeGenerator {
 
-  def binaryIntegerKnownLengthGenerateCode(g: BinaryIntegerKnownLength, cgState: CodeGeneratorState): Unit = {
+  def binaryBooleanGenerateCode(e: ElementBase, cgState: CodeGeneratorState): Unit = {
     // For the time being this is a very limited back end.
     // So there are some restrictions to enforce.
-    val e = g.e
-    val lengthInBits: Long = {
-      e.schemaDefinitionUnless(e.elementLengthInBitsEv.isConstant, "Runtime dfdl:length expressions not supported.")
-      val len = e.elementLengthInBitsEv.constValue.get
-      len
-    }
     e.schemaDefinitionUnless(e.bitOrder eq BitOrder.MostSignificantBitFirst, "Only dfdl:bitOrder 'mostSignificantBitFirst' is supported.")
     val byteOrder: ByteOrder = {
       e.schemaDefinitionUnless(e.byteOrderEv.isConstant, "Runtime dfdl:byteOrder expressions not supported.")
-      val bo = e.byteOrderEv.constValue
-      bo
+      e.byteOrderEv.constValue
     }
-
-    // Use an unusual memory bit pattern (magic debug value) to mark our field
-    // as uninitialized in case parsing or unparsing fails to set the field.
-    val initialValue = lengthInBits match {
-      case 8 => "0xCC"
-      case 16 => "0xCCCC"
-      case 32 => "0xCCCCCCCC"
-      case 64 => "0xCCCCCCCCCCCCCCCC"
-      case _ => e.SDE("Lengths other than 8, 16, 32, or 64 bits are not supported.")
+    val lengthInBits: Long = {
+      e.schemaDefinitionUnless(e.elementLengthInBitsEv.isConstant, "Runtime dfdl:length expressions not supported.")
+      val len = e.elementLengthInBitsEv.constValue.get
+      len match {
+        case 8 | 16 | 32 => len
+        case _ => e.SDE("Boolean lengths other than 8, 16, or 32 bits are not supported.")
+      }
     }
+    Assert.invariant(e.binaryBooleanTrueRep.isEmpty || e.binaryBooleanTrueRep.getULong >= ULong(0))
+    Assert.invariant(e.binaryBooleanFalseRep >= ULong(0))
+
+    val initialValue = "true"
     val fieldName = e.namedQName.local
-    val integer = if (g.signed) s"int${lengthInBits}" else s"uint${lengthInBits}"
     val conv = if (byteOrder eq ByteOrder.BigEndian) "be" else "le"
+    val prim = s"bool$lengthInBits"
+    val trueRep = if (e.binaryBooleanTrueRep.isDefined) e.binaryBooleanTrueRep.getULong else -1
+    val falseRep = e.binaryBooleanFalseRep
+    val unparseTrueRep = if (e.binaryBooleanTrueRep.isDefined) s"$trueRep" else s"~$falseRep"
     val arraySize = if (e.occursCountKind == OccursCountKind.Fixed) e.maxOccurs else 0
+    val fixed = e.xml.attribute("fixed")
+    val fixedValue = if (fixed.isDefined) fixed.get.text else ""
 
-    def addSimpleTypeStatements(deref: String): Unit = {
+    def addStatements(deref: String): Unit = {
       val initStatement = s"    instance->$fieldName$deref = $initialValue;"
-      val parseStatement = s"    parse_${conv}_$integer(&instance->$fieldName$deref, pstate);"
-      val unparseStatement = s"    unparse_${conv}_$integer(instance->$fieldName$deref, ustate);"
+      val parseStatement = s"    parse_${conv}_$prim(&instance->$fieldName$deref, $trueRep, $falseRep, pstate);"
+      val unparseStatement = s"    unparse_${conv}_$prim(instance->$fieldName$deref, $unparseTrueRep, $falseRep, ustate);"
       cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+
+      if (fixedValue.nonEmpty) {
+        val init2 = ""
+        val parse2 = s"""    parse_validate_fixed(instance->$fieldName$deref == $fixedValue, "$fieldName", pstate);"""
+        val unparse2 = s"""    unparse_validate_fixed(instance->$fieldName$deref == $fixedValue, "$fieldName", ustate);"""
+        cgState.addSimpleTypeStatements(init2, parse2, unparse2)
+      }
     }
     if (arraySize > 0)
       for (i <- 0 until arraySize)
-        addSimpleTypeStatements(s"[$i]")
+        addStatements(s"[$i]")
     else
-      addSimpleTypeStatements("")
+      addStatements("")
   }
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala
index 2567ae0..332ba66 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala
@@ -35,21 +35,31 @@ trait BinaryFloatCodeGenerator {
 
     // Use a NAN to mark our field as uninitialized in case parsing or unparsing
     // fails to set the field.
+    val initialValue = "NAN"
     val fieldName = e.namedQName.local
-    val float = if (lengthInBits == 32) "float" else "double"
     val conv = if (byteOrder eq ByteOrder.BigEndian) "be" else "le"
+    val prim = if (lengthInBits == 32) "float" else "double"
     val arraySize = if (e.occursCountKind == OccursCountKind.Fixed) e.maxOccurs else 0
+    val fixed = e.xml.attribute("fixed")
+    val fixedValue = if (fixed.isDefined) fixed.get.text else ""
 
-    def addSimpleTypeStatements(deref: String): Unit = {
-      val initStatement = s"    instance->$fieldName$deref = NAN;"
-      val parseStatement = s"    parse_${conv}_$float(&instance->$fieldName$deref, pstate);"
-      val unparseStatement = s"    unparse_${conv}_$float(instance->$fieldName$deref, ustate);"
+    def addStatements(deref: String): Unit = {
+      val initStatement = s"    instance->$fieldName$deref = $initialValue;"
+      val parseStatement = s"    parse_${conv}_$prim(&instance->$fieldName$deref, pstate);"
+      val unparseStatement = s"    unparse_${conv}_$prim(instance->$fieldName$deref, ustate);"
       cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+
+      if (fixedValue.nonEmpty) {
+        val init2 = ""
+        val parse2 = s"""    parse_validate_fixed(instance->$fieldName$deref == $fixedValue, "$fieldName", pstate);"""
+        val unparse2 = s"""    unparse_validate_fixed(instance->$fieldName$deref == $fixedValue, "$fieldName", ustate);"""
+        cgState.addSimpleTypeStatements(init2, parse2, unparse2)
+      }
     }
     if (arraySize > 0)
       for (i <- 0 until arraySize)
-        addSimpleTypeStatements(s"[$i]")
+        addStatements(s"[$i]")
     else
-      addSimpleTypeStatements("")
+      addStatements("")
   }
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
index c3ac488..9761b3b 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
@@ -46,23 +46,32 @@ trait BinaryIntegerKnownLengthCodeGenerator {
       case 16 => "0xCCCC"
       case 32 => "0xCCCCCCCC"
       case 64 => "0xCCCCCCCCCCCCCCCC"
-      case _ => e.SDE("Lengths other than 8, 16, 32, or 64 bits are not supported.")
+      case _ => e.SDE("Integer lengths other than 8, 16, 32, or 64 bits are not supported.")
     }
     val fieldName = e.namedQName.local
-    val integer = if (g.signed) s"int${lengthInBits}" else s"uint${lengthInBits}"
     val conv = if (byteOrder eq ByteOrder.BigEndian) "be" else "le"
+    val prim = if (g.signed) s"int${lengthInBits}" else s"uint${lengthInBits}"
     val arraySize = if (e.occursCountKind == OccursCountKind.Fixed) e.maxOccurs else 0
+    val fixed = e.xml.attribute("fixed")
+    val fixedValue = if (fixed.isDefined) fixed.get.text else ""
 
-    def addSimpleTypeStatements(deref: String): Unit = {
+    def addStatements(deref: String): Unit = {
       val initStatement = s"    instance->$fieldName$deref = $initialValue;"
-      val parseStatement = s"    parse_${conv}_$integer(&instance->$fieldName$deref, pstate);"
-      val unparseStatement = s"    unparse_${conv}_$integer(instance->$fieldName$deref, ustate);"
+      val parseStatement = s"    parse_${conv}_$prim(&instance->$fieldName$deref, pstate);"
+      val unparseStatement = s"    unparse_${conv}_$prim(instance->$fieldName$deref, ustate);"
       cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+
+      if (fixedValue.nonEmpty) {
+        val init2 = ""
+        val parse2 = s"""    parse_validate_fixed(instance->$fieldName$deref == $fixedValue, "$fieldName", pstate);"""
+        val unparse2 = s"""    unparse_validate_fixed(instance->$fieldName$deref == $fixedValue, "$fieldName", ustate);"""
+        cgState.addSimpleTypeStatements(init2, parse2, unparse2)
+      }
     }
     if (arraySize > 0)
       for (i <- 0 until arraySize)
-        addSimpleTypeStatements(s"[$i]")
+        addStatements(s"[$i]")
     else
-      addSimpleTypeStatements("")
+      addStatements("")
   }
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
index 5142db7..0fd7922 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -17,8 +17,8 @@
 
 package org.apache.daffodil.runtime2.generators
 
+import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.cookers.ChoiceBranchKeyCooker
-import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.dsom.AbstractElementRef
 import org.apache.daffodil.dsom.Choice
@@ -67,8 +67,21 @@ class CodeGeneratorState {
     val C = localName(context)
     val initStatements = structs.top.initStatements.mkString("\n")
     val initChoiceStatements = structs.top.initChoiceStatements.mkString("\n")
-    val parserStatements = structs.top.parserStatements.mkString("\n")
-    val unparserStatements = structs.top.unparserStatements.mkString("\n")
+    val hasStatements = structs.top.parserStatements.nonEmpty
+    val parserStatements = if (hasStatements)
+      structs.top.parserStatements.mkString("\n")
+    else
+      s"""    // Empty struct, but need to prevent compiler warnings
+         |    UNUSED(${C}_compute_offsets);
+         |    UNUSED(instance);
+         |    UNUSED(pstate);""".stripMargin
+    val unparserStatements = if (hasStatements)
+      structs.top.unparserStatements.mkString("\n")
+    else
+      s"""    // Empty struct, but need to prevent compiler warnings
+         |    UNUSED(${C}_compute_offsets);
+         |    UNUSED(instance);
+         |    UNUSED(ustate);""".stripMargin
     val hasChoice = structs.top.initChoiceStatements.nonEmpty
     val root = structs.elems.last.C
     val prototypeInitChoice = if (hasChoice)
@@ -171,12 +184,24 @@ class CodeGeneratorState {
     res
   }
 
+  // We know context is a complex type.  We need to 1) support choice groups; 2) support
+  // padding complex elements to explicit lengths with fill bytes
   def addBeforeSwitchStatements(context: ElementBase): Unit = {
     val erd = erdName(context)
     val initStatement = s"    instance->_base.erd = &$erd;"
 
     structs.top.initStatements += initStatement
 
+    // Implement padding if complex type has an explicit length
+    if (context.maybeFixedLengthInBits.isDefined && context.maybeFixedLengthInBits.get > 0) {
+      val lengthInBytes = context.maybeFixedLengthInBits.get / 8;
+      val parseStatement = s"    const size_t end_position = pstate->position + $lengthInBytes;"
+      val unparseStatement = s"    const size_t end_position = ustate->position + $lengthInBytes;"
+
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+
     val dispatchField = choiceDispatchField(context)
     if (dispatchField.nonEmpty) {
       val C = localName(context)
@@ -222,7 +247,9 @@ class CodeGeneratorState {
     }
   }
 
-  def addAfterSwitchStatements(): Unit = {
+  // We know context is a complex type.  We need to 1) support choice groups; 2) support
+  // padding complex elements to explicit lengths with fill bytes
+  def addAfterSwitchStatements(context: ElementBase): Unit = {
     if (structs.top.initChoiceStatements.nonEmpty) {
       val declaration = s"    };"
       val initChoiceStatement =
@@ -262,6 +289,16 @@ class CodeGeneratorState {
       structs.top.parserStatements += parseStatement
       structs.top.unparserStatements += unparseStatement
     }
+
+    // Implement padding if complex type has an explicit length
+    if (context.maybeFixedLengthInBits.isDefined && context.maybeFixedLengthInBits.get > 0) {
+      val octalFillByte = context.fillByteEv.constValue.toByte.toOctalString
+      val parseStatement = s"    parse_fill_bytes(end_position, pstate);"
+      val unparseStatement = s"    unparse_fill_bytes(end_position, '\\$octalFillByte', ustate);"
+
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
   }
 
   def addComplexTypeERD(context: ElementBase): Unit = {
@@ -316,41 +353,55 @@ class CodeGeneratorState {
   }
 
   def addSimpleTypeStatements(initStatement: String, parseStatement: String, unparseStatement: String): Unit = {
-    structs.top.initStatements += initStatement
-    structs.top.parserStatements += parseStatement
-    structs.top.unparserStatements += unparseStatement
+    if (initStatement.nonEmpty) structs.top.initStatements += initStatement
+    if (parseStatement.nonEmpty) structs.top.parserStatements += parseStatement
+    if (unparseStatement.nonEmpty) structs.top.unparserStatements += unparseStatement
   }
 
   def addComplexTypeStatements(child: ElementBase): Unit = {
     val C = localName(child)
     val e = child.name
     val hasChoice = structs.top.initChoiceStatements.nonEmpty
-    val offset = if (hasChoice) child.position - 1 else -1
-    val initStatement = s"    ${C}_initSelf(&instance->$e);"
-    val initChoiceStatement =
-      s"""        instance->_choice = $offset;
-         |        break;""".stripMargin
-    val parseStatement = if (hasChoice)
-      s"""    case $offset:
-         |        ${C}_parseSelf(&instance->$e, pstate);
-         |        break;""".stripMargin
-    else
-      s"    ${C}_parseSelf(&instance->$e, pstate);"
-    val unparseStatement = if (hasChoice)
-      s"""    case $offset:
-         |        ${C}_unparseSelf(&instance->$e, ustate);
-         |        break;""".stripMargin
-    else
-      s"    ${C}_unparseSelf(&instance->$e, ustate);"
+    val arraySize = if (child.occursCountKind == OccursCountKind.Fixed) child.maxOccurs else 0
 
-    structs.top.initStatements += initStatement
     if (hasChoice) {
+      val offset = child.position - 1
+      val initChoiceStatement =
+        s"""        instance->_choice = $offset;
+           |        break;""".stripMargin
+      val parseStatement = s"    case $offset:"
+      val unparseStatement = s"    case $offset:"
+
       structs.top.initChoiceStatements ++= ChoiceBranchKeyCooker.convertConstant(
         child.choiceBranchKey, child, forUnparse = false).map { key => s"    case $key:"}
       structs.top.initChoiceStatements += initChoiceStatement
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+
+    def addStatements(deref: String): Unit = {
+      val moreIndent = if (hasChoice) "    " else ""
+      val initStatement = s"    ${C}_initSelf(&instance->$e$deref);"
+      val parseStatement = s"    $moreIndent${C}_parseSelf(&instance->$e$deref, pstate);"
+      val unparseStatement = s"    $moreIndent${C}_unparseSelf(&instance->$e$deref, ustate);"
+
+      structs.top.initStatements += initStatement
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
+    }
+    if (arraySize > 0)
+      for (i <- 0 until arraySize)
+        addStatements(s"[$i]")
+    else
+      addStatements("")
+
+    if (hasChoice) {
+      val parseStatement = s"        break;"
+      val unparseStatement = s"        break;"
+
+      structs.top.parserStatements += parseStatement
+      structs.top.unparserStatements += unparseStatement
     }
-    structs.top.parserStatements += parseStatement
-    structs.top.unparserStatements += unparseStatement
   }
 
   def pushComplexElement(context: ElementBase): Unit = {
@@ -362,21 +413,74 @@ class CodeGeneratorState {
     structs.pop()
   }
 
+  // Gets length from explicit length declaration if any, otherwise from base type's implicit length
+  private def getLengthInBits(e: ElementBase): Long = {
+    e.schemaDefinitionUnless(e.elementLengthInBitsEv.isConstant, "Runtime dfdl:length expressions are not supported.")
+    e.elementLengthInBitsEv.constValue.get
+  }
+
+  // Because schema authors don't always get types right, allows explicit lengths to override implicit lengths
+  private def getPrimType(e: ElementBase): PrimType = {
+    val primType = e.optPrimType.get match {
+      case PrimType.Byte
+         | PrimType.Short
+         | PrimType.Int
+         | PrimType.Long
+         | PrimType.Integer =>
+        getLengthInBits(e) match {
+          case 8 =>  PrimType.Byte
+          case 16 => PrimType.Short
+          case 32 => PrimType.Int
+          case 64 => PrimType.Long
+          case _ =>  e.SDE("Integer lengths other than 8, 16, 32, or 64 bits are not supported.")
+        }
+      case PrimType.UnsignedByte
+         | PrimType.UnsignedShort
+         | PrimType.UnsignedInt
+         | PrimType.UnsignedLong
+         | PrimType.NonNegativeInteger =>
+        getLengthInBits(e) match {
+          case 8 =>  PrimType.UnsignedByte
+          case 16 => PrimType.UnsignedShort
+          case 32 => PrimType.UnsignedInt
+          case 64 => PrimType.UnsignedLong
+          case _ =>  e.SDE("Unsigned integer lengths other than 8, 16, 32, or 64 bits are not supported.")
+        }
+      case PrimType.Double
+         | PrimType.Float =>
+        getLengthInBits(e) match {
+          case 32 => PrimType.Float
+          case 64 => PrimType.Double
+          case _ =>  e.SDE("Floating point lengths other than 32 or 64 bits are not supported.")
+        }
+      case PrimType.Boolean =>
+        getLengthInBits(e) match {
+          case 8 | 16 | 32 => PrimType.Boolean
+          case _ => e.SDE("Boolean lengths other than 8, 16, or 32 bits are not supported.")
+        }
+      case p => e.SDE("PrimType %s is not supported in C code generator.", p.toString)
+    }
+    if (primType != e.optPrimType.get)
+      e.SDW(WarnID.IgnoreDFDLProperty, "Ignoring PrimType %s, using %s", e.optPrimType.get.toString, primType.toString)
+    primType
+  }
+
   def addSimpleTypeERD(context: ElementBase): Unit = {
     val erd = erdName(context)
     val qnameInit = defineQNameInit(context)
-    val typeCode = context.optPrimType.get match {
-      case PrimType.UnsignedLong => "PRIMITIVE_UINT64"
-      case PrimType.UnsignedInt => "PRIMITIVE_UINT32"
-      case PrimType.UnsignedShort => "PRIMITIVE_UINT16"
-      case PrimType.UnsignedByte => "PRIMITIVE_UINT8"
-      case PrimType.Long => "PRIMITIVE_INT64"
-      case PrimType.Int => "PRIMITIVE_INT32"
+    val typeCode = getPrimType(context) match {
+      case PrimType.Boolean => "PRIMITIVE_BOOLEAN"
+      case PrimType.Double => "PRIMITIVE_DOUBLE"
+      case PrimType.Float => "PRIMITIVE_FLOAT"
       case PrimType.Short => "PRIMITIVE_INT16"
+      case PrimType.Int => "PRIMITIVE_INT32"
+      case PrimType.Long => "PRIMITIVE_INT64"
       case PrimType.Byte => "PRIMITIVE_INT8"
-      case PrimType.Float => "PRIMITIVE_FLOAT"
-      case PrimType.Double => "PRIMITIVE_DOUBLE"
-      case p: PrimType => context.SDE("PrimType %s not supported yet.", p.toString)
+      case PrimType.UnsignedShort => "PRIMITIVE_UINT16"
+      case PrimType.UnsignedInt => "PRIMITIVE_UINT32"
+      case PrimType.UnsignedLong => "PRIMITIVE_UINT64"
+      case PrimType.UnsignedByte => "PRIMITIVE_UINT8"
+      case p => context.SDE("PrimType %s is not supported.", p.toString)
     }
     val erdDef =
       s"""static const ERD $erd = {
@@ -409,19 +513,19 @@ class CodeGeneratorState {
 
   def addFieldDeclaration(context: ThrowsSDE, child: ElementBase): Unit = {
     val definition = if (child.isSimpleType) {
-      import NodeInfo.PrimType
-      child.optPrimType.get match {
-        case PrimType.UnsignedLong => "uint64_t   "
-        case PrimType.UnsignedInt => "uint32_t   "
-        case PrimType.UnsignedShort => "uint16_t   "
-        case PrimType.UnsignedByte => "uint8_t    "
-        case PrimType.Long => "int64_t    "
-        case PrimType.Int => "int32_t    "
+      getPrimType(child) match {
+        case PrimType.Boolean => "bool       "
+        case PrimType.Double => "double     "
+        case PrimType.Float => "float      "
         case PrimType.Short => "int16_t    "
+        case PrimType.Int => "int32_t    "
+        case PrimType.Long => "int64_t    "
         case PrimType.Byte => "int8_t     "
-        case PrimType.Float => "float      "
-        case PrimType.Double => "double     "
-        case x => context.SDE("Unsupported primitive type: " + x)
+        case PrimType.UnsignedShort => "uint16_t   "
+        case PrimType.UnsignedInt => "uint32_t   "
+        case PrimType.UnsignedLong => "uint64_t   "
+        case PrimType.UnsignedByte => "uint8_t    "
+        case p => child.SDE("PrimType %s is not supported: ", p.toString)
       }
     } else {
       localName(child)
@@ -441,6 +545,7 @@ class CodeGeneratorState {
          |#define GENERATED_CODE_H
          |
          |#include "infoset.h"  // for InfosetBase
+         |#include <stdbool.h>  // for bool
          |#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
          |// Define infoset structures
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
index 26203f8..553d2c7 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
@@ -49,7 +49,7 @@ trait ElementParseAndUnspecifiedLengthCodeGenerator {
         cgState.addFieldDeclaration(context, child) // struct member for child
         Runtime2CodeGenerator.generateCode(child.enclosedElement, cgState) // generate children too
       }
-      cgState.addAfterSwitchStatements() // switch statements for choices
+      cgState.addAfterSwitchStatements(context) // switch statements for choices
       cgState.addStruct(context) // struct definition
       cgState.addImplementation(context) // initSelf, parseSelf, unparseSelf
       cgState.addComplexTypeERD(context) // ERD static initializer
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
index 06355f0..af0aa43 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.dfdl.xsd
@@ -17,21 +17,24 @@
 -->
 
 <xs:schema
-    elementFormDefault="qualified"
-    targetNamespace="http://example.com"
-    xmlns="http://example.com"
-    xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
-    xmlns:xs="http://www.w3.org/2001/XMLSchema">
+        elementFormDefault="qualified"
+        targetNamespace="http://example.com"
+        xmlns="http://example.com"
+        xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+        xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
     <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
 
     <xs:annotation>
         <xs:appinfo source="http://www.ogf.org/dfdl/">
             <dfdl:format
-                byteOrder="bigEndian"
-                encoding="UTF-8"
-                representation="binary"
-                ref="GeneralFormat"/>
+                    binaryBooleanFalseRep="0"
+                    binaryBooleanTrueRep=""
+                    byteOrder="bigEndian"
+                    encoding="UTF-8"
+                    lengthUnits="bits"
+                    representation="binary"
+                    ref="GeneralFormat"/>
         </xs:appinfo>
     </xs:annotation>
 
@@ -41,44 +44,115 @@
                 <xs:element name="array">
                     <xs:complexType>
                         <xs:sequence>
-                            <xs:element name="be_int16" type="xs:short"
-                                        minOccurs="3" maxOccurs="3" dfdl:occursCountKind="fixed" />
+                            <xs:element name="be_bool16" type="xs:boolean"
+                                        dfdl:length="16"
+                                        dfdl:lengthKind="explicit"
+                                        dfdl:occursCountKind="fixed"
+                                        maxOccurs="2" minOccurs="2"/>
                             <xs:element name="be_float" type="xs:float"
-                                        minOccurs="3" maxOccurs="3" dfdl:occursCountKind="fixed" />
+                                        dfdl:occursCountKind="fixed"
+                                        minOccurs="3" maxOccurs="3"/>
+                            <xs:element name="be_int16" type="xs:short"
+                                        dfdl:occursCountKind="fixed"
+                                        minOccurs="3" maxOccurs="3"/>
                         </xs:sequence>
                     </xs:complexType>
                 </xs:element>
                 <xs:element name="bigEndian">
-                  <xs:complexType>
-                    <xs:sequence>
-                      <xs:element name="be_double" type="xs:double" />
-                      <xs:element name="be_float" type="xs:float" />
-                      <xs:element name="be_uint64" type="xs:unsignedLong" />
-                      <xs:element name="be_uint32" type="xs:unsignedInt" />
-                      <xs:element name="be_uint16" type="xs:unsignedShort" />
-                      <xs:element name="be_uint8" type="xs:unsignedByte" />
-                      <xs:element name="be_int64" type="xs:long" />
-                      <xs:element name="be_int32" type="xs:int" />
-                      <xs:element name="be_int16" type="xs:short" />
-                      <xs:element name="be_int8" type="xs:byte" />
-                    </xs:sequence>
-                  </xs:complexType>
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="be_bool16" type="xs:boolean"
+                                        dfdl:binaryBooleanTrueRep="1"
+                                        dfdl:length="16"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="be_bool32" type="xs:boolean"
+                                        dfdl:length="32"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="be_bool8" type="xs:boolean"
+                                        dfdl:length="8"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="be_boolean" type="xs:boolean"/>
+                            <xs:element name="be_double" type="xs:double"/>
+                            <xs:element name="be_float" type="xs:float"/>
+                            <xs:element name="be_int16" type="xs:short"/>
+                            <xs:element name="be_int32" type="xs:int"/>
+                            <xs:element name="be_int64" type="xs:long"/>
+                            <xs:element name="be_int8" type="xs:byte"/>
+                            <xs:element name="be_integer16" type="xs:integer"
+                                        dfdl:length="16"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="be_uint16" type="xs:unsignedShort"/>
+                            <xs:element name="be_uint32" type="xs:unsignedInt"/>
+                            <xs:element name="be_uint64" type="xs:unsignedLong"/>
+                            <xs:element name="be_uint8" type="xs:unsignedByte"/>
+                            <xs:element name="be_nonNegativeInteger32" type="xs:nonNegativeInteger"
+                                        dfdl:length="32"
+                                        dfdl:lengthKind="explicit"/>
+                        </xs:sequence>
+                    </xs:complexType>
                 </xs:element>
                 <xs:element name="littleEndian">
-                  <xs:complexType>
-                    <xs:sequence>
-                      <xs:element name="le_uint64" type="xs:unsignedLong" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_uint32" type="xs:unsignedInt" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_uint16" type="xs:unsignedShort" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_uint8" type="xs:unsignedByte" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_int64" type="xs:long" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_int32" type="xs:int" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_int16" type="xs:short" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_int8" type="xs:byte" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_float" type="xs:float" dfdl:byteOrder="littleEndian" />
-                      <xs:element name="le_double" type="xs:double" dfdl:byteOrder="littleEndian" />
-                    </xs:sequence>
-                  </xs:complexType>
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="le_bool16" type="xs:boolean"
+                                        dfdl:binaryBooleanTrueRep="1"
+                                        dfdl:byteOrder="littleEndian"
+                                        dfdl:length="16"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="le_bool32" type="xs:boolean"
+                                        dfdl:byteOrder="littleEndian"
+                                        dfdl:length="32"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="le_bool8" type="xs:boolean"
+                                        dfdl:byteOrder="littleEndian"
+                                        dfdl:length="8"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="le_boolean" type="xs:boolean"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_double" type="xs:double"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_float" type="xs:float"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_int16" type="xs:short"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_int32" type="xs:int"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_int64" type="xs:long"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_int8" type="xs:byte"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_integer64" type="xs:integer"
+                                        dfdl:byteOrder="littleEndian"
+                                        dfdl:length="64"
+                                        dfdl:lengthKind="explicit"/>
+                            <xs:element name="le_uint16" type="xs:unsignedShort"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_uint32" type="xs:unsignedInt"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_uint64" type="xs:unsignedLong"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_uint8" type="xs:unsignedByte"
+                                        dfdl:byteOrder="littleEndian"/>
+                            <xs:element name="le_nonNegativeInteger8" type="xs:nonNegativeInteger"
+                                        dfdl:byteOrder="littleEndian"
+                                        dfdl:length="8"
+                                        dfdl:lengthKind="explicit"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="fixed">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="boolean_false" type="xs:boolean"
+                                        fixed="false"/>
+                            <xs:element name="boolean_true" type="xs:boolean"
+                                        fixed="true"/>
+                            <xs:element name="float_1_5" type="xs:float"
+                                        fixed="1.5"/>
+                            <xs:element name="int_32" type="xs:int"
+                                        fixed="32"/>
+                        </xs:sequence>
+                    </xs:complexType>
                 </xs:element>
             </xs:sequence>
         </xs:complexType>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
index 3d12954..812c327 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
@@ -84,4 +84,19 @@
     </tdml:document>
   </tdml:unparserTestCase>
 
+  <tdml:unparserTestCase
+    name="ex_nums_unparse_errors"
+    model="ex_nums.dfdl.xsd"
+    config="config-runtime2">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse_errors.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:errors>
+      <tdml:error>value</tdml:error>
+      <tdml:error>does not match</tdml:error>
+      <tdml:error>fixed</tdml:error>
+      <tdml:error>attribute</tdml:error>
+    </tdml:errors>
+  </tdml:unparserTestCase>
+
 </tdml:testSuite>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat
index 7df03f3..d3285c0 100644
Binary files a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_errors.xml
similarity index 72%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
copy to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_errors.xml
index d30a688..deb8839 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_errors.xml
@@ -18,35 +18,55 @@
 
 <ex_nums xmlns="http://example.com">
   <array>
-    <be_int16>1</be_int16>
-    <be_int16>2</be_int16>
-    <be_int16>3</be_int16>
+    <be_bool16>false</be_bool16>
+    <be_bool16>true</be_bool16>
     <be_float>1.0</be_float>
     <be_float>INF</be_float>
     <be_float>NaN</be_float>
+    <be_int16>1</be_int16>
+    <be_int16>2</be_int16>
+    <be_int16>3</be_int16>
   </array>
   <bigEndian>
+    <be_bool16>true</be_bool16>
+    <be_bool32>true</be_bool32>
+    <be_bool8>false</be_bool8>
+    <be_boolean>false</be_boolean>
     <be_double>1.7976931348623157E308</be_double>
     <be_float>3.4028235E38</be_float>
-    <be_uint64>64</be_uint64>
-    <be_uint32>32</be_uint32>
-    <be_uint16>16</be_uint16>
-    <be_uint8>8</be_uint8>
-    <be_int64>-64</be_int64>
-    <be_int32>-32</be_int32>
     <be_int16>-16</be_int16>
+    <be_int32>-32</be_int32>
+    <be_int64>-64</be_int64>
     <be_int8>-8</be_int8>
+    <be_integer16>-16</be_integer16>
+    <be_uint16>16</be_uint16>
+    <be_uint32>32</be_uint32>
+    <be_uint64>64</be_uint64>
+    <be_uint8>8</be_uint8>
+    <be_nonNegativeInteger32>32</be_nonNegativeInteger32>
   </bigEndian>
   <littleEndian>
-    <le_uint64>64</le_uint64>
-    <le_uint32>32</le_uint32>
-    <le_uint16>16</le_uint16>
-    <le_uint8>8</le_uint8>
-    <le_int64>-64</le_int64>
-    <le_int32>-32</le_int32>
+    <le_bool16>true</le_bool16>
+    <le_bool32>true</le_bool32>
+    <le_bool8>false</le_bool8>
+    <le_boolean>false</le_boolean>
+    <le_double>-2.2250738585072014E-308</le_double>
+    <le_float>-1.17549435E-38</le_float>
     <le_int16>-16</le_int16>
+    <le_int32>-32</le_int32>
+    <le_int64>-64</le_int64>
     <le_int8>-8</le_int8>
-    <le_float>-1.17549435E-38</le_float>
-    <le_double>-2.2250738585072014E-308</le_double>
+    <le_integer64>-64</le_integer64>
+    <le_uint16>16</le_uint16>
+    <le_uint32>32</le_uint32>
+    <le_uint64>64</le_uint64>
+    <le_uint8>8</le_uint8>
+    <le_nonNegativeInteger8>8</le_nonNegativeInteger8>
   </littleEndian>
+  <fixed>
+    <boolean_false>true</boolean_false>
+    <boolean_true>false</boolean_true>
+    <float_1_5>0.0</float_1_5>
+    <int_32>0</int_32>
+  </fixed>
 </ex_nums>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
index d30a688..ae38f12 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime1.xml
@@ -18,35 +18,55 @@
 
 <ex_nums xmlns="http://example.com">
   <array>
-    <be_int16>1</be_int16>
-    <be_int16>2</be_int16>
-    <be_int16>3</be_int16>
+    <be_bool16>false</be_bool16>
+    <be_bool16>true</be_bool16>
     <be_float>1.0</be_float>
     <be_float>INF</be_float>
     <be_float>NaN</be_float>
+    <be_int16>1</be_int16>
+    <be_int16>2</be_int16>
+    <be_int16>3</be_int16>
   </array>
   <bigEndian>
+    <be_bool16>true</be_bool16>
+    <be_bool32>true</be_bool32>
+    <be_bool8>false</be_bool8>
+    <be_boolean>false</be_boolean>
     <be_double>1.7976931348623157E308</be_double>
     <be_float>3.4028235E38</be_float>
-    <be_uint64>64</be_uint64>
-    <be_uint32>32</be_uint32>
-    <be_uint16>16</be_uint16>
-    <be_uint8>8</be_uint8>
-    <be_int64>-64</be_int64>
-    <be_int32>-32</be_int32>
     <be_int16>-16</be_int16>
+    <be_int32>-32</be_int32>
+    <be_int64>-64</be_int64>
     <be_int8>-8</be_int8>
+    <be_integer16>-16</be_integer16>
+    <be_uint16>16</be_uint16>
+    <be_uint32>32</be_uint32>
+    <be_uint64>64</be_uint64>
+    <be_uint8>8</be_uint8>
+    <be_nonNegativeInteger32>32</be_nonNegativeInteger32>
   </bigEndian>
   <littleEndian>
-    <le_uint64>64</le_uint64>
-    <le_uint32>32</le_uint32>
-    <le_uint16>16</le_uint16>
-    <le_uint8>8</le_uint8>
-    <le_int64>-64</le_int64>
-    <le_int32>-32</le_int32>
+    <le_bool16>true</le_bool16>
+    <le_bool32>true</le_bool32>
+    <le_bool8>false</le_bool8>
+    <le_boolean>false</le_boolean>
+    <le_double>-2.2250738585072014E-308</le_double>
+    <le_float>-1.17549435E-38</le_float>
     <le_int16>-16</le_int16>
+    <le_int32>-32</le_int32>
+    <le_int64>-64</le_int64>
     <le_int8>-8</le_int8>
-    <le_float>-1.17549435E-38</le_float>
-    <le_double>-2.2250738585072014E-308</le_double>
+    <le_integer64>-64</le_integer64>
+    <le_uint16>16</le_uint16>
+    <le_uint32>32</le_uint32>
+    <le_uint64>64</le_uint64>
+    <le_uint8>8</le_uint8>
+    <le_nonNegativeInteger8>8</le_nonNegativeInteger8>
   </littleEndian>
+  <fixed>
+    <boolean_false>false</boolean_false>
+    <boolean_true>true</boolean_true>
+    <float_1_5>1.5</float_1_5>
+    <int_32>32</int_32>
+  </fixed>
 </ex_nums>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
index f45a9fc..a656481 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse_runtime2.xml
@@ -18,35 +18,55 @@
 
 <ex_nums xmlns="http://example.com">
   <array>
-    <be_int16>1</be_int16>
-    <be_int16>2</be_int16>
-    <be_int16>3</be_int16>
+    <be_bool16>false</be_bool16>
+    <be_bool16>true</be_bool16>
     <be_float>1</be_float>
     <be_float>INF</be_float>
     <be_float>NaN</be_float>
+    <be_int16>1</be_int16>
+    <be_int16>2</be_int16>
+    <be_int16>3</be_int16>
   </array>
   <bigEndian>
+    <be_bool16>true</be_bool16>
+    <be_bool32>true</be_bool32>
+    <be_bool8>false</be_bool8>
+    <be_boolean>false</be_boolean>
     <be_double>1.7976931348623157E+308</be_double>
     <be_float>3.40282347E+38</be_float>
-    <be_uint64>64</be_uint64>
-    <be_uint32>32</be_uint32>
-    <be_uint16>16</be_uint16>
-    <be_uint8>8</be_uint8>
-    <be_int64>-64</be_int64>
-    <be_int32>-32</be_int32>
     <be_int16>-16</be_int16>
+    <be_int32>-32</be_int32>
+    <be_int64>-64</be_int64>
     <be_int8>-8</be_int8>
+    <be_integer16>-16</be_integer16>
+    <be_uint16>16</be_uint16>
+    <be_uint32>32</be_uint32>
+    <be_uint64>64</be_uint64>
+    <be_uint8>8</be_uint8>
+    <be_nonNegativeInteger32>32</be_nonNegativeInteger32>
   </bigEndian>
   <littleEndian>
-    <le_uint64>64</le_uint64>
-    <le_uint32>32</le_uint32>
-    <le_uint16>16</le_uint16>
-    <le_uint8>8</le_uint8>
-    <le_int64>-64</le_int64>
-    <le_int32>-32</le_int32>
+    <le_bool16>true</le_bool16>
+    <le_bool32>true</le_bool32>
+    <le_bool8>false</le_bool8>
+    <le_boolean>false</le_boolean>
+    <le_double>-2.2250738585072014E-308</le_double>
+    <le_float>-1.17549435E-38</le_float>
     <le_int16>-16</le_int16>
+    <le_int32>-32</le_int32>
+    <le_int64>-64</le_int64>
     <le_int8>-8</le_int8>
-    <le_float>-1.17549435E-38</le_float>
-    <le_double>-2.2250738585072014E-308</le_double>
+    <le_integer64>-64</le_integer64>
+    <le_uint16>16</le_uint16>
+    <le_uint32>32</le_uint32>
+    <le_uint64>64</le_uint64>
+    <le_uint8>8</le_uint8>
+    <le_nonNegativeInteger8>8</le_nonNegativeInteger8>
   </littleEndian>
+  <fixed>
+    <boolean_false>false</boolean_false>
+    <boolean_true>true</boolean_true>
+    <float_1_5>1.5</float_1_5>
+    <int_32>32</int_32>
+  </fixed>
 </ex_nums>
diff --git a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
index f150580..5e84cd1 100644
--- a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
+++ b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/Runtime2TDMLDFDLProcessor.scala
@@ -117,8 +117,12 @@ final class Runtime2TDMLDFDLProcessorFactory private(
       val compileResult = if (generator.isError) {
         Left(generator.getDiagnostics) // C code compilation diagnostics
       } else {
-        // Create a processor for running the test using the executable
-        val processor = new Runtime2TDMLDFDLProcessor(tempDir, executable)
+        // Create a processor for running the test using the executable, passing it
+        // generator.diagnostics in order to let us check generator warnings later
+        val processor = new Runtime2TDMLDFDLProcessor(tempDir, executable, generator.getDiagnostics)
+        // Sadly, TDMLRunner never checks generator diagnostics in "Right" tuple below
+        // nor does it check processor diagnostics in cross tests (runtime2's TDML tests)
+        // unless you set defaultShouldDoWarningComparisonOnCrossTests true in RunnerFactory
         Right((generator.getDiagnostics, processor))
       }
       compileResult
@@ -134,13 +138,13 @@ final class Runtime2TDMLDFDLProcessorFactory private(
  * TDML XML Infosets, feeding to the unparser, creating XML from the result created by
  * the Runtime2DataProcessor. All the "real work" is done by Runtime2DataProcessor.
  */
-class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path) extends TDMLDFDLProcessor {
+class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path,
+                                var diagnostics: Seq[Diagnostic]) extends TDMLDFDLProcessor {
 
   override type R = Runtime2TDMLDFDLProcessor
 
   private val dataProcessor = new Runtime2DataProcessor(executable)
   private var anyErrors: Boolean = false
-  private var diagnostics: Seq[Diagnostic] = Nil
 
   @deprecated("Use withDebugging.", "2.6.0")
   override def setDebugging(b: Boolean) = ???
@@ -175,7 +179,7 @@ class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path) extends T
     // TODO: pass lengthLimitInBits to the C program to tell it how big the data is
     val pr = dataProcessor.parse(is)
     anyErrors = pr.isError
-    diagnostics = pr.getDiagnostics
+    diagnostics = diagnostics ++ pr.getDiagnostics
     new Runtime2TDMLParseResult(pr, tempDir)
   }
 
@@ -189,7 +193,7 @@ class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path) extends T
     val inStream = os.read.inputStream(os.Path(tempInputFile))
     val upr = dataProcessor.unparse(inStream, outStream)
     anyErrors = upr.isError
-    diagnostics = upr.getDiagnostics
+    diagnostics = diagnostics ++ upr.getDiagnostics
     new Runtime2TDMLUnparseResult(upr, tempDir)
   }
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.dfdl.xsd
new file mode 100644
index 0000000..2a74955
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.dfdl.xsd
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="1" alignmentUnits="bytes" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%NUL;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bytes" occursCountKind [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="float" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:float"/>
+  </xs:simpleType>
+  <xs:simpleType name="double" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:double"/>
+  </xs:simpleType>
+  <xs:simpleType name="int8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="int32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:int"/>
+  </xs:simpleType>
+  <xs:simpleType name="int64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:long"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedLong"/>
+  </xs:simpleType>
+  <xs:simpleType name="boolean" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:boolean"/>
+  </xs:simpleType>
+  <xs:complexType name="IsrmEntry">
+    <xs:sequence>
+      <xs:element name="x" type="idl:double"/>
+      <xs:element name="y" type="idl:double"/>
+      <xs:element name="z" type="idl:double"/>
+      <xs:element name="speed" type="idl:double"/>
+      <xs:element name="bearing" type="idl:double"/>
+      <xs:element name="confidence" type="idl:double"/>
+      <xs:element name="id">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="80" maxOccurs="80" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="classification">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="80" maxOccurs="80" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="IsrmEntryDecl" type="idl:IsrmEntry"/>
+  <xs:complexType name="IsrmEnd">
+    <xs:sequence/>
+  </xs:complexType>
+  <xs:element name="IsrmEndDecl" type="idl:IsrmEnd"/>
+  <xs:simpleType name="IsrmResultTag">
+    <xs:restriction base="idl:uint32"/>
+  </xs:simpleType>
+  <xs:complexType name="IsrmResult">
+    <xs:sequence>
+      <xs:element name="tag" type="idl:IsrmResultTag"/>
+      <xs:element name="data" dfdl:length="208" dfdl:lengthKind="explicit">
+        <xs:complexType>
+          <xs:choice dfdl:choiceDispatchKey="{xs:string(../tag)}">
+            <xs:element dfdl:choiceBranchKey="0" name="entry" type="idl:IsrmEntry"/>
+            <xs:element dfdl:choiceBranchKey="1" name="end" type="idl:IsrmEnd"/>
+          </xs:choice>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="IsrmResultDecl" type="idl:IsrmResult"/>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.tdml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.tdml
index 3d12954..f062372 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.tdml
@@ -17,9 +17,11 @@
 -->
 
 <tdml:testSuite
+  defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
   defaultRoundTrip="none"
-  description="TDML tests for ex_nums"
+  defaultValidation="on"
+  description="TDML tests for ISRM_green_to_orange_60000"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,50 +39,50 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    name="ex_nums_parse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="ISRM_green_to_orange_60000.dfdl.xsd"
+    name="ISRM_green_to_orange_60000_parse_0"
+    root="IsrmResultDecl">
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ISRM_green_to_orange_60000_parse_0.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ISRM_green_to_orange_60000_unparse_0.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="ISRM_green_to_orange_60000.dfdl.xsd"
+    name="ISRM_green_to_orange_60000_unparse_0"
+    root="IsrmResultDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ISRM_green_to_orange_60000_unparse_0.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ISRM_green_to_orange_60000_parse_0.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    name="ex_nums_parse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
+    model="ISRM_green_to_orange_60000.dfdl.xsd"
+    name="ISRM_green_to_orange_60000_parse_1"
+    root="IsrmResultDecl">
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ISRM_green_to_orange_60000_parse_1.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ISRM_green_to_orange_60000_unparse_1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
+    model="ISRM_green_to_orange_60000.dfdl.xsd"
+    name="ISRM_green_to_orange_60000_unparse_1"
+    root="IsrmResultDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ISRM_green_to_orange_60000_unparse_1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ISRM_green_to_orange_60000_parse_1.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_0.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_0.dat
new file mode 100644
index 0000000..47b87e2
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_0.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_1.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_1.dat
new file mode 100644
index 0000000..3f698bb
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_1.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_0.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_0.xml
new file mode 100644
index 0000000..73609a4
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_0.xml
@@ -0,0 +1,195 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<idl:IsrmResultDecl xmlns:idl="urn:idl:1.0">
+  <tag>0</tag>
+  <data>
+    <entry>
+      <x>0.5</x>
+      <y>1.5</y>
+      <z>2.5</z>
+      <speed>3.5</speed>
+      <bearing>4.5</bearing>
+      <confidence>5.5</confidence>
+      <id>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+        <item>6</item>
+        <item>7</item>
+        <item>8</item>
+        <item>9</item>
+        <item>10</item>
+        <item>11</item>
+        <item>12</item>
+        <item>13</item>
+        <item>14</item>
+        <item>15</item>
+        <item>16</item>
+        <item>17</item>
+        <item>18</item>
+        <item>19</item>
+        <item>20</item>
+        <item>21</item>
+        <item>22</item>
+        <item>23</item>
+        <item>24</item>
+        <item>25</item>
+        <item>26</item>
+        <item>27</item>
+        <item>28</item>
+        <item>29</item>
+        <item>30</item>
+        <item>31</item>
+        <item>32</item>
+        <item>33</item>
+        <item>34</item>
+        <item>35</item>
+        <item>36</item>
+        <item>37</item>
+        <item>38</item>
+        <item>39</item>
+        <item>40</item>
+        <item>41</item>
+        <item>42</item>
+        <item>43</item>
+        <item>44</item>
+        <item>45</item>
+        <item>46</item>
+        <item>47</item>
+        <item>48</item>
+        <item>49</item>
+        <item>50</item>
+        <item>51</item>
+        <item>52</item>
+        <item>53</item>
+        <item>54</item>
+        <item>55</item>
+        <item>56</item>
+        <item>57</item>
+        <item>58</item>
+        <item>59</item>
+        <item>60</item>
+        <item>61</item>
+        <item>62</item>
+        <item>63</item>
+        <item>64</item>
+        <item>65</item>
+        <item>66</item>
+        <item>67</item>
+        <item>68</item>
+        <item>69</item>
+        <item>70</item>
+        <item>71</item>
+        <item>72</item>
+        <item>73</item>
+        <item>74</item>
+        <item>75</item>
+        <item>76</item>
+        <item>77</item>
+        <item>78</item>
+        <item>79</item>
+      </id>
+      <classification>
+        <item>0</item>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+        <item>6</item>
+        <item>7</item>
+        <item>8</item>
+        <item>9</item>
+        <item>10</item>
+        <item>11</item>
+        <item>12</item>
+        <item>13</item>
+        <item>14</item>
+        <item>15</item>
+        <item>16</item>
+        <item>17</item>
+        <item>18</item>
+        <item>19</item>
+        <item>20</item>
+        <item>21</item>
+        <item>22</item>
+        <item>23</item>
+        <item>24</item>
+        <item>25</item>
+        <item>26</item>
+        <item>27</item>
+        <item>28</item>
+        <item>29</item>
+        <item>30</item>
+        <item>31</item>
+        <item>32</item>
+        <item>33</item>
+        <item>34</item>
+        <item>35</item>
+        <item>36</item>
+        <item>37</item>
+        <item>38</item>
+        <item>39</item>
+        <item>40</item>
+        <item>41</item>
+        <item>42</item>
+        <item>43</item>
+        <item>44</item>
+        <item>45</item>
+        <item>46</item>
+        <item>47</item>
+        <item>48</item>
+        <item>49</item>
+        <item>50</item>
+        <item>51</item>
+        <item>52</item>
+        <item>53</item>
+        <item>54</item>
+        <item>55</item>
+        <item>56</item>
+        <item>57</item>
+        <item>58</item>
+        <item>59</item>
+        <item>60</item>
+        <item>61</item>
+        <item>62</item>
+        <item>63</item>
+        <item>64</item>
+        <item>65</item>
+        <item>66</item>
+        <item>67</item>
+        <item>68</item>
+        <item>69</item>
+        <item>70</item>
+        <item>71</item>
+        <item>72</item>
+        <item>73</item>
+        <item>74</item>
+        <item>75</item>
+        <item>76</item>
+        <item>77</item>
+        <item>78</item>
+        <item>79</item>
+      </classification>
+    </entry>
+  </data>
+</idl:IsrmResultDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_1.xml
similarity index 78%
copy from daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_1.xml
index 01f3fd0..c824daf 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_unparse_1.xml
@@ -16,13 +16,9 @@
   limitations under the License.
 -->
 
-<idl:CameraState xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>97</id>
-  <length>5</length>
-  <zoom>10</zoom>
-  <focus>10</focus>
-  <index>0</index>
-  <checksum>30149</checksum>
-</idl:CameraState>
+<idl:IsrmResultDecl xmlns:idl="urn:idl:1.0">
+  <tag>1</tag>
+  <data>
+    <end />
+  </data>
+</idl:IsrmResultDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.dfdl.xsd
new file mode 100644
index 0000000..4ffb8ac
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.dfdl.xsd
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="1" alignmentUnits="bytes" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%NUL;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bytes" occursCountKind [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="float" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:float"/>
+  </xs:simpleType>
+  <xs:simpleType name="double" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:double"/>
+  </xs:simpleType>
+  <xs:simpleType name="int8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="int32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:int"/>
+  </xs:simpleType>
+  <xs:simpleType name="int64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:long"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedLong"/>
+  </xs:simpleType>
+  <xs:simpleType name="boolean" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:boolean"/>
+  </xs:simpleType>
+  <xs:complexType name="IsrmRequest">
+    <xs:sequence>
+      <xs:element name="phase">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="80" maxOccurs="80" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="IsrmRequestDecl" type="idl:IsrmRequest"/>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.tdml
similarity index 56%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.tdml
index 3d12954..b4537cf 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.tdml
@@ -17,9 +17,11 @@
 -->
 
 <tdml:testSuite
+  defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
   defaultRoundTrip="none"
-  description="TDML tests for ex_nums"
+  defaultValidation="on"
+  description="TDML tests for ISRM_orange_to_green_60002"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,50 +39,26 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    name="ex_nums_parse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="ISRM_orange_to_green_60002.dfdl.xsd"
+    name="ISRM_orange_to_green_60002_parse"
+    root="IsrmRequestDecl">
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ISRM_orange_to_green_60002_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ISRM_orange_to_green_60002_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="ISRM_orange_to_green_60002.dfdl.xsd"
+    name="ISRM_orange_to_green_60002_unparse"
+    root="IsrmRequestDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ISRM_orange_to_green_60002_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
-    </tdml:document>
-  </tdml:unparserTestCase>
-
-  <tdml:parserTestCase
-    name="ex_nums_parse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
-    <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
-    </tdml:document>
-    <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
-    </tdml:infoset>
-  </tdml:parserTestCase>
-
-  <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
-    <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
-    </tdml:infoset>
-    <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ISRM_orange_to_green_60002_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_parse.dat
new file mode 100644
index 0000000..f82ef2b
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_parse.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_unparse.xml
new file mode 100644
index 0000000..3399c9a
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_unparse.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<idl:IsrmRequestDecl xmlns:idl="urn:idl:1.0">
+  <phase>
+    <item>0</item>
+    <item>1</item>
+    <item>2</item>
+    <item>3</item>
+    <item>4</item>
+    <item>5</item>
+    <item>6</item>
+    <item>7</item>
+    <item>8</item>
+    <item>9</item>
+    <item>10</item>
+    <item>11</item>
+    <item>12</item>
+    <item>13</item>
+    <item>14</item>
+    <item>15</item>
+    <item>16</item>
+    <item>17</item>
+    <item>18</item>
+    <item>19</item>
+    <item>20</item>
+    <item>21</item>
+    <item>22</item>
+    <item>23</item>
+    <item>24</item>
+    <item>25</item>
+    <item>26</item>
+    <item>27</item>
+    <item>28</item>
+    <item>29</item>
+    <item>30</item>
+    <item>31</item>
+    <item>32</item>
+    <item>33</item>
+    <item>34</item>
+    <item>35</item>
+    <item>36</item>
+    <item>37</item>
+    <item>38</item>
+    <item>39</item>
+    <item>40</item>
+    <item>41</item>
+    <item>42</item>
+    <item>43</item>
+    <item>44</item>
+    <item>45</item>
+    <item>46</item>
+    <item>47</item>
+    <item>48</item>
+    <item>49</item>
+    <item>50</item>
+    <item>51</item>
+    <item>52</item>
+    <item>53</item>
+    <item>54</item>
+    <item>55</item>
+    <item>56</item>
+    <item>57</item>
+    <item>58</item>
+    <item>59</item>
+    <item>60</item>
+    <item>61</item>
+    <item>62</item>
+    <item>63</item>
+    <item>64</item>
+    <item>65</item>
+    <item>66</item>
+    <item>67</item>
+    <item>68</item>
+    <item>69</item>
+    <item>70</item>
+    <item>71</item>
+    <item>72</item>
+    <item>73</item>
+    <item>74</item>
+    <item>75</item>
+    <item>76</item>
+    <item>77</item>
+    <item>78</item>
+    <item>79</item>
+  </phase>
+</idl:IsrmRequestDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.dfdl.xsd
new file mode 100644
index 0000000..fe03a94
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.dfdl.xsd
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="1" alignmentUnits="bytes" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%NUL;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bytes" occursCountKind [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="float" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:float"/>
+  </xs:simpleType>
+  <xs:simpleType name="double" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:double"/>
+  </xs:simpleType>
+  <xs:simpleType name="int8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="int32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:int"/>
+  </xs:simpleType>
+  <xs:simpleType name="int64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:long"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedLong"/>
+  </xs:simpleType>
+  <xs:simpleType name="boolean" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:boolean"/>
+  </xs:simpleType>
+  <xs:complexType name="ComponentReady">
+    <xs:sequence>
+      <xs:element name="name">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="80" maxOccurs="80" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="status" type="idl:boolean"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="ComponentReadyDecl" type="idl:ComponentReady"/>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.tdml
similarity index 56%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.tdml
index 3d12954..a7bab3e 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.tdml
@@ -17,9 +17,11 @@
 -->
 
 <tdml:testSuite
+  defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
   defaultRoundTrip="none"
-  description="TDML tests for ex_nums"
+  defaultValidation="on"
+  description="TDML tests for MPU_green_to_orange_60004"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,50 +39,26 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    name="ex_nums_parse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="MPU_green_to_orange_60004.dfdl.xsd"
+    name="MPU_green_to_orange_60004_parse"
+    root="ComponentReadyDecl">
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">MPU_green_to_orange_60004_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">MPU_green_to_orange_60004_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="MPU_green_to_orange_60004.dfdl.xsd"
+    name="MPU_green_to_orange_60004_unparse"
+    root="ComponentReadyDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">MPU_green_to_orange_60004_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
-    </tdml:document>
-  </tdml:unparserTestCase>
-
-  <tdml:parserTestCase
-    name="ex_nums_parse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
-    <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
-    </tdml:document>
-    <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
-    </tdml:infoset>
-  </tdml:parserTestCase>
-
-  <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
-    <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
-    </tdml:infoset>
-    <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">MPU_green_to_orange_60004_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_parse.dat
new file mode 100644
index 0000000..81c33f6
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_parse.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_unparse.xml
new file mode 100644
index 0000000..1f39771
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_unparse.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<idl:ComponentReadyDecl xmlns:idl="urn:idl:1.0">
+  <name>
+    <item>0</item>
+    <item>1</item>
+    <item>2</item>
+    <item>3</item>
+    <item>4</item>
+    <item>5</item>
+    <item>6</item>
+    <item>7</item>
+    <item>8</item>
+    <item>9</item>
+    <item>10</item>
+    <item>11</item>
+    <item>12</item>
+    <item>13</item>
+    <item>14</item>
+    <item>15</item>
+    <item>16</item>
+    <item>17</item>
+    <item>18</item>
+    <item>19</item>
+    <item>20</item>
+    <item>21</item>
+    <item>22</item>
+    <item>23</item>
+    <item>24</item>
+    <item>25</item>
+    <item>26</item>
+    <item>27</item>
+    <item>28</item>
+    <item>29</item>
+    <item>30</item>
+    <item>31</item>
+    <item>32</item>
+    <item>33</item>
+    <item>34</item>
+    <item>35</item>
+    <item>36</item>
+    <item>37</item>
+    <item>38</item>
+    <item>39</item>
+    <item>40</item>
+    <item>41</item>
+    <item>42</item>
+    <item>43</item>
+    <item>44</item>
+    <item>45</item>
+    <item>46</item>
+    <item>47</item>
+    <item>48</item>
+    <item>49</item>
+    <item>50</item>
+    <item>51</item>
+    <item>52</item>
+    <item>53</item>
+    <item>54</item>
+    <item>55</item>
+    <item>56</item>
+    <item>57</item>
+    <item>58</item>
+    <item>59</item>
+    <item>60</item>
+    <item>61</item>
+    <item>62</item>
+    <item>63</item>
+    <item>64</item>
+    <item>65</item>
+    <item>66</item>
+    <item>67</item>
+    <item>68</item>
+    <item>69</item>
+    <item>80</item>
+    <item>81</item>
+    <item>82</item>
+    <item>83</item>
+    <item>84</item>
+    <item>85</item>
+    <item>86</item>
+    <item>87</item>
+    <item>88</item>
+    <item>89</item>
+  </name>
+  <status>true</status>
+</idl:ComponentReadyDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.dfdl.xsd
new file mode 100644
index 0000000..441a5be
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.dfdl.xsd
@@ -0,0 +1,163 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="1" alignmentUnits="bytes" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%NUL;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bytes" occursCountKind [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="float" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:float"/>
+  </xs:simpleType>
+  <xs:simpleType name="double" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:double"/>
+  </xs:simpleType>
+  <xs:simpleType name="int8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="int32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:int"/>
+  </xs:simpleType>
+  <xs:simpleType name="int64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:long"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="2" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="4" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint64" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedLong"/>
+  </xs:simpleType>
+  <xs:simpleType name="boolean" dfdl:length="1" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:boolean"/>
+  </xs:simpleType>
+  <xs:complexType name="SystemReady">
+    <xs:sequence/>
+  </xs:complexType>
+  <xs:element name="SystemReadyDecl" type="idl:SystemReady"/>
+  <xs:complexType name="Action">
+    <xs:sequence>
+      <xs:element name="actionId">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="10" maxOccurs="10" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="actionTy">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="10" maxOccurs="10" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="waypoint">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="10" maxOccurs="10" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="ActionDecl" type="idl:Action"/>
+  <xs:complexType name="Waypoint">
+    <xs:sequence>
+      <xs:element name="id">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="10" maxOccurs="10" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="x" type="idl:double"/>
+      <xs:element name="y" type="idl:double"/>
+      <xs:element name="z" type="idl:double"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="WaypointDecl" type="idl:Waypoint"/>
+  <xs:complexType name="MissionPlan">
+    <xs:sequence>
+      <xs:element name="missionId">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="20" maxOccurs="20" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="sensorActions">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="action" minOccurs="2" maxOccurs="2" dfdl:occursCountKind="fixed" type="idl:Action"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="sensorPlanId">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="10" maxOccurs="10" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="vehiclePlanId">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="10" maxOccurs="10" dfdl:occursCountKind="fixed" type="idl:int8"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+      <xs:element name="waypoints">
+        <xs:complexType>
+          <xs:sequence>
+            <xs:element name="item" minOccurs="4" maxOccurs="4" dfdl:occursCountKind="fixed" type="idl:Waypoint"/>
+          </xs:sequence>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="MissionPlanDecl" type="idl:MissionPlan"/>
+  <xs:simpleType name="MpuRequestTag">
+    <xs:restriction base="idl:uint32"/>
+  </xs:simpleType>
+  <xs:complexType name="MpuRequest">
+    <xs:sequence>
+      <xs:element name="tag" type="idl:MpuRequestTag"/>
+      <xs:element name="data" dfdl:length="236" dfdl:lengthKind="explicit">
+        <xs:complexType>
+          <xs:choice dfdl:choiceDispatchKey="{xs:string(../tag)}">
+            <xs:element dfdl:choiceBranchKey="0" name="missionPlan" type="idl:MissionPlan"/>
+            <xs:element dfdl:choiceBranchKey="1" name="systemReady" type="idl:SystemReady"/>
+          </xs:choice>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="MpuRequestDecl" type="idl:MpuRequest"/>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.tdml
similarity index 59%
copy from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.tdml
index 3d12954..ae6376c 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.tdml
@@ -17,9 +17,11 @@
 -->
 
 <tdml:testSuite
+  defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
   defaultRoundTrip="none"
-  description="TDML tests for ex_nums"
+  defaultValidation="on"
+  description="TDML tests for MPU_orange_to_green_60006"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
@@ -37,50 +39,50 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    name="ex_nums_parse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="MPU_orange_to_green_60006.dfdl.xsd"
+    name="MPU_orange_to_green_60006_parse_0"
+    root="MpuRequestDecl">
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">MPU_orange_to_green_60006_parse_0.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">MPU_orange_to_green_60006_unparse_0.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime1"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime1">
+    model="MPU_orange_to_green_60006.dfdl.xsd"
+    name="MPU_orange_to_green_60006_unparse_0"
+    root="MpuRequestDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime1.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">MPU_orange_to_green_60006_unparse_0.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">MPU_orange_to_green_60006_parse_0.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    name="ex_nums_parse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
+    model="MPU_orange_to_green_60006.dfdl.xsd"
+    name="MPU_orange_to_green_60006_parse_1"
+    root="MpuRequestDecl">
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">MPU_orange_to_green_60006_parse_1.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">MPU_orange_to_green_60006_unparse_1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    name="ex_nums_unparse_runtime2"
-    model="ex_nums.dfdl.xsd"
-    config="config-runtime2">
+    model="MPU_orange_to_green_60006.dfdl.xsd"
+    name="MPU_orange_to_green_60006_unparse_1"
+    root="MpuRequestDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_nums_unparse_runtime2.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">MPU_orange_to_green_60006_unparse_1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">MPU_orange_to_green_60006_parse_1.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_0.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_0.dat
new file mode 100644
index 0000000..5d314b7
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_0.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_1.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_1.dat
new file mode 100644
index 0000000..07a1626
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_1.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_unparse_0.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_unparse_0.xml
new file mode 100644
index 0000000..eee1745
--- /dev/null
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_unparse_0.xml
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<idl:MpuRequestDecl xmlns:idl="urn:idl:1.0">
+  <tag>0</tag>
+  <data>
+    <missionPlan>
+      <missionId>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+        <item>6</item>
+        <item>7</item>
+        <item>8</item>
+        <item>9</item>
+        <item>10</item>
+        <item>11</item>
+        <item>12</item>
+        <item>13</item>
+        <item>14</item>
+        <item>15</item>
+        <item>16</item>
+        <item>17</item>
+        <item>18</item>
+        <item>19</item>
+        <item>20</item>
+      </missionId>
+      <sensorActions>
+        <action>
+          <actionId>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </actionId>
+          <actionTy>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </actionTy>
+          <waypoint>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </waypoint>
+        </action>
+        <action>
+          <actionId>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </actionId>
+          <actionTy>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </actionTy>
+          <waypoint>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </waypoint>
+        </action>
+      </sensorActions>
+      <sensorPlanId>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+        <item>6</item>
+        <item>7</item>
+        <item>8</item>
+        <item>9</item>
+        <item>10</item>
+      </sensorPlanId>
+      <vehiclePlanId>
+        <item>1</item>
+        <item>2</item>
+        <item>3</item>
+        <item>4</item>
+        <item>5</item>
+        <item>6</item>
+        <item>7</item>
+        <item>8</item>
+        <item>9</item>
+        <item>10</item>
+      </vehiclePlanId>
+      <waypoints>
+        <item>
+          <id>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </id>
+          <x>111.5</x>
+          <y>112.5</y>
+          <z>113.5</z>
+        </item>
+        <item>
+          <id>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </id>
+          <x>121.5</x>
+          <y>122.5</y>
+          <z>123.5</z>
+        </item>
+        <item>
+          <id>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </id>
+          <x>131.5</x>
+          <y>132.5</y>
+          <z>133.5</z>
+        </item>
+        <item>
+          <id>
+            <item>1</item>
+            <item>2</item>
+            <item>3</item>
+            <item>4</item>
+            <item>5</item>
+            <item>6</item>
+            <item>7</item>
+            <item>8</item>
+            <item>9</item>
+            <item>10</item>
+          </id>
+          <x>141.5</x>
+          <y>142.5</y>
+          <z>143.5</z>
+        </item>
+      </waypoints>
+    </missionPlan>
+  </data>
+</idl:MpuRequestDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_unparse_1.xml
similarity index 78%
copy from daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_unparse_1.xml
index 01f3fd0..116d33b 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_unparse_1.xml
@@ -16,13 +16,9 @@
   limitations under the License.
 -->
 
-<idl:CameraState xmlns:idl="urn:idl:1.0">
-  <sync0>208</sync0>
-  <sync1>13</sync1>
-  <id>97</id>
-  <length>5</length>
-  <zoom>10</zoom>
-  <focus>10</focus>
-  <index>0</index>
-  <checksum>30149</checksum>
-</idl:CameraState>
+<idl:MpuRequestDecl xmlns:idl="urn:idl:1.0">
+  <tag>1</tag>
+  <data>
+    <systemReady />
+  </data>
+</idl:MpuRequestDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_parse.dat
new file mode 100644
index 0000000..d58021f
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_parse.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_unparse.xml
similarity index 68%
copy from daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_unparse.xml
index 01f3fd0..ed5647d 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_unparse.xml
@@ -16,13 +16,21 @@
   limitations under the License.
 -->
 
-<idl:CameraState xmlns:idl="urn:idl:1.0">
+<idl:AptinaSettingsDecl xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
-  <id>97</id>
-  <length>5</length>
-  <zoom>10</zoom>
-  <focus>10</focus>
+  <id>104</id>
+  <length>15</length>
   <index>0</index>
-  <checksum>30149</checksum>
-</idl:CameraState>
+  <minExposure>515</minExposure>
+  <maxExposure>1055</maxExposure>
+  <minGain>36</minGain>
+  <maxGain>864</maxGain>
+  <brightness>1</brightness>
+  <contrast>2</contrast>
+  <saturation>3</saturation>
+  <sharpness>5</sharpness>
+  <debugEnable>0</debugEnable>
+  <hue>6</hue>
+  <checksum>464</checksum>
+</idl:AptinaSettingsDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
index 01f3fd0..dd78cb8 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
@@ -16,7 +16,7 @@
   limitations under the License.
 -->
 
-<idl:CameraState xmlns:idl="urn:idl:1.0">
+<idl:CameraStateDecl xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
   <id>97</id>
@@ -25,4 +25,4 @@
   <focus>10</focus>
   <index>0</index>
   <checksum>30149</checksum>
-</idl:CameraState>
+</idl:CameraStateDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
index 9a1d4a1..6aec4ad 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
@@ -16,7 +16,7 @@
   limitations under the License.
 -->
 
-<idl:Command xmlns:idl="urn:idl:1.0">
+<idl:CommandDecl xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
   <id>1</id>
@@ -27,4 +27,4 @@
   <stabilized>0</stabilized>
   <impulse>0</impulse>
   <checksum>30149</checksum>
-</idl:Command>
+</idl:CommandDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_parse.dat b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_parse.dat
new file mode 100644
index 0000000..b007dd0
Binary files /dev/null and b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_parse.dat differ
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_unparse.xml
similarity index 82%
copy from daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
copy to daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_unparse.xml
index 01f3fd0..7fe7fe0 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_unparse.xml
@@ -16,13 +16,10 @@
   limitations under the License.
 -->
 
-<idl:CameraState xmlns:idl="urn:idl:1.0">
+<idl:LimitsDecl xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
-  <id>97</id>
-  <length>5</length>
-  <zoom>10</zoom>
-  <focus>10</focus>
-  <index>0</index>
-  <checksum>30149</checksum>
-</idl:CameraState>
+  <id>34</id>
+  <length>0</length>
+  <checksum>255</checksum>
+</idl:LimitsDecl>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
index 4034d39..d4569ed 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
@@ -40,7 +40,7 @@
   <xs:simpleType name="uint32" dfdl:length="32" dfdl:lengthKind="explicit">
     <xs:restriction base="xs:unsignedInt"/>
   </xs:simpleType>
-  <xs:complexType name="CommandType">
+  <xs:complexType name="Command">
     <xs:sequence>
       <xs:element name="sync0" fixed="208" type="idl:uint8"/>
       <xs:element name="sync1" fixed="13" type="idl:uint8"/>
@@ -61,8 +61,8 @@
       <xs:element name="checksum" type="idl:uint16"/>
     </xs:sequence>
   </xs:complexType>
-  <xs:element name="Command" type="idl:CommandType"/>
-  <xs:complexType name="CameraStateType">
+  <xs:element name="CommandDecl" type="idl:Command"/>
+  <xs:complexType name="CameraState">
     <xs:sequence>
       <xs:element name="sync0" fixed="208" type="idl:uint8"/>
       <xs:element name="sync1" fixed="13" type="idl:uint8"/>
@@ -74,8 +74,8 @@
       <xs:element name="checksum" type="idl:uint16"/>
     </xs:sequence>
   </xs:complexType>
-  <xs:element name="CameraState" type="idl:CameraStateType"/>
-  <xs:complexType name="VideoSettingsType">
+  <xs:element name="CameraStateDecl" type="idl:CameraState"/>
+  <xs:complexType name="VideoSettings">
     <xs:sequence>
       <xs:element name="sync0" fixed="208" type="idl:uint8"/>
       <xs:element name="sync1" fixed="13" type="idl:uint8"/>
@@ -97,5 +97,36 @@
       <xs:element name="checksum" type="idl:uint16"/>
     </xs:sequence>
   </xs:complexType>
-  <xs:element name="VideoSettings" type="idl:VideoSettingsType"/>
+  <xs:element name="VideoSettingsDecl" type="idl:VideoSettings"/>
+  <xs:complexType name="AptinaSettings">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="104" type="idl:uint8"/>
+      <xs:element name="length" fixed="15" type="idl:uint8"/>
+      <xs:element name="index" fixed="0" type="idl:uint8"/>
+      <xs:element name="minExposure" type="idl:uint16"/>
+      <xs:element name="maxExposure" type="idl:uint16"/>
+      <xs:element name="minGain" type="idl:uint16"/>
+      <xs:element name="maxGain" type="idl:uint16"/>
+      <xs:element name="brightness" type="idl:int8"/>
+      <xs:element name="contrast" type="idl:int8"/>
+      <xs:element name="saturation" type="idl:int8"/>
+      <xs:element name="sharpness" type="idl:uint8"/>
+      <xs:element name="debugEnable" type="idl:uint8"/>
+      <xs:element name="hue" type="idl:int8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="AptinaSettingsDecl" type="idl:AptinaSettings"/>
+  <xs:complexType name="Limits">
+    <xs:sequence>
+      <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+      <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+      <xs:element name="id" fixed="34" type="idl:uint8"/>
+      <xs:element name="length" fixed="0" type="idl:uint8"/>
+      <xs:element name="checksum" type="idl:uint16"/>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:element name="LimitsDecl" type="idl:Limits"/>
 </xs:schema>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
index 4b44391..e9c30e2 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
@@ -20,6 +20,7 @@
   defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
   defaultRoundTrip="none"
+  defaultValidation="on"
   description="TDML tests for orion-command"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
@@ -38,62 +39,57 @@
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    description="orion-command CameraState parse test"
     model="orion-command.dfdl.xsd"
-    name="camera_state_parse"
-    root="CameraState">
+    name="command_parse"
+    root="CommandDecl">
     <tdml:document>
-      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="orion-command CameraState unparse test"
     model="orion-command.dfdl.xsd"
-    name="camera_state_unparse"
-    root="CameraState">
+    name="command_unparse"
+    root="CommandDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    description="orion-command Command parse test"
     model="orion-command.dfdl.xsd"
-    name="command_parse"
-    root="Command">
+    name="camera_state_parse"
+    root="CameraStateDecl">
     <tdml:document>
-      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="orion-command Command unparse test"
     model="orion-command.dfdl.xsd"
-    name="command_unparse"
-    root="Command">
+    name="camera_state_unparse"
+    root="CameraStateDecl">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">camera_state_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">camera_state_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    description="orion-command VideoSettings parse test"
     model="orion-command.dfdl.xsd"
     name="video_settings_parse"
-    root="VideoSettings">
+    root="VideoSettingsDecl">
     <tdml:document>
       <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
     </tdml:document>
@@ -103,10 +99,9 @@
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="orion-command VideoSettings unparse test"
     model="orion-command.dfdl.xsd"
     name="video_settings_unparse"
-    root="VideoSettings">
+    root="VideoSettingsDecl">
     <tdml:infoset>
       <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
@@ -115,4 +110,52 @@
     </tdml:document>
   </tdml:unparserTestCase>
 
+  <tdml:parserTestCase
+    model="orion-command.dfdl.xsd"
+    name="aptina_settings_parse"
+    root="AptinaSettingsDecl">
+    <tdml:document>
+      <tdml:documentPart type="file">aptina_settings_parse.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">aptina_settings_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    model="orion-command.dfdl.xsd"
+    name="aptina_settings_unparse"
+    root="AptinaSettingsDecl">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">aptina_settings_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">aptina_settings_parse.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    model="orion-command.dfdl.xsd"
+    name="limits_parse"
+    root="LimitsDecl">
+    <tdml:document>
+      <tdml:documentPart type="file">limits_parse.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">limits_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    model="orion-command.dfdl.xsd"
+    name="limits_unparse"
+    root="LimitsDecl">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">limits_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">limits_parse.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
 </tdml:testSuite>
diff --git a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
index 0307283..f23d999 100644
--- a/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
+++ b/daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
@@ -16,7 +16,7 @@
   limitations under the License.
 -->
 
-<idl:VideoSettings xmlns:idl="urn:idl:1.0">
+<idl:VideoSettingsDecl xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
   <sync1>13</sync1>
   <id>98</id>
@@ -34,4 +34,4 @@
   <mjpegQuality>0</mjpegQuality>
   <saveSettingsAndTsPacketCount>0</saveSettingsAndTsPacketCount>
   <checksum>3073</checksum>
-</idl:VideoSettings>
+</idl:VideoSettingsDecl>
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
index ba5a060..a52caed 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
@@ -35,4 +35,5 @@ class TestExNums {
   @Test def test_ex_nums_unparse_runtime1(): Unit = { runner.runOneTest("ex_nums_unparse_runtime1") }
   @Test def test_ex_nums_parse_runtime2(): Unit = { runner.runOneTest("ex_nums_parse_runtime2") }
   @Test def test_ex_nums_unparse_runtime2(): Unit = { runner.runOneTest("ex_nums_unparse_runtime2") }
+  @Test def test_ex_nums_unparse_errors(): Unit = { runner.runOneTest("ex_nums_unparse_errors") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIsrmGreenToOrange60000.scala
similarity index 56%
copy from daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
copy to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIsrmGreenToOrange60000.scala
index 9cf4546..ba12f18 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIsrmGreenToOrange60000.scala
@@ -1,7 +1,7 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
+ * this work for additional information ringarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
@@ -17,24 +17,22 @@
 
 package org.apache.daffodil.runtime2
 
-import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
+import org.junit.Test
 
-object TestOrionCommand {
+object TestIsrmGreenToOrange60000 {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "orion-command.tdml")
+  val runner = Runner(testDir, "ISRM_green_to_orange_60000.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestOrionCommand {
-  import TestOrionCommand._
+class TestIsrmGreenToOrange60000 {
+  import TestIsrmGreenToOrange60000._
 
-  @Test def test_camera_state_parse(): Unit = { runner.runOneTest("camera_state_parse") }
-  @Test def test_camera_state_unparse(): Unit = { runner.runOneTest("camera_state_unparse") }
-  @Test def test_command_parse(): Unit = { runner.runOneTest("command_parse") }
-  @Test def test_command_unparse(): Unit = { runner.runOneTest("command_unparse") }
-  @Test def test_video_settings_parse(): Unit = { runner.runOneTest("video_settings_parse") }
-  @Test def test_video_settings_unparse(): Unit = { runner.runOneTest("video_settings_unparse") }
+  @Test def test_ISRM_green_to_orange_60000_parse_0(): Unit = { runner.runOneTest("ISRM_green_to_orange_60000_parse_0") }
+  @Test def test_ISRM_green_to_orange_60000_unparse_0(): Unit = { runner.runOneTest("ISRM_green_to_orange_60000_unparse_0") }
+  @Test def test_ISRM_green_to_orange_60000_parse_1(): Unit = { runner.runOneTest("ISRM_green_to_orange_60000_parse_1") }
+  @Test def test_ISRM_green_to_orange_60000_unparse_1(): Unit = { runner.runOneTest("ISRM_green_to_orange_60000_unparse_1") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIsrmOrangeToGreen60002.scala
similarity index 62%
copy from daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
copy to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIsrmOrangeToGreen60002.scala
index ba5a060..752834d 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestIsrmOrangeToGreen60002.scala
@@ -1,7 +1,7 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
+ * this work for additional information ringarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
@@ -17,22 +17,20 @@
 
 package org.apache.daffodil.runtime2
 
-import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
+import org.junit.Test
 
-object TestExNums {
+object TestIsrmOrangeToGreen60002 {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "ex_nums.tdml")
+  val runner = Runner(testDir, "ISRM_orange_to_green_60002.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestExNums {
-  import TestExNums._
+class TestIsrmOrangeToGreen60002 {
+  import TestIsrmOrangeToGreen60002._
 
-  @Test def test_ex_nums_parse_runtime1(): Unit = { runner.runOneTest("ex_nums_parse_runtime1") }
-  @Test def test_ex_nums_unparse_runtime1(): Unit = { runner.runOneTest("ex_nums_unparse_runtime1") }
-  @Test def test_ex_nums_parse_runtime2(): Unit = { runner.runOneTest("ex_nums_parse_runtime2") }
-  @Test def test_ex_nums_unparse_runtime2(): Unit = { runner.runOneTest("ex_nums_unparse_runtime2") }
+  @Test def test_ISRM_orange_to_green_60002_parse(): Unit = { runner.runOneTest("ISRM_orange_to_green_60002_parse") }
+  @Test def test_ISRM_orange_to_green_60002_unparse(): Unit = { runner.runOneTest("ISRM_orange_to_green_60002_unparse") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestMpuGreenToOrange60004.scala
similarity index 62%
copy from daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
copy to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestMpuGreenToOrange60004.scala
index ba5a060..49a716b 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestMpuGreenToOrange60004.scala
@@ -1,7 +1,7 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
+ * this work for additional information ringarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
@@ -17,22 +17,20 @@
 
 package org.apache.daffodil.runtime2
 
-import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
+import org.junit.Test
 
-object TestExNums {
+object TestMpuGreenToOrange60004 {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "ex_nums.tdml")
+  val runner = Runner(testDir, "MPU_green_to_orange_60004.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestExNums {
-  import TestExNums._
+class TestMpuGreenToOrange60004 {
+  import TestMpuGreenToOrange60004._
 
-  @Test def test_ex_nums_parse_runtime1(): Unit = { runner.runOneTest("ex_nums_parse_runtime1") }
-  @Test def test_ex_nums_unparse_runtime1(): Unit = { runner.runOneTest("ex_nums_unparse_runtime1") }
-  @Test def test_ex_nums_parse_runtime2(): Unit = { runner.runOneTest("ex_nums_parse_runtime2") }
-  @Test def test_ex_nums_unparse_runtime2(): Unit = { runner.runOneTest("ex_nums_unparse_runtime2") }
+  @Test def test_MPU_green_to_orange_60004_parse(): Unit = { runner.runOneTest("MPU_green_to_orange_60004_parse") }
+  @Test def test_MPU_green_to_orange_60004_unparse(): Unit = { runner.runOneTest("MPU_green_to_orange_60004_unparse") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestMpuOrangeToGreen60006.scala
similarity index 57%
copy from daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
copy to daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestMpuOrangeToGreen60006.scala
index ba5a060..56c67b0 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestExNums.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestMpuOrangeToGreen60006.scala
@@ -1,7 +1,7 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
+ * this work for additional information ringarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
@@ -17,22 +17,22 @@
 
 package org.apache.daffodil.runtime2
 
-import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
+import org.junit.Test
 
-object TestExNums {
+object TestMpuOrangeToGreen60006 {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "ex_nums.tdml")
+  val runner = Runner(testDir, "MPU_orange_to_green_60006.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestExNums {
-  import TestExNums._
+class TestMpuOrangeToGreen60006 {
+  import TestMpuOrangeToGreen60006._
 
-  @Test def test_ex_nums_parse_runtime1(): Unit = { runner.runOneTest("ex_nums_parse_runtime1") }
-  @Test def test_ex_nums_unparse_runtime1(): Unit = { runner.runOneTest("ex_nums_unparse_runtime1") }
-  @Test def test_ex_nums_parse_runtime2(): Unit = { runner.runOneTest("ex_nums_parse_runtime2") }
-  @Test def test_ex_nums_unparse_runtime2(): Unit = { runner.runOneTest("ex_nums_unparse_runtime2") }
+  @Test def test_MPU_orange_to_green_60006_parse_0(): Unit = { runner.runOneTest("MPU_orange_to_green_60006_parse_0") }
+  @Test def test_MPU_orange_to_green_60006_unparse_0(): Unit = { runner.runOneTest("MPU_orange_to_green_60006_unparse_0") }
+  @Test def test_MPU_orange_to_green_60006_parse_1(): Unit = { runner.runOneTest("MPU_orange_to_green_60006_parse_1") }
+  @Test def test_MPU_orange_to_green_60006_unparse_1(): Unit = { runner.runOneTest("MPU_orange_to_green_60006_unparse_1") }
 }
diff --git a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
index 9cf4546..b5d3f92 100644
--- a/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
+++ b/daffodil-test/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
@@ -31,10 +31,14 @@ object TestOrionCommand {
 class TestOrionCommand {
   import TestOrionCommand._
 
-  @Test def test_camera_state_parse(): Unit = { runner.runOneTest("camera_state_parse") }
-  @Test def test_camera_state_unparse(): Unit = { runner.runOneTest("camera_state_unparse") }
   @Test def test_command_parse(): Unit = { runner.runOneTest("command_parse") }
   @Test def test_command_unparse(): Unit = { runner.runOneTest("command_unparse") }
+  @Test def test_camera_state_parse(): Unit = { runner.runOneTest("camera_state_parse") }
+  @Test def test_camera_state_unparse(): Unit = { runner.runOneTest("camera_state_unparse") }
   @Test def test_video_settings_parse(): Unit = { runner.runOneTest("video_settings_parse") }
   @Test def test_video_settings_unparse(): Unit = { runner.runOneTest("video_settings_unparse") }
+  @Test def test_aptina_settings_parse(): Unit = { runner.runOneTest("aptina_settings_parse") }
+  @Test def test_aptina_settings_unparse(): Unit = { runner.runOneTest("aptina_settings_unparse") }
+  @Test def test_limits_parse(): Unit = { runner.runOneTest("limits_parse") }
+  @Test def test_limits_unparse(): Unit = { runner.runOneTest("limits_unparse") }
 }
diff --git a/project/Rat.scala b/project/Rat.scala
index 4c88ef5..0e28845 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -124,6 +124,13 @@ object Rat {
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_0.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000_parse_1.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002_parse.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004_parse.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_0.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006_parse_1.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/aptina_settings_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/camera_state_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.dfdl"),
@@ -144,6 +151,7 @@ object Rat {
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_114.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_115.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw_parse_116.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/limits_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file.txt"),
     file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file2.txt"),

[daffodil] 02/09: Reorganize C source files

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit daa4f46475bbf112b68dbb2d2c0bb4aecb64d088
Author: John Interrante <in...@research.ge.com>
AuthorDate: Sun Dec 6 20:39:38 2020 -0500

    Reorganize C source files
    
    As requested on the dev list, reoganize C source files into two
    distinct groups.  Separate these groups from each other by moving them
    into two subdirectories, "c/libcli" and "c/libruntime".
    
    In build.sbt, ensure C compiler test-builds these subdirectories by
    doing a recursive glob on "c" and "examples".
    
    In TestCLIGenerateC.scala, update tests to keep them passing (some
    tests were checking the location and existence of the
    "generated_code.c" file).
    
    In resources/c, move the C source files into libcli and libruntime.
    
    In CodeGenerator.scala, make CodeGenerator write generated_code.[ch]
    into libruntime, find C source files in any subdirectory, and compile
    them with two include flags (one for each subdirectory).
    
    In TestCodeGenerator.scala, make all tests remove temporary output dir
    after using it, and update tests to keep them passing (some tests were
    checking the location and existence of the "generated_code.c" file).
---
 build.sbt                                          |  7 ++--
 .../daffodil/generating/TestCLIGenerateC.scala     | 24 +++++++-----
 .../main/resources/c/{ => libcli}/daffodil_argp.c  |  0
 .../main/resources/c/{ => libcli}/daffodil_argp.h  |  0
 .../main/resources/c/{ => libcli}/daffodil_main.c  |  0
 .../src/main/resources/c/{ => libcli}/stack.c      |  0
 .../src/main/resources/c/{ => libcli}/stack.h      |  0
 .../src/main/resources/c/{ => libcli}/xml_reader.c |  0
 .../src/main/resources/c/{ => libcli}/xml_reader.h |  0
 .../src/main/resources/c/{ => libcli}/xml_writer.c |  0
 .../src/main/resources/c/{ => libcli}/xml_writer.h |  0
 .../main/resources/c/{ => libruntime}/infoset.c    |  0
 .../main/resources/c/{ => libruntime}/infoset.h    |  0
 .../apache/daffodil/runtime2/CodeGenerator.scala   |  9 +++--
 .../daffodil/runtime2/TestCodeGenerator.scala      | 44 +++++++++++-----------
 15 files changed, 45 insertions(+), 39 deletions(-)

diff --git a/build.sbt b/build.sbt
index ed2beb0..489682b 100644
--- a/build.sbt
+++ b/build.sbt
@@ -71,13 +71,14 @@ lazy val runtime2         = Project("daffodil-runtime2", file("daffodil-runtime2
                                 Compile / ccTargets := ListSet(runtime2CFiles),
                                 Compile / cSources  := Map(
                                   runtime2CFiles -> (
-                                    ((Compile / resourceDirectory).value / "c" * GlobFilter("*.c")).get() ++
-                                    ((Compile / resourceDirectory).value / "examples" * GlobFilter("*.c")).get()
+                                    ((Compile / resourceDirectory).value / "c" ** GlobFilter("*.c")).get() ++
+                                    ((Compile / resourceDirectory).value / "examples" ** GlobFilter("*.c")).get()
                                   )
                                 ),
                                 Compile / cIncludeDirectories := Map(
                                   runtime2CFiles -> Seq(
-                                    (Compile / resourceDirectory).value / "c",
+                                    (Compile / resourceDirectory).value / "c" / "libcli",
+                                    (Compile / resourceDirectory).value / "c" / "libruntime",
                                     (Compile / resourceDirectory).value / "examples"
                                   )
                                 ),
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
index 9b5c9b3..f4e5cdc 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -17,22 +17,26 @@
 
 package org.apache.daffodil.generating
 
-import org.junit.Test
-import org.junit.Before
-import org.junit.After
-import org.apache.daffodil.CLI.Util
 import net.sf.expectit.matcher.Matchers.contains
 import net.sf.expectit.matcher.Matchers.eof
+import org.apache.daffodil.CLI.Util
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
 
+/**
+ * Checks that we can run the "daffodil generate c" subcommand with
+ * various options and get expected outputs.
+ */
 class TestCLIGenerateC {
 
   val daffodil: String = Util.binPath
-  val outputDir: os.Path = os.pwd/"generate_tmp"
+  var outputDir: os.Path = _
   lazy val schemaFile: String = if (Util.isWindows) Util.cmdConvert(sf) else sf
   val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd")
 
   @Before def before(): Unit = {
-    os.remove.all(outputDir)
+    outputDir = os.temp.dir()
   }
 
   @After def after(): Unit = {
@@ -52,7 +56,7 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"generated_code.c"))
+    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_CLI_Generate_noC_error(): Unit = {
@@ -130,7 +134,7 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"generated_code.c"))
+    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_CLI_Generate_root(): Unit = {
@@ -146,7 +150,7 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"generated_code.c"))
+    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_CLI_Generate_root_error(): Unit = {
@@ -193,6 +197,6 @@ class TestCLIGenerateC {
       shell.close()
     }
 
-    assert(os.exists(outputDir/"c"/"generated_code.c"))
+    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
   }
 }
diff --git a/daffodil-runtime2/src/main/resources/c/daffodil_argp.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/daffodil_argp.c
rename to daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
diff --git a/daffodil-runtime2/src/main/resources/c/daffodil_argp.h b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.h
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/daffodil_argp.h
rename to daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.h
diff --git a/daffodil-runtime2/src/main/resources/c/daffodil_main.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/daffodil_main.c
rename to daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
diff --git a/daffodil-runtime2/src/main/resources/c/stack.c b/daffodil-runtime2/src/main/resources/c/libcli/stack.c
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/stack.c
rename to daffodil-runtime2/src/main/resources/c/libcli/stack.c
diff --git a/daffodil-runtime2/src/main/resources/c/stack.h b/daffodil-runtime2/src/main/resources/c/libcli/stack.h
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/stack.h
rename to daffodil-runtime2/src/main/resources/c/libcli/stack.h
diff --git a/daffodil-runtime2/src/main/resources/c/xml_reader.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/xml_reader.c
rename to daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
diff --git a/daffodil-runtime2/src/main/resources/c/xml_reader.h b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.h
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/xml_reader.h
rename to daffodil-runtime2/src/main/resources/c/libcli/xml_reader.h
diff --git a/daffodil-runtime2/src/main/resources/c/xml_writer.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/xml_writer.c
rename to daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
diff --git a/daffodil-runtime2/src/main/resources/c/xml_writer.h b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.h
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/xml_writer.h
rename to daffodil-runtime2/src/main/resources/c/libcli/xml_writer.h
diff --git a/daffodil-runtime2/src/main/resources/c/infoset.c b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/infoset.c
rename to daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
diff --git a/daffodil-runtime2/src/main/resources/c/infoset.h b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
similarity index 100%
rename from daffodil-runtime2/src/main/resources/c/infoset.h
rename to daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
index 6dcc19d..4f2a776 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
@@ -77,8 +77,8 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     val codeFileText = codeGeneratorState.generateCodeFile(rootElementName)
 
     // Write the generated C code into our code subdirectory
-    val generatedCodeHeader = codeDir/"generated_code.h"
-    val generatedCodeFile = codeDir/"generated_code.c"
+    val generatedCodeHeader = codeDir/"libruntime"/"generated_code.h"
+    val generatedCodeFile = codeDir/"libruntime"/"generated_code.c"
     os.write(generatedCodeHeader, codeHeaderText)
     os.write(generatedCodeFile, codeFileText)
 
@@ -96,7 +96,7 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     try {
       // Assemble the compiler's command line arguments
       val compiler = pickCompiler
-      val files = os.list(codeDir).filter(_.ext == "c")
+      val files = os.walk(codeDir).filter(_.ext == "c")
       val libs = Seq("-lmxml", if (isWindows) "-largp" else "-lpthread")
 
       // Call the compiler if it was found.  We run the compiler in the output directory,
@@ -105,7 +105,8 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
       // We can't let "zig_cache" be put into "c" because we always remove and re-generate
       // everything in "c" from scratch.
       if (compiler.nonEmpty) {
-        val result = os.proc(compiler, "-I", codeDir, files, libs, "-o", exe).call(cwd = outputDir, stderr = os.Pipe)
+        val result = os.proc(compiler, "-I", codeDir/"libcli", "-I", codeDir/"libruntime",
+          files, libs, "-o", exe).call(cwd = outputDir, stderr = os.Pipe)
 
         // Report any compiler output as a warning
         if (result.out.text.nonEmpty || result.err.text.nonEmpty) {
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
index 19d5682..f64d6b9 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
@@ -20,24 +20,36 @@ package org.apache.daffodil.runtime2
 import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
 import java.nio.channels.Channels
-
 import org.apache.daffodil.Implicits.intercept
 import org.apache.daffodil.compiler.Compiler
 import org.apache.daffodil.util.Misc
 import org.apache.daffodil.util.SchemaUtils
 import org.apache.daffodil.util.TestUtils
+import org.junit.After
 import org.junit.Assert.assertArrayEquals
+import org.junit.Before
 import org.junit.Test
 
 /**
  * Checks that we can create a [[CodeGenerator]] and call its methods.
  * The value of this test is to debug the call path from [[Compiler]]
- * to [[CodeGenerator]] for one very simple DFDL schema.  Running TDML
- * tests with daffodil-runtime2 is a more effective way to test the
- * functionality of CodeGenerator's generated code for as many DFDL
- * schemas as you could want.
+ * to [[CodeGenerator]] for a single test DFDL schema.  Running TDML
+ * tests with daffodil-runtime2 is a more effective way to check that
+ * CodeGenerator can generate appropriate code for as many DFDL schemas
+ * as you could want.
  */
 class TestCodeGenerator {
+  // Ensure all tests remove outputDir after using it
+  var outputDir: os.Path = _
+
+  @Before def before(): Unit = {
+    outputDir = os.temp.dir()
+  }
+
+  @After def after(): Unit = {
+    os.remove.all(outputDir)
+  }
+
   // Define a simple DFDL test schema for debugging our code path
   private val testSchema = SchemaUtils.dfdlTestSchema(
       <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
@@ -78,35 +90,29 @@ class TestCodeGenerator {
     val cg = pf.forLanguage("c")
 
     // Generate code from the test schema successfully
-    val outputDir = cg.generateCode(None, "./generateCode_tmp")
+    val outputDir = cg.generateCode(None, s"${this.outputDir}")
     assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
     assert(os.exists(outputDir))
-    assert(os.exists(outputDir/"c"/"generated_code.c"))
-
-    // Remove the generated code
-    os.remove.all(outputDir)
+    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_compileCode_success(): Unit = {
     // Create a CodeGenerator and generate code from the test schema
     val pf = Compiler().compileNode(testSchema)
     val cg = pf.forLanguage("c")
-    val outputDir = cg.generateCode(None, "./compileCode_tmp")
+    val outputDir = cg.generateCode(None, s"${this.outputDir}")
 
     // Compile the generated code into an executable successfully
     val executable = cg.compileCode(outputDir)
     assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
     assert(os.exists(executable))
-
-    // Remove the generated code
-    os.remove.all(outputDir)
   }
 
   @Test def test_parse_success(): Unit = {
     // Compile the test schema into a C executable
     val pf = Compiler().compileNode(testSchema)
     val cg = pf.forLanguage("c")
-    val outputDir = cg.generateCode(None, "./parse_tmp")
+    val outputDir = cg.generateCode(None, s"${this.outputDir}")
     val executable = cg.compileCode(outputDir)
 
     // Create a Runtime2DataProcessor and parse a binary int32 number successfully
@@ -117,16 +123,13 @@ class TestCodeGenerator {
     assert(!pr.isError && pf.getDiagnostics.isEmpty, pr.getDiagnostics.map(_.getMessage()).mkString("\n"))
     val expected = <e1><x>5</x></e1>
     TestUtils.assertEqualsXMLElements(expected, pr.infosetAsXML)
-
-    // Remove the generated code
-    os.remove.all(outputDir)
   }
 
   @Test def test_unparse_success(): Unit = {
     // Compile the test schema into a C executable
     val pf = Compiler().compileNode(testSchema)
     val cg = pf.forLanguage("c")
-    val outputDir = cg.generateCode(None, "./unparse_tmp")
+    val outputDir = cg.generateCode(None, s"${this.outputDir}")
     val executable = cg.compileCode(outputDir)
 
     // Create a Runtime2DataProcessor and unparse a binary int32 number successfully
@@ -137,8 +140,5 @@ class TestCodeGenerator {
     assert(!pr.isError && pf.getDiagnostics.isEmpty, pr.getDiagnostics.map(_.getMessage()).mkString("\n"))
     val expected = Misc.hex2Bytes("00000005")
     assertArrayEquals(expected, output.toByteArray)
-
-    // Remove the generated code
-    os.remove.all(outputDir)
   }
 }

[daffodil] 08/09: Fix compilation errors after rebase

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 57b3c89bbf3ca4f0f16334bfe185f7f5e1089cc6
Author: John Interrante <in...@research.ge.com>
AuthorDate: Sat Mar 27 11:09:21 2021 -0400

    Fix compilation errors after rebase
    
    Rebase runtime2-2202 on latest commits from asf/master.  Fix
    compilation errors in Main.c due to changes in scallop API.  Fix
    compilation errors in DataProcessor.scala due to rebase conflicts.
---
 daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala   | 12 +++++-------
 .../scala/org/apache/daffodil/processors/DataProcessor.scala |  3 +--
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
index 75a0a0c..3891195 100644
--- a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
+++ b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
@@ -502,7 +502,7 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments)
   }
 
   // Generate Subcommand Options
-  val generate = new scallop.Subcommand("generate") {
+  object generate extends scallop.Subcommand("generate") {
     descr("generate <language> code from a DFDL schema")
 
     banner("""|Usage: daffodil [GLOBAL_OPTS] generate <language> [SUBCOMMAND_OPTS]
@@ -511,7 +511,7 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments)
     footer("""|
               |Run 'daffodil generate <language> --help' for subcommand specific options""".stripMargin)
 
-    val c = new scallop.Subcommand("c") {
+    object c extends scallop.Subcommand("c") {
       banner("""|Usage: daffodil generate c -s <schema> [-r [{namespace}]<root>]
                 |                           [-c <file>] [outputDir]
                 |
@@ -526,13 +526,11 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments)
       val schema = opt[URI]("schema", required = true, argName = "file", descr = "the annotated DFDL schema to use to generate source code.")
       val rootNS = opt[RefQName]("root", argName = "node", descr = "the root element of the XML file to use.  An optional namespace may be provided. This needs to be one of the top-level elements of the DFDL schema defined with --schema. Requires --schema. If not supplied uses the first element of the first schema")
       val tunables = props[String]('T', keyName = "tunable", valueName = "value", descr = "daffodil tunable to be used when compiling schema.")
-      val config = opt[String](short = 'c', argName = "file", descr = "path to file containing configuration items.")
+      val config = opt[File](short = 'c', argName = "file", descr = "path to file containing configuration items.")
       val outputDir = trailArg[String](required = false, descr = "output directory in which to generate source code. If not specified, uses current directory.")
 
-      validateOpt(schema) {
-        case None => Left("No schemas specified using the --schema option")
-        case _ => Right(Unit)
-      }
+      requireOne(schema) // --schema must be provided
+      validateFileIsFile(config) // --config must be a file that exists
     }
     addSubcommand(c)
   }
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
index 903ff08..f1bd90b 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
@@ -27,7 +27,6 @@ import java.nio.file.Files
 import java.util.zip.GZIPOutputStream
 
 import scala.collection.immutable.Queue
-import scala.collection.mutable
 
 import org.apache.daffodil.Implicits._; object INoWarn4 {
   ImplicitsSuppressUnusedImportWarning() }
@@ -67,7 +66,7 @@ import org.apache.daffodil.processors.unparsers.UnparseError
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe._
 import org.apache.daffodil.util.Misc
-
+import org.apache.daffodil.validation.XercesValidatorFactory
 
 /**
  * Implementation mixin - provides simple helper methods

[daffodil] 04/09: Test all integer sizes, signs, and byte orders

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit be9cf975c311aa86fd394bd03c7356ad608d3732
Author: John Interrante <in...@research.ge.com>
AuthorDate: Thu Dec 17 16:10:07 2020 -0500

    Test all integer sizes, signs, and byte orders
    
    Update pull request in response to reviewer feedback.  Lift byteOrder
    restriction so both bigEndian and littleEndian integers can be tested.
    Expand test schema to test all integer sizes, signs, and byte orders.
    
    In bin.LICENSE, add os-lib and directories-jvm licenses since we need
    to make it clear daffodil-cli uses them at runtime.
    
    In TestCLIGenerateC.scala, rename ex_int32 to ex_ints.
    
    Add c/Makefile to make it easier for people to build generated code
    themselves after running "daffodil generate c -s <schema>".
    
    In xml_reader.c, add strtounum since we need another function to parse
    64-bit unsigned integers successfully.
    
    In xml_writer.c, update comment as requested by pull request review.
    
    Replace ex_int32.[ch] with ex_ints.[ch] since test schema now attempts
    to test all integer sizes, signs, and byte orders.
    
    In BinaryIntegerKnownLengthCodeGenerator.scala, remove byteOrder
    restriction to allow littleEndian as well as bigEndian.  Add comment
    to explain unusual memory bit pattern (and change it to 0xCCC... which
    is the Microsoft magic debug value for uninitialized stack memory).
    Generate calls to both "be" and "le" endian conversion functions.
    
    In CodeGeneratorState.scala, add comment to explain degenerate cases
    of endian conversion functions and add littleEndian functions as well.
    
    In TestRuntime2.dfdl.xsd, remove alignment properties to ensure
    TestRuntime2.tdml will pass under both daffodil-runtime1 and
    daffodil-runtime2 and replace ex_int32 with ex_ints in order to test
    all integer sizes, signs, and byte orders.
    
    In TestRuntime2.tdml, replace ex_int32 tests with more comprehensive
    ex_ints tests.  Change binary and XML test files to have .dat and .xml
    file extensions as requested and update their contents to make tests
    pass under both runtime1 and runtime2.
    
    In TestRuntime2.scala, rename ex_int32 tests to ex_ints.
    
    In Rat.scala, rename binary test files and move them before sapi.
---
 daffodil-cli/bin.LICENSE                           | 405 +++++++++++
 .../daffodil/generating/TestCLIGenerateC.scala     |   6 +-
 daffodil-runtime2/src/main/resources/c/Makefile    |  52 ++
 .../src/main/resources/c/libcli/xml_reader.c       |  49 +-
 .../src/main/resources/c/libcli/xml_writer.c       |   2 +-
 .../src/main/resources/examples/ex_int32.c         | 263 -------
 .../src/main/resources/examples/ex_ints.c          | 766 +++++++++++++++++++++
 .../resources/examples/{ex_int32.h => ex_ints.h}   |  29 +-
 .../BinaryIntegerKnownLengthCodeGenerator.scala    |  27 +-
 .../runtime2/generators/CodeGeneratorState.scala   |  11 +-
 .../apache/daffodil/runtime2/TestRuntime2.dfdl.xsd |  33 +-
 .../org/apache/daffodil/runtime2/TestRuntime2.tdml |  29 +-
 .../org/apache/daffodil/runtime2/ex_int32_parse    | Bin 12 -> 0 bytes
 .../org/apache/daffodil/runtime2/ex_ints_parse.dat | Bin 0 -> 60 bytes
 .../{ex_int32_unparse => ex_ints_unparse.xml}      |  25 +-
 ...orion_command_parse => orion_command_parse.dat} | Bin
 ...n_command_unparse => orion_command_unparse.xml} |   0
 .../apache/daffodil/runtime2/TestRuntime2.scala    |   4 +-
 project/Rat.scala                                  |   4 +-
 19 files changed, 1362 insertions(+), 343 deletions(-)

diff --git a/daffodil-cli/bin.LICENSE b/daffodil-cli/bin.LICENSE
index f5fe806..63c4098 100644
--- a/daffodil-cli/bin.LICENSE
+++ b/daffodil-cli/bin.LICENSE
@@ -1445,3 +1445,408 @@ is subject to the terms and conditions of the following licenses.
     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     THE SOFTWARE.
+
+  This product bundles libraries from 'libaoyi', including the following files:
+    - lib/com.lihaoyi.geany_<VERSION>.jar
+    - lib/com.lihaoyi.os-lib_<VERSION>.jar
+  These files are available under the MIT license:
+
+    The MIT License (MIT)
+
+    Copyright (c) 2019 Li Haoyi (haoyi.sg@gmail.com)
+
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+
+  This product bundles 'directories-jvm', including the following files:
+    - lib/dirs-dev.directories_<VERSION>.jar
+  These files are available under the Mozilla 2.0 license:
+
+    Mozilla Public License Version 2.0
+    ==================================
+
+    1. Definitions
+    --------------
+
+    1.1. "Contributor"
+        means each individual or legal entity that creates, contributes to
+        the creation of, or owns Covered Software.
+
+    1.2. "Contributor Version"
+        means the combination of the Contributions of others (if any) used
+        by a Contributor and that particular Contributor's Contribution.
+
+    1.3. "Contribution"
+        means Covered Software of a particular Contributor.
+
+    1.4. "Covered Software"
+        means Source Code Form to which the initial Contributor has attached
+        the notice in Exhibit A, the Executable Form of such Source Code
+        Form, and Modifications of such Source Code Form, in each case
+        including portions thereof.
+
+    1.5. "Incompatible With Secondary Licenses"
+        means
+
+        (a) that the initial Contributor has attached the notice described
+            in Exhibit B to the Covered Software; or
+
+        (b) that the Covered Software was made available under the terms of
+            version 1.1 or earlier of the License, but not also under the
+            terms of a Secondary License.
+
+    1.6. "Executable Form"
+        means any form of the work other than Source Code Form.
+
+    1.7. "Larger Work"
+        means a work that combines Covered Software with other material, in
+        a separate file or files, that is not Covered Software.
+
+    1.8. "License"
+        means this document.
+
+    1.9. "Licensable"
+        means having the right to grant, to the maximum extent possible,
+        whether at the time of the initial grant or subsequently, any and
+        all of the rights conveyed by this License.
+
+    1.10. "Modifications"
+        means any of the following:
+
+        (a) any file in Source Code Form that results from an addition to,
+            deletion from, or modification of the contents of Covered
+            Software; or
+
+        (b) any new file in Source Code Form that contains any Covered
+            Software.
+
+    1.11. "Patent Claims" of a Contributor
+        means any patent claim(s), including without limitation, method,
+        process, and apparatus claims, in any patent Licensable by such
+        Contributor that would be infringed, but for the grant of the
+        License, by the making, using, selling, offering for sale, having
+        made, import, or transfer of either its Contributions or its
+        Contributor Version.
+
+    1.12. "Secondary License"
+        means either the GNU General Public License, Version 2.0, the GNU
+        Lesser General Public License, Version 2.1, the GNU Affero General
+        Public License, Version 3.0, or any later versions of those
+        licenses.
+
+    1.13. "Source Code Form"
+        means the form of the work preferred for making modifications.
+
+    1.14. "You" (or "Your")
+        means an individual or a legal entity exercising rights under this
+        License. For legal entities, "You" includes any entity that
+        controls, is controlled by, or is under common control with You. For
+        purposes of this definition, "control" means (a) the power, direct
+        or indirect, to cause the direction or management of such entity,
+        whether by contract or otherwise, or (b) ownership of more than
+        fifty percent (50%) of the outstanding shares or beneficial
+        ownership of such entity.
+
+    2. License Grants and Conditions
+    --------------------------------
+
+    2.1. Grants
+
+    Each Contributor hereby grants You a world-wide, royalty-free,
+    non-exclusive license:
+
+    (a) under intellectual property rights (other than patent or trademark)
+        Licensable by such Contributor to use, reproduce, make available,
+        modify, display, perform, distribute, and otherwise exploit its
+        Contributions, either on an unmodified basis, with Modifications, or
+        as part of a Larger Work; and
+
+    (b) under Patent Claims of such Contributor to make, use, sell, offer
+        for sale, have made, import, and otherwise transfer either its
+        Contributions or its Contributor Version.
+
+    2.2. Effective Date
+
+    The licenses granted in Section 2.1 with respect to any Contribution
+    become effective for each Contribution on the date the Contributor first
+    distributes such Contribution.
+
+    2.3. Limitations on Grant Scope
+
+    The licenses granted in this Section 2 are the only rights granted under
+    this License. No additional rights or licenses will be implied from the
+    distribution or licensing of Covered Software under this License.
+    Notwithstanding Section 2.1(b) above, no patent license is granted by a
+    Contributor:
+
+    (a) for any code that a Contributor has removed from Covered Software;
+        or
+
+    (b) for infringements caused by: (i) Your and any other third party's
+        modifications of Covered Software, or (ii) the combination of its
+        Contributions with other software (except as part of its Contributor
+        Version); or
+
+    (c) under Patent Claims infringed by Covered Software in the absence of
+        its Contributions.
+
+    This License does not grant any rights in the trademarks, service marks,
+    or logos of any Contributor (except as may be necessary to comply with
+    the notice requirements in Section 3.4).
+
+    2.4. Subsequent Licenses
+
+    No Contributor makes additional grants as a result of Your choice to
+    distribute the Covered Software under a subsequent version of this
+    License (see Section 10.2) or under the terms of a Secondary License (if
+    permitted under the terms of Section 3.3).
+
+    2.5. Representation
+
+    Each Contributor represents that the Contributor believes its
+    Contributions are its original creation(s) or it has sufficient rights
+    to grant the rights to its Contributions conveyed by this License.
+
+    2.6. Fair Use
+
+    This License is not intended to limit any rights You have under
+    applicable copyright doctrines of fair use, fair dealing, or other
+    equivalents.
+
+    2.7. Conditions
+
+    Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+    in Section 2.1.
+
+    3. Responsibilities
+    -------------------
+
+    3.1. Distribution of Source Form
+
+    All distribution of Covered Software in Source Code Form, including any
+    Modifications that You create or to which You contribute, must be under
+    the terms of this License. You must inform recipients that the Source
+    Code Form of the Covered Software is governed by the terms of this
+    License, and how they can obtain a copy of this License. You may not
+    attempt to alter or restrict the recipients' rights in the Source Code
+    Form.
+
+    3.2. Distribution of Executable Form
+
+    If You distribute Covered Software in Executable Form then:
+
+    (a) such Covered Software must also be made available in Source Code
+        Form, as described in Section 3.1, and You must inform recipients of
+        the Executable Form how they can obtain a copy of such Source Code
+        Form by reasonable means in a timely manner, at a charge no more
+        than the cost of distribution to the recipient; and
+
+    (b) You may distribute such Executable Form under the terms of this
+        License, or sublicense it under different terms, provided that the
+        license for the Executable Form does not attempt to limit or alter
+        the recipients' rights in the Source Code Form under this License.
+
+    3.3. Distribution of a Larger Work
+
+    You may create and distribute a Larger Work under terms of Your choice,
+    provided that You also comply with the requirements of this License for
+    the Covered Software. If the Larger Work is a combination of Covered
+    Software with a work governed by one or more Secondary Licenses, and the
+    Covered Software is not Incompatible With Secondary Licenses, this
+    License permits You to additionally distribute such Covered Software
+    under the terms of such Secondary License(s), so that the recipient of
+    the Larger Work may, at their option, further distribute the Covered
+    Software under the terms of either this License or such Secondary
+    License(s).
+
+    3.4. Notices
+
+    You may not remove or alter the substance of any license notices
+    (including copyright notices, patent notices, disclaimers of warranty,
+    or limitations of liability) contained within the Source Code Form of
+    the Covered Software, except that You may alter any license notices to
+    the extent required to remedy known factual inaccuracies.
+
+    3.5. Application of Additional Terms
+
+    You may choose to offer, and to charge a fee for, warranty, support,
+    indemnity or liability obligations to one or more recipients of Covered
+    Software. However, You may do so only on Your own behalf, and not on
+    behalf of any Contributor. You must make it absolutely clear that any
+    such warranty, support, indemnity, or liability obligation is offered by
+    You alone, and You hereby agree to indemnify every Contributor for any
+    liability incurred by such Contributor as a result of warranty, support,
+    indemnity or liability terms You offer. You may include additional
+    disclaimers of warranty and limitations of liability specific to any
+    jurisdiction.
+
+    4. Inability to Comply Due to Statute or Regulation
+    ---------------------------------------------------
+
+    If it is impossible for You to comply with any of the terms of this
+    License with respect to some or all of the Covered Software due to
+    statute, judicial order, or regulation then You must: (a) comply with
+    the terms of this License to the maximum extent possible; and (b)
+    describe the limitations and the code they affect. Such description must
+    be placed in a text file included with all distributions of the Covered
+    Software under this License. Except to the extent prohibited by statute
+    or regulation, such description must be sufficiently detailed for a
+    recipient of ordinary skill to be able to understand it.
+
+    5. Termination
+    --------------
+
+    5.1. The rights granted under this License will terminate automatically
+    if You fail to comply with any of its terms. However, if You become
+    compliant, then the rights granted under this License from a particular
+    Contributor are reinstated (a) provisionally, unless and until such
+    Contributor explicitly and finally terminates Your grants, and (b) on an
+    ongoing basis, if such Contributor fails to notify You of the
+    non-compliance by some reasonable means prior to 60 days after You have
+    come back into compliance. Moreover, Your grants from a particular
+    Contributor are reinstated on an ongoing basis if such Contributor
+    notifies You of the non-compliance by some reasonable means, this is the
+    first time You have received notice of non-compliance with this License
+    from such Contributor, and You become compliant prior to 30 days after
+    Your receipt of the notice.
+
+    5.2. If You initiate litigation against any entity by asserting a patent
+    infringement claim (excluding declaratory judgment actions,
+    counter-claims, and cross-claims) alleging that a Contributor Version
+    directly or indirectly infringes any patent, then the rights granted to
+    You by any and all Contributors for the Covered Software under Section
+    2.1 of this License shall terminate.
+
+    5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+    end user license agreements (excluding distributors and resellers) which
+    have been validly granted by You or Your distributors under this License
+    prior to termination shall survive termination.
+
+    ************************************************************************
+    *                                                                      *
+    *  6. Disclaimer of Warranty                                           *
+    *  -------------------------                                           *
+    *                                                                      *
+    *  Covered Software is provided under this License on an "as is"       *
+    *  basis, without warranty of any kind, either expressed, implied, or  *
+    *  statutory, including, without limitation, warranties that the       *
+    *  Covered Software is free of defects, merchantable, fit for a        *
+    *  particular purpose or non-infringing. The entire risk as to the     *
+    *  quality and performance of the Covered Software is with You.        *
+    *  Should any Covered Software prove defective in any respect, You     *
+    *  (not any Contributor) assume the cost of any necessary servicing,   *
+    *  repair, or correction. This disclaimer of warranty constitutes an   *
+    *  essential part of this License. No use of any Covered Software is   *
+    *  authorized under this License except under this disclaimer.         *
+    *                                                                      *
+    ************************************************************************
+
+    ************************************************************************
+    *                                                                      *
+    *  7. Limitation of Liability                                          *
+    *  --------------------------                                          *
+    *                                                                      *
+    *  Under no circumstances and under no legal theory, whether tort      *
+    *  (including negligence), contract, or otherwise, shall any           *
+    *  Contributor, or anyone who distributes Covered Software as          *
+    *  permitted above, be liable to You for any direct, indirect,         *
+    *  special, incidental, or consequential damages of any character      *
+    *  including, without limitation, damages for lost profits, loss of    *
+    *  goodwill, work stoppage, computer failure or malfunction, or any    *
+    *  and all other commercial damages or losses, even if such party      *
+    *  shall have been informed of the possibility of such damages. This   *
+    *  limitation of liability shall not apply to liability for death or   *
+    *  personal injury resulting from such party's negligence to the       *
+    *  extent applicable law prohibits such limitation. Some               *
+    *  jurisdictions do not allow the exclusion or limitation of           *
+    *  incidental or consequential damages, so this exclusion and          *
+    *  limitation may not apply to You.                                    *
+    *                                                                      *
+    ************************************************************************
+
+    8. Litigation
+    -------------
+
+    Any litigation relating to this License may be brought only in the
+    courts of a jurisdiction where the defendant maintains its principal
+    place of business and such litigation shall be governed by laws of that
+    jurisdiction, without reference to its conflict-of-law provisions.
+    Nothing in this Section shall prevent a party's ability to bring
+    cross-claims or counter-claims.
+
+    9. Miscellaneous
+    ----------------
+
+    This License represents the complete agreement concerning the subject
+    matter hereof. If any provision of this License is held to be
+    unenforceable, such provision shall be reformed only to the extent
+    necessary to make it enforceable. Any law or regulation which provides
+    that the language of a contract shall be construed against the drafter
+    shall not be used to construe this License against a Contributor.
+
+    10. Versions of the License
+    ---------------------------
+
+    10.1. New Versions
+
+    Mozilla Foundation is the license steward. Except as provided in Section
+    10.3, no one other than the license steward has the right to modify or
+    publish new versions of this License. Each version will be given a
+    distinguishing version number.
+
+    10.2. Effect of New Versions
+
+    You may distribute the Covered Software under the terms of the version
+    of the License under which You originally received the Covered Software,
+    or under the terms of any subsequent version published by the license
+    steward.
+
+    10.3. Modified Versions
+
+    If you create software not governed by this License, and you want to
+    create a new license for such software, you may create and use a
+    modified version of this License if you rename the license and remove
+    any references to the name of the license steward (except to note that
+    such modified license differs from this License).
+
+    10.4. Distributing Source Code Form that is Incompatible With Secondary
+    Licenses
+
+    If You choose to distribute Source Code Form that is Incompatible With
+    Secondary Licenses under the terms of this version of the License, the
+    notice described in Exhibit B of this License must be attached.
+
+    Exhibit A - Source Code Form License Notice
+    -------------------------------------------
+
+      This Source Code Form is subject to the terms of the Mozilla Public
+      License, v. 2.0. If a copy of the MPL was not distributed with this
+      file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+    If it is not possible or desirable to put the notice in a particular
+    file, then You may include the notice in a location (such as a LICENSE
+    file in a relevant directory) where a recipient would be likely to look
+    for such a notice.
+
+    You may add additional accurate notices of copyright ownership.
+
+    Exhibit B - "Incompatible With Secondary Licenses" Notice
+    ---------------------------------------------------------
+
+      This Source Code Form is "Incompatible With Secondary Licenses", as
+      defined by the Mozilla Public License, v. 2.0.
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
index f4e5cdc..de004d2 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -138,7 +138,7 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_root(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_int32 $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_ints $outputDir"
     val exitCmd = "exit"
 
     val shell = Util.start("")
@@ -154,14 +154,14 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_root_error(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_int32 $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_ints $outputDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
     try {
       shell.sendLine(generateCmd)
       shell.expect(contains("Schema Definition Error"))
-      shell.expect(contains("No global element found for {ex}ex_int32"))
+      shell.expect(contains("No global element found for {ex}ex_ints"))
       shell.sendLine(exitCmd)
       shell.expect(eof())
     } finally {
diff --git a/daffodil-runtime2/src/main/resources/c/Makefile b/daffodil-runtime2/src/main/resources/c/Makefile
new file mode 100644
index 0000000..d3fcb79
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/Makefile
@@ -0,0 +1,52 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Here's how to compile the C sources into a program for running
+# parse/unparse tests (.dat <-> .xml)
+
+SOURCES = libcli/*.[ch] libruntime/*.[ch]
+PROGRAM = ./daffodil
+CFLAGS = -Wall
+
+$(PROGRAM): $(SOURCES)
+	$(CC) $(CFLAGS) -o $(PROGRAM) -I libcli -I libruntime $(SOURCES) -lmxml -lpthread -lm
+
+# Here's how to run parse/unparse tests (.dat <-> .xml, although you
+# will need to create the .dat and .xml files first)
+
+PARSE_DAT = parse.dat
+UNPARSE_XML = unparse.xml
+
+clean:
+	rm -f $(PROGRAM) test_$(PARSE_DAT) test_$(UNPARSE_XML)
+
+tests: parse-test unparse-test
+
+parse-test: $(PROGRAM)
+	$(PROGRAM) parse $(PARSE_DAT) -o test_$(UNPARSE_XML)
+	xmldiff $(UNPARSE_XML) test_$(UNPARSE_XML)
+
+unparse-test: $(PROGRAM)
+	$(PROGRAM) unparse $(UNPARSE_XML) -o test_$(PARSE_DAT)
+	diff $(PARSE_DAT) test_$(PARSE_DAT)
+
+# You will need the Mini-XML library and xmldiff - here's how to
+# install both in Ubuntu 20.04
+
+deps:
+	sudo apt install libmxml-dev xmldiff
+
+.PHONY: deps tests parse-test unparse-test
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
index 763c5e3..175ca52 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
@@ -22,7 +22,7 @@
 #include <stdint.h>   // for intmax_t, int32_t, INT32_MAX, INT32_MIN
 #include <string.h>   // for strcmp, strlen, strncmp
 
-// Convert an XML element's text to an integer (BSD function not
+// Convert an XML element's text to a signed integer (BSD function not
 // widely available, so roll our own function based on strtoimax)
 
 static intmax_t
@@ -60,6 +60,43 @@ strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
     return value;
 }
 
+// Convert an XML element's text to an unsigned integer (roll our own
+// function based on strtoumax)
+
+static uintmax_t
+strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
+{
+    char *endptr = NULL;
+
+    // Clear errno to detect failure after calling strtoumax
+    errno = 0;
+    const uintmax_t value = strtoumax(numptr, &endptr, 10);
+
+    // Report any issues converting the string to a number
+    if (errno != 0)
+    {
+        *errstrp = "Error converting XML data to integer";
+    }
+    else if (endptr == numptr)
+    {
+        *errstrp = "Found no number in XML data";
+    }
+    else if (*endptr != '\0')
+    {
+        *errstrp = "Found non-number characters in XML data";
+    }
+    else if (value > maxval)
+    {
+        *errstrp = "Number in XML data out of range";
+    }
+    else
+    {
+        *errstrp = NULL;
+    }
+
+    return value;
+}
+
 // Read XML data from file before walking infoset
 
 static const char *
@@ -187,25 +224,25 @@ xmlIntegerElem(XMLReader *reader, const ERD *erd, void *intLocation)
             // Check for any errors getting the integer number
             const char *errstr = NULL;
 
-            // Need to handle varying bit lengths and signedness
+            // Handle varying bit lengths of both signed & unsigned numbers
             const enum TypeCode typeCode = erd->typeCode;
             switch (typeCode)
             {
             case PRIMITIVE_UINT64:
                 *(uint64_t *)intLocation =
-                    (uint64_t)strtonum(number_from_xml, 0, UINT64_MAX, &errstr);
+                    (uint64_t)strtounum(number_from_xml, UINT64_MAX, &errstr);
                 break;
             case PRIMITIVE_UINT32:
                 *(uint32_t *)intLocation =
-                    (uint32_t)strtonum(number_from_xml, 0, UINT32_MAX, &errstr);
+                    (uint32_t)strtounum(number_from_xml, UINT32_MAX, &errstr);
                 break;
             case PRIMITIVE_UINT16:
                 *(uint16_t *)intLocation =
-                    (uint16_t)strtonum(number_from_xml, 0, UINT16_MAX, &errstr);
+                    (uint16_t)strtounum(number_from_xml, UINT16_MAX, &errstr);
                 break;
             case PRIMITIVE_UINT8:
                 *(uint8_t *)intLocation =
-                    (uint8_t)strtonum(number_from_xml, 0, UINT8_MAX, &errstr);
+                    (uint8_t)strtounum(number_from_xml, UINT8_MAX, &errstr);
                 break;
             case PRIMITIVE_INT64:
                 *(int64_t *)intLocation = (int64_t)strtonum(
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
index 791968b..9a0be6d 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
@@ -107,7 +107,7 @@ xmlIntegerElem(XMLWriter *writer, const ERD *erd, const void *intLocation)
         mxmlElementSetAttr(simple, xmlns, ns);
     }
 
-    // Need to handle varying bit lengths and signedness
+    // Handle varying bit lengths of both signed & unsigned numbers
     const enum TypeCode typeCode = erd->typeCode;
     mxml_node_t *       text = NULL;
     switch (typeCode)
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_int32.c b/daffodil-runtime2/src/main/resources/examples/ex_int32.c
deleted file mode 100644
index 5e38ae0..0000000
--- a/daffodil-runtime2/src/main/resources/examples/ex_int32.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ex_int32.h" // for generated code structs
-#include <endian.h>   // for be32toh, htobe32
-#include <stddef.h>   // for ptrdiff_t
-#include <stdio.h>    // for NULL, fread, fwrite, size_t, FILE
-
-// Prototypes needed for compilation
-
-static void        c2_initSelf(c2 *instance);
-static const char *c2_parseSelf(c2 *instance, const PState *pstate);
-static const char *c2_unparseSelf(const c2 *instance, const UState *ustate);
-static void        ex_int32_initSelf(ex_int32 *instance);
-static const char *ex_int32_parseSelf(ex_int32 *instance, const PState *pstate);
-static const char *ex_int32_unparseSelf(const ex_int32 *instance, const UState *ustate);
-
-// Metadata singletons
-
-static const ERD e1_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "e1", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD e2_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "e2", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD e3_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "e3", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const c2 c2_compute_ERD_offsets;
-
-static const ptrdiff_t c2_offsets[2] = {
-    (char *)&c2_compute_ERD_offsets.e2 - (char *)&c2_compute_ERD_offsets,
-    (char *)&c2_compute_ERD_offsets.e3 - (char *)&c2_compute_ERD_offsets};
-
-static const ERD *c2_childrenERDs[2] = {&e2_ERD, &e3_ERD};
-
-static const ERD c2_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "c2", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    COMPLEX,                         // typeCode
-    2,                               // numChildren
-    c2_offsets,                      // offsets
-    c2_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&c2_initSelf,       // initSelf
-    (ERDParseSelf)&c2_parseSelf,     // parseSelf
-    (ERDUnparseSelf)&c2_unparseSelf, // unparseSelf
-};
-
-static const ex_int32 ex_int32_compute_ERD_offsets;
-
-static const ptrdiff_t ex_int32_offsets[2] = {
-    (char *)&ex_int32_compute_ERD_offsets.e1 - (char *)&ex_int32_compute_ERD_offsets,
-    (char *)&ex_int32_compute_ERD_offsets.c2 - (char *)&ex_int32_compute_ERD_offsets};
-
-static const ERD *ex_int32_childrenERDs[2] = {&e1_ERD, &c2_ERD};
-
-static const ERD ex_int32_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "ex_int32", // namedQName.local
-        "http://example.com", // namedQName.ns
-    },
-    COMPLEX,                         // typeCode
-    2,                               // numChildren
-    ex_int32_offsets,                      // offsets
-    ex_int32_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&ex_int32_initSelf,       // initSelf
-    (ERDParseSelf)&ex_int32_parseSelf,     // parseSelf
-    (ERDUnparseSelf)&ex_int32_unparseSelf, // unparseSelf
-};
-
-// Return a root element to be used for parsing or unparsing
-
-InfosetBase *
-rootElement()
-{
-    static ex_int32    instance;
-    InfosetBase *root = &instance._base;
-    ex_int32_ERD.initSelf(root);
-    return root;
-}
-
-// Methods to initialize, parse, and unparse infoset nodes
-
-static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
-static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
-
-static void
-c2_initSelf(c2 *instance)
-{
-    instance->e2 = 0xCDCDCDCD;
-    instance->e3 = 0xCDCDCDCD;
-    instance->_base.erd = &c2_ERD;
-}
-
-static const char *
-c2_parseSelf(c2 *instance, const PState *pstate)
-{
-    const char *error_msg = NULL;
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->e2 = be32toh(*((uint32_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->e3 = be32toh(*((uint32_t *)(&buffer)));
-    }
-    return error_msg;
-}
-
-static const char *
-c2_unparseSelf(const c2 *instance, const UState *ustate)
-{
-    const char *error_msg = NULL;
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htobe32(instance->e2);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htobe32(instance->e3);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    return error_msg;
-}
-
-static void
-ex_int32_initSelf(ex_int32 *instance)
-{
-    instance->e1 = 0xCDCDCDCD;
-    c2_initSelf(&instance->c2);
-    instance->_base.erd = &ex_int32_ERD;
-}
-
-static const char *
-ex_int32_parseSelf(ex_int32 *instance, const PState *pstate)
-{
-    const char *error_msg = NULL;
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->e1 = be32toh(*((uint32_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        error_msg = c2_parseSelf(&instance->c2, pstate);
-    }
-    return error_msg;
-}
-
-static const char *
-ex_int32_unparseSelf(const ex_int32 *instance, const UState *ustate)
-{
-    const char *error_msg = NULL;
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htobe32(instance->e1);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        error_msg = c2_unparseSelf(&instance->c2, ustate);
-    }
-    return error_msg;
-}
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_ints.c b/daffodil-runtime2/src/main/resources/examples/ex_ints.c
new file mode 100644
index 0000000..2db53e2
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/examples/ex_ints.c
@@ -0,0 +1,766 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ex_ints.h" // for generated code structs
+#include <endian.h>         // for be32toh, htobe32, etc.
+#include <stddef.h>         // for ptrdiff_t
+#include <stdio.h>          // for NULL, fread, fwrite, size_t, FILE
+
+// Prototypes needed for compilation
+
+static void        ex_ints_initSelf(ex_ints *instance);
+static const char *ex_ints_parseSelf(ex_ints *instance, const PState *pstate);
+static const char *ex_ints_unparseSelf(const ex_ints *instance, const UState *ustate);
+
+// Metadata singletons
+
+static const ERD be_uint64_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint32_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint16_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint8_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int64_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int32_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int16_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int8_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint64_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint32_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint16_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint8_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int64_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int32_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int16_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int8_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ex_ints ex_ints_compute_ERD_offsets;
+
+static const ptrdiff_t ex_ints_offsets[16] = {
+    (char *)&ex_ints_compute_ERD_offsets.be_uint64 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_uint32 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_uint16 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_uint8 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_int64 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_int32 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_int16 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.be_int8 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_uint64 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_uint32 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_uint16 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_uint8 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_int64 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_int32 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_int16 - (char *)&ex_ints_compute_ERD_offsets,
+    (char *)&ex_ints_compute_ERD_offsets.le_int8 - (char *)&ex_ints_compute_ERD_offsets
+};
+
+static const ERD *ex_ints_childrenERDs[16] = {
+    &be_uint64_ERD,
+    &be_uint32_ERD,
+    &be_uint16_ERD,
+    &be_uint8_ERD,
+    &be_int64_ERD,
+    &be_int32_ERD,
+    &be_int16_ERD,
+    &be_int8_ERD,
+    &le_uint64_ERD,
+    &le_uint32_ERD,
+    &le_uint16_ERD,
+    &le_uint8_ERD,
+    &le_int64_ERD,
+    &le_int32_ERD,
+    &le_int16_ERD,
+    &le_int8_ERD
+};
+
+static const ERD ex_ints_ERD = {
+    {
+        NULL, // namedQName.prefix
+        "ex_ints", // namedQName.local
+        "http://example.com", // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    16,                               // numChildren
+    ex_ints_offsets,                      // offsets
+    ex_ints_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&ex_ints_initSelf,       // initSelf
+    (ERDParseSelf)&ex_ints_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&ex_ints_unparseSelf, // unparseSelf
+};
+
+// Return a root element to be used for parsing or unparsing
+
+InfosetBase *
+rootElement()
+{
+    static ex_ints    instance;
+    InfosetBase *root = &instance._base;
+    ex_ints_ERD.initSelf(root);
+    return root;
+}
+
+// Degenerate cases of endian-conversion functions called by code
+// generator since <endian.h> handles only 16, 32, and 64-bit cases
+
+static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
+static inline uint8_t htole8(uint8_t h8b) { return h8b; }
+static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
+static inline uint8_t le8toh(uint8_t le8b) { return le8b; }
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+ex_ints_initSelf(ex_ints *instance)
+{
+    instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
+    instance->be_uint32 = 0xCCCCCCCC;
+    instance->be_uint16 = 0xCCCC;
+    instance->be_uint8 = 0xCC;
+    instance->be_int64 = 0xCCCCCCCCCCCCCCCC;
+    instance->be_int32 = 0xCCCCCCCC;
+    instance->be_int16 = 0xCCCC;
+    instance->be_int8 = 0xCC;
+    instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
+    instance->le_uint32 = 0xCCCCCCCC;
+    instance->le_uint16 = 0xCCCC;
+    instance->le_uint8 = 0xCC;
+    instance->le_int64 = 0xCCCCCCCCCCCCCCCC;
+    instance->le_int32 = 0xCCCCCCCC;
+    instance->le_int16 = 0xCCCC;
+    instance->le_int8 = 0xCC;
+    instance->_base.erd = &ex_ints_ERD;
+}
+
+static const char *
+ex_ints_parseSelf(ex_ints *instance, const PState *pstate)
+{
+    const char *error_msg = NULL;
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint64_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_uint64 = be64toh(*((uint64_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint32_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_uint32 = be32toh(*((uint32_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint16_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_uint16 = be16toh(*((uint16_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint8_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_uint8 = be8toh(*((uint8_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint64_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_int64 = be64toh(*((uint64_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint32_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_int32 = be32toh(*((uint32_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint16_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_int16 = be16toh(*((uint16_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint8_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->be_int8 = be8toh(*((uint8_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint64_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_uint64 = le64toh(*((uint64_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint32_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_uint32 = le32toh(*((uint32_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint16_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_uint16 = le16toh(*((uint16_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint8_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_uint8 = le8toh(*((uint8_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint64_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_int64 = le64toh(*((uint64_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint32_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_int32 = le32toh(*((uint32_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint16_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_int16 = le16toh(*((uint16_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[sizeof(uint8_t)];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->le_int8 = le8toh(*((uint8_t *)(&buffer)));
+    }
+    return error_msg;
+}
+
+static const char *
+ex_ints_unparseSelf(const ex_ints *instance, const UState *ustate)
+{
+    const char *error_msg = NULL;
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint64_t)];
+            uint64_t i_val;
+        } buffer;
+        buffer.i_val = htobe64(instance->be_uint64);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint32_t)];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htobe32(instance->be_uint32);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint16_t)];
+            uint16_t i_val;
+        } buffer;
+        buffer.i_val = htobe16(instance->be_uint16);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint8_t)];
+            uint8_t i_val;
+        } buffer;
+        buffer.i_val = htobe8(instance->be_uint8);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint64_t)];
+            uint64_t i_val;
+        } buffer;
+        buffer.i_val = htobe64(instance->be_int64);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint32_t)];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htobe32(instance->be_int32);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint16_t)];
+            uint16_t i_val;
+        } buffer;
+        buffer.i_val = htobe16(instance->be_int16);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint8_t)];
+            uint8_t i_val;
+        } buffer;
+        buffer.i_val = htobe8(instance->be_int8);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint64_t)];
+            uint64_t i_val;
+        } buffer;
+        buffer.i_val = htole64(instance->le_uint64);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint32_t)];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htole32(instance->le_uint32);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint16_t)];
+            uint16_t i_val;
+        } buffer;
+        buffer.i_val = htole16(instance->le_uint16);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint8_t)];
+            uint8_t i_val;
+        } buffer;
+        buffer.i_val = htole8(instance->le_uint8);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint64_t)];
+            uint64_t i_val;
+        } buffer;
+        buffer.i_val = htole64(instance->le_int64);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint32_t)];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htole32(instance->le_int32);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint16_t)];
+            uint16_t i_val;
+        } buffer;
+        buffer.i_val = htole16(instance->le_int16);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[sizeof(uint8_t)];
+            uint8_t i_val;
+        } buffer;
+        buffer.i_val = htole8(instance->le_int8);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    return error_msg;
+}
+
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_int32.h b/daffodil-runtime2/src/main/resources/examples/ex_ints.h
similarity index 69%
rename from daffodil-runtime2/src/main/resources/examples/ex_int32.h
rename to daffodil-runtime2/src/main/resources/examples/ex_ints.h
index b46c30c..bc8ffd8 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_int32.h
+++ b/daffodil-runtime2/src/main/resources/examples/ex_ints.h
@@ -23,18 +23,25 @@
 
 // Define some infoset structures
 
-typedef struct c2
+typedef struct ex_ints
 {
     InfosetBase _base;
-    int32_t     e2;
-    int32_t     e3;
-} c2;
-
-typedef struct ex_int32
-{
-    InfosetBase _base;
-    int32_t     e1;
-    c2          c2;
-} ex_int32;
+    uint64_t    be_uint64;
+    uint32_t    be_uint32;
+    uint16_t    be_uint16;
+    uint8_t     be_uint8;
+    int64_t     be_int64;
+    int32_t     be_int32;
+    int16_t     be_int16;
+    int8_t      be_int8;
+    uint64_t    le_uint64;
+    uint32_t    le_uint32;
+    uint16_t    le_uint16;
+    uint8_t     le_uint8;
+    int64_t     le_int64;
+    int32_t     le_int32;
+    int16_t     le_int16;
+    int8_t      le_int8;
+} ex_ints;
 
 #endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
index 2936ea6..f31a162 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
@@ -39,26 +39,23 @@ trait BinaryIntegerKnownLengthCodeGenerator {
       bo
     }
 
-    // This insures we can use regular java.io library calls.
-    if (e.alignmentValueInBits.intValue() % 8 != 0)
-      e.SDE("Only alignment to 8-bit (1 byte) boundaries is supported.")
-
-    // The restrictions below are ones we want to eventually lift.
-    if (byteOrder ne ByteOrder.BigEndian)
-      e.SDE("Only dfdl:byteOrder 'bigEndian' is supported.")
-
+    // We eventually want to lift this restriction.
     if (e.bitOrder ne BitOrder.MostSignificantBitFirst)
       e.SDE("Only dfdl:bitOrder 'mostSignificantBitFirst' is supported.")
+    if (e.alignmentValueInBits.intValue() % 8 != 0)
+      e.SDE("Only alignment to 8-bit (1 byte) boundaries is supported.")
 
-    // Start generating code snippets
+    // Use an unusual memory bit pattern (magic debug value) to mark fields as
+    // uninitialized in case generated code fails to set them during parsing.
     val initialValue = lengthInBits match {
-      case 8 => "0xCD"
-      case 16 => "0xCDCD"
-      case 32 => "0xCDCDCDCD"
-      case 64 => "0xCDCDCDCDCDCDCDCD"
+      case 8 => "0xCC"
+      case 16 => "0xCCCC"
+      case 32 => "0xCCCCCCCC"
+      case 64 => "0xCCCCCCCCCCCCCCCC"
       case _ => e.SDE("Lengths other than 8, 16, 32, or 64 bits are not supported.")
     }
     val initStatement = s"    instance->$fieldName = $initialValue;"
+    val conv = if (byteOrder eq ByteOrder.BigEndian) "be" else "le"
     val parseStatement =
       s"""    if (!error_msg)
          |    {
@@ -68,7 +65,7 @@ trait BinaryIntegerKnownLengthCodeGenerator {
          |        {
          |            error_msg = eof_or_error_msg(pstate->stream);
          |        }
-         |        instance->$fieldName = be${lengthInBits}toh(*((uint${lengthInBits}_t *)(&buffer)));
+         |        instance->$fieldName = ${conv}${lengthInBits}toh(*((uint${lengthInBits}_t *)(&buffer)));
          |    }""".stripMargin
     val unparseStatement =
       s"""    if (!error_msg)
@@ -78,7 +75,7 @@ trait BinaryIntegerKnownLengthCodeGenerator {
          |            char     c_val[sizeof(uint${lengthInBits}_t)];
          |            uint${lengthInBits}_t i_val;
          |        } buffer;
-         |        buffer.i_val = htobe${lengthInBits}(instance->$fieldName);
+         |        buffer.i_val = hto${conv}${lengthInBits}(instance->$fieldName);
          |        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
          |        if (count < sizeof(buffer))
          |        {
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
index 0255111..f629f14 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -248,7 +248,7 @@ class CodeGeneratorState {
     val finalImplementation = this.finalImplementation.mkString("\n")
     val code =
       s"""#include "generated_code.h" // for generated code structs
-         |#include <endian.h>         // for be32toh, htobe32
+         |#include <endian.h>         // for be32toh, htobe32, etc.
          |#include <stddef.h>         // for ptrdiff_t
          |#include <stdio.h>          // for NULL, fread, fwrite, size_t, FILE
          |
@@ -270,10 +270,15 @@ class CodeGeneratorState {
          |    return root;
          |}
          |
-         |// Methods to initialize, parse, and unparse infoset nodes
+         |// Degenerate cases of endian-conversion functions called by code
+         |// generator since <endian.h> handles only 16, 32, and 64-bit cases
          |
-         |static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
          |static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
+         |static inline uint8_t htole8(uint8_t h8b) { return h8b; }
+         |static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
+         |static inline uint8_t le8toh(uint8_t le8b) { return le8b; }
+         |
+         |// Methods to initialize, parse, and unparse infoset nodes
          |
          |$finalImplementation
          |""".stripMargin
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
index 88fdf56..5998338 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
@@ -29,8 +29,7 @@
     <xs:annotation>
         <xs:appinfo source="http://www.ogf.org/dfdl/">
             <dfdl:format
-                alignment="8"
-                alignmentUnits="bits"
+                byteOrder="bigEndian"
                 encoding="UTF-8"
                 lengthUnits="bits"
                 representation="binary"
@@ -38,39 +37,43 @@
         </xs:appinfo>
     </xs:annotation>
 
-    <xs:element name="ex_int32">
+    <xs:element name="ex_ints">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="e1" type="xs:int" />
-                <xs:element name="c2">
-                    <xs:complexType>
-                        <xs:sequence>
-                            <xs:element name="e2" type="xs:int" />
-                            <xs:element name="e3" type="xs:int" />
-                        </xs:sequence>
-                    </xs:complexType>
-                </xs:element>
+                <xs:element name="be_uint64" type="xs:unsignedLong" />
+                <xs:element name="be_uint32" type="xs:unsignedInt" />
+                <xs:element name="be_uint16" type="xs:unsignedShort" />
+                <xs:element name="be_uint8" type="xs:unsignedByte" />
+                <xs:element name="be_int64" type="xs:long" />
+                <xs:element name="be_int32" type="xs:int" />
+                <xs:element name="be_int16" type="xs:short" />
+                <xs:element name="be_int8" type="xs:byte" />
+                <xs:element name="le_uint64" type="xs:unsignedLong" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_uint32" type="xs:unsignedInt" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_uint16" type="xs:unsignedShort" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_uint8" type="xs:unsignedByte" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_int64" type="xs:long" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_int32" type="xs:int" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_int16" type="xs:short" dfdl:byteOrder="littleEndian" />
+                <xs:element name="le_int8" type="xs:byte" dfdl:byteOrder="littleEndian" />
             </xs:sequence>
         </xs:complexType>
     </xs:element>
 
     <xs:simpleType
         name="int16"
-        dfdl:alignment="16"
         dfdl:length="16"
         dfdl:lengthKind="explicit">
         <xs:restriction base="xs:short"/>
     </xs:simpleType>
     <xs:simpleType
         name="uint8"
-        dfdl:alignment="8"
         dfdl:length="8"
         dfdl:lengthKind="explicit">
         <xs:restriction base="xs:unsignedByte"/>
     </xs:simpleType>
     <xs:simpleType
         name="uint16"
-        dfdl:alignment="16"
         dfdl:length="16"
         dfdl:lengthKind="explicit">
         <xs:restriction base="xs:unsignedShort"/>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
index 7b85711..3db679c 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
@@ -24,7 +24,6 @@ limitations under the License.
   suiteName="TestRuntime2"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
-  xmlns:ex="http://example.com"
   xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
   xmlns="http://example.com">
 
@@ -41,28 +40,28 @@ limitations under the License.
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    description="Parse example ex_int32"
+    description="Parse example ex_ints"
     model="TestRuntime2.dfdl.xsd"
-    name="ex_int32_parse"
-    root="ex_int32">
+    name="ex_ints_parse"
+    root="ex_ints">
     <tdml:document>
-      <tdml:documentPart type="file">ex_int32_parse</tdml:documentPart>
+      <tdml:documentPart type="file">ex_ints_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_int32_unparse</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_ints_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="Unparse example ex_int32"
+    description="Unparse example ex_ints"
     model="TestRuntime2.dfdl.xsd"
-    name="ex_int32_unparse"
-    root="ex_int32">
+    name="ex_ints_unparse"
+    root="ex_ints">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_int32_unparse</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_ints_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_int32_parse</tdml:documentPart>
+      <tdml:documentPart type="file">ex_ints_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
@@ -72,10 +71,10 @@ limitations under the License.
     name="orion_command_parse"
     root="orion_command">
     <tdml:document>
-      <tdml:documentPart type="file">orion_command_parse</tdml:documentPart>
+      <tdml:documentPart type="file">orion_command_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">orion_command_unparse</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">orion_command_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
@@ -85,10 +84,10 @@ limitations under the License.
     name="orion_command_unparse"
     root="orion_command">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">orion_command_unparse</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">orion_command_unparse.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">orion_command_parse</tdml:documentPart>
+      <tdml:documentPart type="file">orion_command_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse
deleted file mode 100644
index fce373f..0000000
Binary files a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse and /dev/null differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat
new file mode 100644
index 0000000..e16cc72
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_unparse b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_unparse.xml
similarity index 63%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_unparse
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_unparse.xml
index cad2f06..8874561 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_unparse
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_unparse.xml
@@ -16,10 +16,21 @@
   limitations under the License.
 -->
 
-<ex_int32 xmlns="http://example.com">
-  <e1>1</e1>
-  <c2>
-    <e2>2</e2>
-    <e3>3</e3>
-  </c2>
-</ex_int32>
+<ex_ints xmlns="http://example.com">
+  <be_uint64>64</be_uint64>
+  <be_uint32>32</be_uint32>
+  <be_uint16>16</be_uint16>
+  <be_uint8>8</be_uint8>
+  <be_int64>-64</be_int64>
+  <be_int32>-32</be_int32>
+  <be_int16>-16</be_int16>
+  <be_int8>-8</be_int8>
+  <le_uint64>64</le_uint64>
+  <le_uint32>32</le_uint32>
+  <le_uint16>16</le_uint16>
+  <le_uint8>8</le_uint8>
+  <le_int64>-64</le_int64>
+  <le_int32>-32</le_int32>
+  <le_int16>-16</le_int16>
+  <le_int8>-8</le_int8>
+</ex_ints>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse.xml
similarity index 100%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse.xml
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
index 5a5b7e7..88d7e12 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
@@ -31,8 +31,8 @@ object TestRuntime2 {
 class TestRuntime2 {
   import TestRuntime2._
 
-  @Test def test_ex_int32_parse(): Unit = { runner.runOneTest("ex_int32_parse") }
-  @Test def test_ex_int32_unparse(): Unit = { runner.runOneTest("ex_int32_unparse") }
+  @Test def test_ex_ints_parse(): Unit = { runner.runOneTest("ex_ints_parse") }
+  @Test def test_ex_ints_unparse(): Unit = { runner.runOneTest("ex_ints_unparse") }
   @Test def test_orion_command_parse(): Unit = { runner.runOneTest("orion_command_parse") }
   @Test def test_orion_command_unparse(): Unit = { runner.runOneTest("orion_command_unparse") }
 }
diff --git a/project/Rat.scala b/project/Rat.scala
index aa3b78d..803027b 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -107,6 +107,8 @@ object Rat {
     file("daffodil-japi/src/test/resources/test/japi/myData16.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myData19.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myDataBroken.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/01very_simple.txt"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData2.dat"),
@@ -116,8 +118,6 @@ object Rat {
     file("daffodil-sapi/src/test/resources/test/sapi/myData16.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData19.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myDataBroken.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_int32_parse"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse"),
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.bin"),
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),

[daffodil] 05/09: Support arrays, real numbers, and improve TDML processing

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 10618041eae1ac0509e12f608528e604ed80d83d
Author: John Interrante <in...@research.ge.com>
AuthorDate: Thu Jan 7 11:54:00 2021 -0500

    Support arrays, real numbers, and improve TDML processing
    
    Expand the C code generator to support both binary real numbers and
    fixed occurrence arrays of binary numbers.  Reduce the size of the
    generated C code by emitting one-line function calls instead of 14-16
    lines of low level parsing & unparsing C code for each binary number.
    Move the 14-16 lines of low level code into functions within parsers.c
    and unparsers.c in the c/libruntime directory instead.
    
    Remove the orion-command element from TestRuntime2.dfdl.xsd and add it
    back as a new test schema (orion-command.dfdl.xsd), tests
    (orion-command.tdml), and data files (command_parse.dat/unparse.xml,
    video_settings_parse.dat/unparse.xml).  Rename the ex_ints element in
    TestRuntime2.dfdl.xsd to ex_nums and add arrays and real numbers to
    its schema and data files.
    
    Fix file-writing/reading collision problems when both TestOrionCommand
    and TestRuntime2 try to compile and run C code at the same time.  Get
    rid of dev.dirs % directories-jvm and make the TDML processor write to
    a temporary unique directory for each test which gets deleted after
    each test.  Thankfully, the "zig cc" command now caches previously
    built files in zig's own global cache directory instead of a local
    zig_cache directory so the TDML processor no longer needs to write to
    a daffodil cache directory anymore.
    
    Changelog:
    
    In main.yml, install pkgconf instead of pkg-config in msys2 setup
    since pkgconf is newer and better.
    
    In README.md, add new build requirements so developers will know they
    will need a C compiler and Mini-XML library to build Daffodil.
    
    In bin.LICENSE, remove license for dirs-dev / directories-jvm.
    
    In TestCLIGenerateC.scala, rename ex_ints to ex_nums.
    
    In c/Makefile, change CFLAGS for easier debugging and remove unneeded
    libraries.
    
    Run include-what-you-use on C source files in verbose mode to update
    comments saying exactly what is used from each include in these files:
    
     - daffodil_argp.c
     - daffodil_main.c
     - xml_reader.c
     - xml_writer.c
     - infoset.c
     - parsers.[ch]
     - unparsers.[ch]
     - ex_nums.[ch]
    
    In daffodil_main.c, update the parseSelf and unparseSelf calls since
    they now return void instead of const char *error_msg.
    
    In xml_reader.c, define new strtofnum and strtodnum functions to
    support reading floating point numbers from XML data.  Rename
    xmlIntegerElem to xmlNumberElem and make it call strtofnum and
    strtodnum as well as strtounum and strtonum.
    
    In xml_writer.c, rename xmlIntegerElem to xmlNumberElem and make it
    write floating point numbers as well as integers.  Use G format
    specifier and call fixNumberIfNeeded on number's text afterwards to
    ensure that [-]INF and NaN will be capitalized correctly according to
    the XML Schema's xsd:float specification.  We still need to make
    runtime1 and runtime2's XML floating point output match each other
    even more closely or make TDML Runner compare real numbers
    numerically, not textually, so it can ignore minor textual differences
    without ignoring numerical differences.
    
    In infoset.c, make walkInfosetNode call visitNumberElem for primitive
    floats/doubles as well as primitive integers.
    
    In infoset.h, change signatures of parseSelf and unparseSelf.  Rename
    VisitIntegerElem to VisitNumberElem.  Add enumerations for primitive
    floats/doubles.  Add const char *error_msg to PState and UState
    structs so parser/unparser functions can set it when needed.  Add
    (void) to rootElement() to fix -Weverything warning.
    
    In parsers.{c,h}, define functions to parse binary real and integer
    numbers.  Use macros to achieve DRY (Don't Repeat Yourself).  Note
    that binary floating point numbers can be little-endian or big-endian
    just like binary integers.
    
    In unparsers.{c,h}, define functions to unparse binary real and
    integer numbers.  Use macros to achieve DRY (Don't Repeat Yourself).
    
    In ex_nums.{c,h}, rename from ex_ints.{c,h} to ex_nums.{c,h}.  Verify
    real numbers work, then implement and test code to support a fixed
    occurrence array, propagate changes to C code generator, and verify C
    code generator produces same code.  Add a second array to ex_nums'
    schema and verify C code generator generates appropriate code for it
    too.  Make generator add (void) to rootElement() and (const char*) to
    ERD offset computations to fix -Weverything warnings.
    
    In CodeGenerator.scala, make generateCode return codeDir rather than
    outputDir, pass codeDir rather than outputDir to compileCode, and
    perform compilation in codeDir rather than outputDir since "zig cc"
    will now cache previously built files in zig's global cache directory,
    not a local zig_cache directory.
    
    In Runtime2CodeGenerator.scala, add BinaryFloat and BinaryDouble cases
    within the generateCode function and make them call
    BinaryFloatCodeGenerator.  Also add and call a noop function to
    facilitate setting a breakpoint within the generateCode function.
    
    In BinaryFloatCodeGenerator.scala, initialize float fields with NaN
    macro (NAN) since some platforms don't define signaling NaN macros
    (SNAN & SNANF).  Emit one-line function calls to parse and unparse
    32-bit, 64-bit big-endian & little-endian binary floats.  Generate
    code to initialize a floating point array, parse data into the array,
    and unparse data from the array too.
    
    In BinaryIntegerKnownLengthCodeGenerator.scala, remove minimum 8-bit
    alignment restriction to allow schemas to say they want 1-bit
    alignment although C runtime can't handle binary numbers smaller than
    8 bits right now.  Emit one-line function calls to parse and unparse
    binary 8-bit, 16-bit, 32-bit, 64-bit big-endian & little-endian binary
    integers.  Generate code to initialize an integer array, parse data
    into the array, and unparse data from the array too.  Call
    e.schemaDefinitionUnless instead of e.SDE inside an if expression to
    avoid uncovered line of code warning as Mike suggested.
    
    In CodeGeneratorState.scala, add private qualifiedName and localName
    methods to generate unique C file-scope names for ERD objects and
    plain local names for structs/fields although we probably will need to
    prepend namespace prefixes to plain local names to disambiguate some
    structs/fields from each other later.  Make changes to support arrays
    and binary floats as well as binary integers.  Include arrays in
    struct declarations and ERD objects' count of children and offset
    computations.  Change parseSelf and unparseSelf to return void instead
    of const char *error_msg.  Shorten ${C}_compute_ERD_offsets to
    ${C}_compute_offsets.
    
    In Runtime2TDMLDFDLProcessor.scala, make getProcessor create a
    temporary unique directory per call instead of using the same cache
    directory from dev.dirs.ProjectDirectories.  Get codeDir from
    generateCode and pass codeDir to compileCode instead of outputDir.
    Pass temporary directory to Runtime2TDMLDFDLProcessor,
    Runtime2TDMLParseResult, and Runtime2TDMLUnparseResult and implement
    cleanUp() in Runtime2TDMLParseResult and Runtime2TDMLUnparseResult to
    allow us to delete temporary directory later.
    
    In TestRuntime2.dfdl.xsd, rename ex_ints to ex_nums and make it define
    floating point numbers as well as integer numbers.  Use nested
    elements again to ensure more code is executed by tests according to
    coverage report.  Add two fixed occurrence arrays (integer and float)
    to ex_nums.  Move orion_command and its simple types to
    orion-command.xml.
    
    In TestRuntime2.tdml, rename ex_ints tests to ex_nums.  Move
    orion_command tests to orion-command.tdml.  Use ex_nums_unparse1.xml
    with runtime1 and ex_nums_unparse2.xml with runtime2 to demonstrate
    differences in XML floating point output between both runtimes.
    
    In command_parse.dat, rename from orion_command_parse.dat to
    command_parse.dat.  Change tilt field's value from -21231 to -1231 to
    fit new constraint in orion-command.dfdl.xsd.
    
    In command_unparse.xml, rename from orion_command_unparse.xml to
    command_unparse.xml.  Change tilt field's value from -21231 to -1231
    to fit new constraint in orion-command.dfdl.xsd.
    
    In ex_nums_parse.dat, rename from ex_ints_parse.dat to
    ex_nums_parse.dat.  Add arrays and real numbers.  Make two of the real
    numbers INF and NaN to ensure fixNumberIfNeeded gets tested.
    
    In ex_nums_unparse1.xml, rename from ex_nums_unparse.xml, add arrays
    and real numbers, and split into ex_nums_unparse1.xml and
    ex_nums_unparse2.xml to demonstrate differences in XML floating point
    output between both runtimes.
    
    In orion-command.dfdl.xsd, add new test schema with Command,
    CameraState, and VideoSettings elements.
    
    In orion-command.tdml, add new test cases for Command and
    VideoSettings elements.
    
    In video_settings_parse.dat, add data for VideoSettings element.
    
    In video_settings_unparse.xml, add infoset for VideoSettings element.
    
    In TestCodeGenerator.scala, rename outputDir to tempDir, get codeDir
    from generateCode, and pass codeDir to compileCode instead of
    outputDir.
    
    In TestOrionCommand.scala, run test cases in orion-command.tdml as
    part of sbt tests.  Note that tests might run in parallel (that is,
    TestOrionCommand.scala and TestRuntime2.scala can overlap each other
    concurrently).
    
    In TestRuntime2.scala, rename ex_ints to ex_nums.  Move orion_command
    test cases to TestOrionCommand.scala.  Change names and add 2 more
    methods to match renamed & new test cases in TestRuntime2.tdml.
    
    In TDMLRunner.scala, replace duplicate lines of code deleting blob
    files with cleanUp() calls.  Add two new cleanUp() calls in
    UnparserTestCase to ensure unparse tests clean up temporary files too.
    
    In TDMLDFDLProcessor.scala, add a new cleanUp() abstract function to
    TDMLResult.
    
    In DaffodilTDMLDFDLProcessor.scala, make DaffodilTDMLParseResult and
    DaffodilTDMLUnparseResult implement cleanUp() to remove blob files or
    do nothing respectively.
    
    In Dependencies.scala, remove "dev.dirs" % "directories" since we
    don't need it anymore.
    
    In Rat.scala, tell Rat to ignore new/renamed test data files.
---
 .github/workflows/main.yml                         |   2 +-
 README.md                                          |  28 +-
 daffodil-cli/bin.LICENSE                           | 384 +----------
 .../daffodil/generating/TestCLIGenerateC.scala     |   6 +-
 daffodil-runtime2/src/main/resources/c/Makefile    |   4 +-
 .../src/main/resources/c/libcli/daffodil_argp.c    |  10 +-
 .../src/main/resources/c/libcli/daffodil_main.c    |  33 +-
 .../src/main/resources/c/libcli/stack.c            |   8 +-
 .../src/main/resources/c/libcli/stack.h            |   6 +-
 .../src/main/resources/c/libcli/xml_reader.c       | 124 +++-
 .../src/main/resources/c/libcli/xml_reader.h       |   6 +-
 .../src/main/resources/c/libcli/xml_writer.c       |  62 +-
 .../src/main/resources/c/libcli/xml_writer.h       |   6 +-
 .../src/main/resources/c/libruntime/infoset.c      |   8 +-
 .../src/main/resources/c/libruntime/infoset.h      |  30 +-
 .../src/main/resources/c/libruntime/parsers.c      | 111 +++
 .../src/main/resources/c/libruntime/parsers.h      |  52 ++
 .../src/main/resources/c/libruntime/unparsers.c    | 111 +++
 .../src/main/resources/c/libruntime/unparsers.h    |  52 ++
 .../src/main/resources/examples/ex_ints.c          | 766 ---------------------
 .../src/main/resources/examples/ex_nums.c          | 684 ++++++++++++++++++
 .../resources/examples/{ex_ints.h => ex_nums.h}    |  32 +-
 .../apache/daffodil/runtime2/CodeGenerator.scala   |  27 +-
 .../daffodil/runtime2/Runtime2CodeGenerator.scala  |  18 +-
 .../generators/BinaryFloatCodeGenerator.scala      |  55 ++
 .../BinaryIntegerKnownLengthCodeGenerator.scala    |  59 +-
 .../runtime2/generators/CodeGeneratorState.scala   | 137 ++--
 .../runtime2/Runtime2TDMLDFDLProcessor.scala       |  28 +-
 .../apache/daffodil/runtime2/TestRuntime2.dfdl.xsd | 102 ++-
 .../org/apache/daffodil/runtime2/TestRuntime2.tdml |  75 +-
 .../org/apache/daffodil/runtime2/command_parse.dat | Bin 0 -> 13 bytes
 ...ion_command_unparse.xml => command_unparse.xml} |   8 +-
 .../org/apache/daffodil/runtime2/ex_ints_parse.dat | Bin 60 -> 0 bytes
 .../org/apache/daffodil/runtime2/ex_nums_parse.dat | Bin 0 -> 102 bytes
 .../apache/daffodil/runtime2/ex_nums_unparse1.xml  |  52 ++
 .../apache/daffodil/runtime2/ex_nums_unparse2.xml  |  52 ++
 .../daffodil/runtime2/orion-command.dfdl.xsd       | 104 +++
 .../apache/daffodil/runtime2/orion-command.tdml    |  92 +++
 .../daffodil/runtime2/orion_command_parse.dat      | Bin 13 -> 0 bytes
 .../daffodil/runtime2/video_settings_parse.dat     | Bin 0 -> 20 bytes
 ...ints_unparse.xml => video_settings_unparse.xml} |  37 +-
 .../daffodil/runtime2/TestCodeGenerator.scala      |  26 +-
 .../{TestRuntime2.scala => TestOrionCommand.scala} |  16 +-
 .../apache/daffodil/runtime2/TestRuntime2.scala    |   8 +-
 .../org/apache/daffodil/tdml/TDMLRunner.scala      |  42 +-
 .../tdml/processor/TDMLDFDLProcessor.scala         |   5 +-
 .../tdml/processor/DaffodilTDMLDFDLProcessor.scala |   5 +
 project/Dependencies.scala                         |   1 -
 project/Rat.scala                                  |   5 +-
 49 files changed, 1923 insertions(+), 1556 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 38bfa61..2679df5 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -53,7 +53,7 @@ jobs:
         if: runner.os == 'Windows'
         uses: msys2/setup-msys2@v2
         with:
-          install: gcc libargp-devel make pkg-config
+          install: gcc libargp-devel make pkgconf
           path-type: inherit
 
       - name: Check out mxml source (Windows)
diff --git a/README.md b/README.md
index 991d688..9097223 100644
--- a/README.md
+++ b/README.md
@@ -38,17 +38,28 @@ For more information about Daffodil, see https://daffodil.apache.org/.
 
 * JDK 8 or higher
 * SBT 0.13.8 or higher
+* C compiler (for daffodil-runtime2 only)
+* Mini-XML Version 3.2 or higher (for daffodil-runtime2 only)
 
 ## Getting Started
 
-[SBT] is the officially supported tool to build Daffodil, run all tests, create packages,
-and more. Below are some of the more common commands used for Daffodil development.
+You will need the full Java Software Development Kit ([JDK] or [SDK]),
+not the Java Runtime Environment (JRE), to build Daffodil.  You also
+will need [SBT] to build Daffodil, run all tests, create packages, and
+more.
+
+In order to build daffodil-runtime2, you will need a C compiler (for
+example, [gcc]), the [Mini-XML] library, and possibly the [argp]
+library if your system doesn't include it in its C library.
+
+Below are some of the more common commands used for Daffodil development.
 
 ### Compile
 
 ```text
 $ sbt compile
 ```
+
 ### Tests
 
 Run all unit tests:
@@ -100,18 +111,19 @@ users@daffodil.apache.org mailing lists. Bugs can be reported via the [Daffodil
 
 Apache Daffodil is licensed under the [Apache License, v2.0].
 
-
-
-
 [Apache License, v2.0]: https://www.apache.org/licenses/LICENSE-2.0
 [Apache RAT]: https://creadur.apache.org/rat/
 [CodeCov]: https://codecov.io/gh/apache/daffodil/
 [Command Line Interface]: https://daffodil.apache.org/cli/
-[Daffodil JIRA]: https://issues.apache.org/jira/projects/DAFFODIL
 [DFDL specification]: http://www.ogf.org/dfdl
-[Open Grid Forum]: http://www.ogf.org
+[Daffodil JIRA]: https://issues.apache.org/jira/projects/DAFFODIL
+[Github Actions]: https://github.com/apache/daffodil/actions?query=branch%3Amaster+
+[JDK]: https://docs.oracle.com/en/java/javase/11/install/overview-jdk-installation.html
+[Mini-XML]: https://www.msweet.org/mxml/
 [Releases]: http://daffodil.apache.org/releases/
 [SBT]: http://www.scala-sbt.org
-[Github Actions]: https://github.com/apache/daffodil/actions?query=branch%3Amaster+
+[SDK]: https://sdkman.io
 [Website]: https://daffodil.apache.org
+[argp]: https://packages.msys2.org/package/libargp-devel
+[gcc]: https://linuxize.com/post/how-to-install-gcc-on-ubuntu-20-04/
 [sbt-scoverage]: https://github.com/scoverage/sbt-scoverage
diff --git a/daffodil-cli/bin.LICENSE b/daffodil-cli/bin.LICENSE
index 63c4098..07241dc 100644
--- a/daffodil-cli/bin.LICENSE
+++ b/daffodil-cli/bin.LICENSE
@@ -1446,11 +1446,15 @@ is subject to the terms and conditions of the following licenses.
     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     THE SOFTWARE.
 
-  This product bundles libraries from 'libaoyi', including the following files:
+  This product bundles libraries from 'os-lib', including the following files:
     - lib/com.lihaoyi.geany_<VERSION>.jar
     - lib/com.lihaoyi.os-lib_<VERSION>.jar
   These files are available under the MIT license:
 
+    License
+    =======
+
+
     The MIT License (MIT)
 
     Copyright (c) 2019 Li Haoyi (haoyi.sg@gmail.com)
@@ -1472,381 +1476,3 @@ is subject to the terms and conditions of the following licenses.
     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     DEALINGS IN THE SOFTWARE.
-
-  This product bundles 'directories-jvm', including the following files:
-    - lib/dirs-dev.directories_<VERSION>.jar
-  These files are available under the Mozilla 2.0 license:
-
-    Mozilla Public License Version 2.0
-    ==================================
-
-    1. Definitions
-    --------------
-
-    1.1. "Contributor"
-        means each individual or legal entity that creates, contributes to
-        the creation of, or owns Covered Software.
-
-    1.2. "Contributor Version"
-        means the combination of the Contributions of others (if any) used
-        by a Contributor and that particular Contributor's Contribution.
-
-    1.3. "Contribution"
-        means Covered Software of a particular Contributor.
-
-    1.4. "Covered Software"
-        means Source Code Form to which the initial Contributor has attached
-        the notice in Exhibit A, the Executable Form of such Source Code
-        Form, and Modifications of such Source Code Form, in each case
-        including portions thereof.
-
-    1.5. "Incompatible With Secondary Licenses"
-        means
-
-        (a) that the initial Contributor has attached the notice described
-            in Exhibit B to the Covered Software; or
-
-        (b) that the Covered Software was made available under the terms of
-            version 1.1 or earlier of the License, but not also under the
-            terms of a Secondary License.
-
-    1.6. "Executable Form"
-        means any form of the work other than Source Code Form.
-
-    1.7. "Larger Work"
-        means a work that combines Covered Software with other material, in
-        a separate file or files, that is not Covered Software.
-
-    1.8. "License"
-        means this document.
-
-    1.9. "Licensable"
-        means having the right to grant, to the maximum extent possible,
-        whether at the time of the initial grant or subsequently, any and
-        all of the rights conveyed by this License.
-
-    1.10. "Modifications"
-        means any of the following:
-
-        (a) any file in Source Code Form that results from an addition to,
-            deletion from, or modification of the contents of Covered
-            Software; or
-
-        (b) any new file in Source Code Form that contains any Covered
-            Software.
-
-    1.11. "Patent Claims" of a Contributor
-        means any patent claim(s), including without limitation, method,
-        process, and apparatus claims, in any patent Licensable by such
-        Contributor that would be infringed, but for the grant of the
-        License, by the making, using, selling, offering for sale, having
-        made, import, or transfer of either its Contributions or its
-        Contributor Version.
-
-    1.12. "Secondary License"
-        means either the GNU General Public License, Version 2.0, the GNU
-        Lesser General Public License, Version 2.1, the GNU Affero General
-        Public License, Version 3.0, or any later versions of those
-        licenses.
-
-    1.13. "Source Code Form"
-        means the form of the work preferred for making modifications.
-
-    1.14. "You" (or "Your")
-        means an individual or a legal entity exercising rights under this
-        License. For legal entities, "You" includes any entity that
-        controls, is controlled by, or is under common control with You. For
-        purposes of this definition, "control" means (a) the power, direct
-        or indirect, to cause the direction or management of such entity,
-        whether by contract or otherwise, or (b) ownership of more than
-        fifty percent (50%) of the outstanding shares or beneficial
-        ownership of such entity.
-
-    2. License Grants and Conditions
-    --------------------------------
-
-    2.1. Grants
-
-    Each Contributor hereby grants You a world-wide, royalty-free,
-    non-exclusive license:
-
-    (a) under intellectual property rights (other than patent or trademark)
-        Licensable by such Contributor to use, reproduce, make available,
-        modify, display, perform, distribute, and otherwise exploit its
-        Contributions, either on an unmodified basis, with Modifications, or
-        as part of a Larger Work; and
-
-    (b) under Patent Claims of such Contributor to make, use, sell, offer
-        for sale, have made, import, and otherwise transfer either its
-        Contributions or its Contributor Version.
-
-    2.2. Effective Date
-
-    The licenses granted in Section 2.1 with respect to any Contribution
-    become effective for each Contribution on the date the Contributor first
-    distributes such Contribution.
-
-    2.3. Limitations on Grant Scope
-
-    The licenses granted in this Section 2 are the only rights granted under
-    this License. No additional rights or licenses will be implied from the
-    distribution or licensing of Covered Software under this License.
-    Notwithstanding Section 2.1(b) above, no patent license is granted by a
-    Contributor:
-
-    (a) for any code that a Contributor has removed from Covered Software;
-        or
-
-    (b) for infringements caused by: (i) Your and any other third party's
-        modifications of Covered Software, or (ii) the combination of its
-        Contributions with other software (except as part of its Contributor
-        Version); or
-
-    (c) under Patent Claims infringed by Covered Software in the absence of
-        its Contributions.
-
-    This License does not grant any rights in the trademarks, service marks,
-    or logos of any Contributor (except as may be necessary to comply with
-    the notice requirements in Section 3.4).
-
-    2.4. Subsequent Licenses
-
-    No Contributor makes additional grants as a result of Your choice to
-    distribute the Covered Software under a subsequent version of this
-    License (see Section 10.2) or under the terms of a Secondary License (if
-    permitted under the terms of Section 3.3).
-
-    2.5. Representation
-
-    Each Contributor represents that the Contributor believes its
-    Contributions are its original creation(s) or it has sufficient rights
-    to grant the rights to its Contributions conveyed by this License.
-
-    2.6. Fair Use
-
-    This License is not intended to limit any rights You have under
-    applicable copyright doctrines of fair use, fair dealing, or other
-    equivalents.
-
-    2.7. Conditions
-
-    Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
-    in Section 2.1.
-
-    3. Responsibilities
-    -------------------
-
-    3.1. Distribution of Source Form
-
-    All distribution of Covered Software in Source Code Form, including any
-    Modifications that You create or to which You contribute, must be under
-    the terms of this License. You must inform recipients that the Source
-    Code Form of the Covered Software is governed by the terms of this
-    License, and how they can obtain a copy of this License. You may not
-    attempt to alter or restrict the recipients' rights in the Source Code
-    Form.
-
-    3.2. Distribution of Executable Form
-
-    If You distribute Covered Software in Executable Form then:
-
-    (a) such Covered Software must also be made available in Source Code
-        Form, as described in Section 3.1, and You must inform recipients of
-        the Executable Form how they can obtain a copy of such Source Code
-        Form by reasonable means in a timely manner, at a charge no more
-        than the cost of distribution to the recipient; and
-
-    (b) You may distribute such Executable Form under the terms of this
-        License, or sublicense it under different terms, provided that the
-        license for the Executable Form does not attempt to limit or alter
-        the recipients' rights in the Source Code Form under this License.
-
-    3.3. Distribution of a Larger Work
-
-    You may create and distribute a Larger Work under terms of Your choice,
-    provided that You also comply with the requirements of this License for
-    the Covered Software. If the Larger Work is a combination of Covered
-    Software with a work governed by one or more Secondary Licenses, and the
-    Covered Software is not Incompatible With Secondary Licenses, this
-    License permits You to additionally distribute such Covered Software
-    under the terms of such Secondary License(s), so that the recipient of
-    the Larger Work may, at their option, further distribute the Covered
-    Software under the terms of either this License or such Secondary
-    License(s).
-
-    3.4. Notices
-
-    You may not remove or alter the substance of any license notices
-    (including copyright notices, patent notices, disclaimers of warranty,
-    or limitations of liability) contained within the Source Code Form of
-    the Covered Software, except that You may alter any license notices to
-    the extent required to remedy known factual inaccuracies.
-
-    3.5. Application of Additional Terms
-
-    You may choose to offer, and to charge a fee for, warranty, support,
-    indemnity or liability obligations to one or more recipients of Covered
-    Software. However, You may do so only on Your own behalf, and not on
-    behalf of any Contributor. You must make it absolutely clear that any
-    such warranty, support, indemnity, or liability obligation is offered by
-    You alone, and You hereby agree to indemnify every Contributor for any
-    liability incurred by such Contributor as a result of warranty, support,
-    indemnity or liability terms You offer. You may include additional
-    disclaimers of warranty and limitations of liability specific to any
-    jurisdiction.
-
-    4. Inability to Comply Due to Statute or Regulation
-    ---------------------------------------------------
-
-    If it is impossible for You to comply with any of the terms of this
-    License with respect to some or all of the Covered Software due to
-    statute, judicial order, or regulation then You must: (a) comply with
-    the terms of this License to the maximum extent possible; and (b)
-    describe the limitations and the code they affect. Such description must
-    be placed in a text file included with all distributions of the Covered
-    Software under this License. Except to the extent prohibited by statute
-    or regulation, such description must be sufficiently detailed for a
-    recipient of ordinary skill to be able to understand it.
-
-    5. Termination
-    --------------
-
-    5.1. The rights granted under this License will terminate automatically
-    if You fail to comply with any of its terms. However, if You become
-    compliant, then the rights granted under this License from a particular
-    Contributor are reinstated (a) provisionally, unless and until such
-    Contributor explicitly and finally terminates Your grants, and (b) on an
-    ongoing basis, if such Contributor fails to notify You of the
-    non-compliance by some reasonable means prior to 60 days after You have
-    come back into compliance. Moreover, Your grants from a particular
-    Contributor are reinstated on an ongoing basis if such Contributor
-    notifies You of the non-compliance by some reasonable means, this is the
-    first time You have received notice of non-compliance with this License
-    from such Contributor, and You become compliant prior to 30 days after
-    Your receipt of the notice.
-
-    5.2. If You initiate litigation against any entity by asserting a patent
-    infringement claim (excluding declaratory judgment actions,
-    counter-claims, and cross-claims) alleging that a Contributor Version
-    directly or indirectly infringes any patent, then the rights granted to
-    You by any and all Contributors for the Covered Software under Section
-    2.1 of this License shall terminate.
-
-    5.3. In the event of termination under Sections 5.1 or 5.2 above, all
-    end user license agreements (excluding distributors and resellers) which
-    have been validly granted by You or Your distributors under this License
-    prior to termination shall survive termination.
-
-    ************************************************************************
-    *                                                                      *
-    *  6. Disclaimer of Warranty                                           *
-    *  -------------------------                                           *
-    *                                                                      *
-    *  Covered Software is provided under this License on an "as is"       *
-    *  basis, without warranty of any kind, either expressed, implied, or  *
-    *  statutory, including, without limitation, warranties that the       *
-    *  Covered Software is free of defects, merchantable, fit for a        *
-    *  particular purpose or non-infringing. The entire risk as to the     *
-    *  quality and performance of the Covered Software is with You.        *
-    *  Should any Covered Software prove defective in any respect, You     *
-    *  (not any Contributor) assume the cost of any necessary servicing,   *
-    *  repair, or correction. This disclaimer of warranty constitutes an   *
-    *  essential part of this License. No use of any Covered Software is   *
-    *  authorized under this License except under this disclaimer.         *
-    *                                                                      *
-    ************************************************************************
-
-    ************************************************************************
-    *                                                                      *
-    *  7. Limitation of Liability                                          *
-    *  --------------------------                                          *
-    *                                                                      *
-    *  Under no circumstances and under no legal theory, whether tort      *
-    *  (including negligence), contract, or otherwise, shall any           *
-    *  Contributor, or anyone who distributes Covered Software as          *
-    *  permitted above, be liable to You for any direct, indirect,         *
-    *  special, incidental, or consequential damages of any character      *
-    *  including, without limitation, damages for lost profits, loss of    *
-    *  goodwill, work stoppage, computer failure or malfunction, or any    *
-    *  and all other commercial damages or losses, even if such party      *
-    *  shall have been informed of the possibility of such damages. This   *
-    *  limitation of liability shall not apply to liability for death or   *
-    *  personal injury resulting from such party's negligence to the       *
-    *  extent applicable law prohibits such limitation. Some               *
-    *  jurisdictions do not allow the exclusion or limitation of           *
-    *  incidental or consequential damages, so this exclusion and          *
-    *  limitation may not apply to You.                                    *
-    *                                                                      *
-    ************************************************************************
-
-    8. Litigation
-    -------------
-
-    Any litigation relating to this License may be brought only in the
-    courts of a jurisdiction where the defendant maintains its principal
-    place of business and such litigation shall be governed by laws of that
-    jurisdiction, without reference to its conflict-of-law provisions.
-    Nothing in this Section shall prevent a party's ability to bring
-    cross-claims or counter-claims.
-
-    9. Miscellaneous
-    ----------------
-
-    This License represents the complete agreement concerning the subject
-    matter hereof. If any provision of this License is held to be
-    unenforceable, such provision shall be reformed only to the extent
-    necessary to make it enforceable. Any law or regulation which provides
-    that the language of a contract shall be construed against the drafter
-    shall not be used to construe this License against a Contributor.
-
-    10. Versions of the License
-    ---------------------------
-
-    10.1. New Versions
-
-    Mozilla Foundation is the license steward. Except as provided in Section
-    10.3, no one other than the license steward has the right to modify or
-    publish new versions of this License. Each version will be given a
-    distinguishing version number.
-
-    10.2. Effect of New Versions
-
-    You may distribute the Covered Software under the terms of the version
-    of the License under which You originally received the Covered Software,
-    or under the terms of any subsequent version published by the license
-    steward.
-
-    10.3. Modified Versions
-
-    If you create software not governed by this License, and you want to
-    create a new license for such software, you may create and use a
-    modified version of this License if you rename the license and remove
-    any references to the name of the license steward (except to note that
-    such modified license differs from this License).
-
-    10.4. Distributing Source Code Form that is Incompatible With Secondary
-    Licenses
-
-    If You choose to distribute Source Code Form that is Incompatible With
-    Secondary Licenses under the terms of this version of the License, the
-    notice described in Exhibit B of this License must be attached.
-
-    Exhibit A - Source Code Form License Notice
-    -------------------------------------------
-
-      This Source Code Form is subject to the terms of the Mozilla Public
-      License, v. 2.0. If a copy of the MPL was not distributed with this
-      file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-    If it is not possible or desirable to put the notice in a particular
-    file, then You may include the notice in a location (such as a LICENSE
-    file in a relevant directory) where a recipient would be likely to look
-    for such a notice.
-
-    You may add additional accurate notices of copyright ownership.
-
-    Exhibit B - "Incompatible With Secondary Licenses" Notice
-    ---------------------------------------------------------
-
-      This Source Code Form is "Incompatible With Secondary Licenses", as
-      defined by the Mozilla Public License, v. 2.0.
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
index de004d2..6700b66 100644
--- a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -138,7 +138,7 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_root(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_ints $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_nums $outputDir"
     val exitCmd = "exit"
 
     val shell = Util.start("")
@@ -154,14 +154,14 @@ class TestCLIGenerateC {
   }
 
   @Test def test_CLI_Generate_root_error(): Unit = {
-    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_ints $outputDir"
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_nums $outputDir"
     val exitCmd = "exit"
 
     val shell = Util.start("", expectErr = true)
     try {
       shell.sendLine(generateCmd)
       shell.expect(contains("Schema Definition Error"))
-      shell.expect(contains("No global element found for {ex}ex_ints"))
+      shell.expect(contains("No global element found for {ex}ex_nums"))
       shell.sendLine(exitCmd)
       shell.expect(eof())
     } finally {
diff --git a/daffodil-runtime2/src/main/resources/c/Makefile b/daffodil-runtime2/src/main/resources/c/Makefile
index d3fcb79..fd1cf8d 100644
--- a/daffodil-runtime2/src/main/resources/c/Makefile
+++ b/daffodil-runtime2/src/main/resources/c/Makefile
@@ -19,10 +19,10 @@
 
 SOURCES = libcli/*.[ch] libruntime/*.[ch]
 PROGRAM = ./daffodil
-CFLAGS = -Wall
+CFLAGS = -g -Wall -Wextra -Wno-missing-field-initializers
 
 $(PROGRAM): $(SOURCES)
-	$(CC) $(CFLAGS) -o $(PROGRAM) -I libcli -I libruntime $(SOURCES) -lmxml -lpthread -lm
+	$(CC) $(CFLAGS) -I libcli -I libruntime $(SOURCES) -lmxml -o $(PROGRAM)
 
 # Here's how to run parse/unparse tests (.dat <-> .xml, although you
 # will need to create the .dat and .xml files first)
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
index 7e27972..0b4e911 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_argp.c
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-#include "daffodil_argp.h" // for daffodil_cli, daffodil_parse_cli, ...
-#include <argp.h>          // for argp_state, argp_error, error_t, argp_parse
-#include <stdio.h>         // for sprintf
-#include <stdlib.h>        // for putenv, NULL
-#include <string.h>        // for strlen, strcmp
+#include "daffodil_argp.h"
+#include <argp.h>    // for argp_state, argp_error, error_t, argp_parse, ARGP_ERR_UNKNOWN, ARGP_IN_ORDER, ARGP_KEY_ARG, argp, argp_option, ARGP_KEY_END
+#include <stdio.h>   // for sprintf, NULL
+#include <stdlib.h>  // for putenv
+#include <string.h>  // for strlen, strcmp
 
 // Initialize our "daffodil" name and version
 
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
index ce6d62b..f915d9f 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/daffodil_main.c
@@ -15,14 +15,14 @@
  * limitations under the License.
  */
 
-#include "daffodil_argp.h" // for daffodil_cli, parse_daffodil_cli, ...
-#include "infoset.h"       // for InfosetBase, walkInfoset, rootElement, ...
-#include "xml_reader.h"    // for xmlReaderMethods, XMLReader
-#include "xml_writer.h"    // for xmlWriterMethods, XMLWriter
-#include <error.h>         // for error
-#include <stdio.h>         // for FILE, perror, fclose, fopen, stdin
-#include <stdlib.h>        // for exit, EXIT_FAILURE
-#include <string.h>        // for strcmp
+#include "daffodil_argp.h"  // for daffodil_cli, daffodil_parse, daffodil_parse_cli, daffodil_unparse, daffodil_unparse_cli, parse_daffodil_cli, DAFFODIL_PARSE, DAFFODIL_UNPARSE
+#include "infoset.h"        // for walkInfoset, InfosetBase, rootElement, ERD, PState, UState, VisitEventHandler
+#include "xml_reader.h"     // for xmlReaderMethods, XMLReader
+#include "xml_writer.h"     // for xmlWriterMethods, XMLWriter
+#include <error.h>          // for error
+#include <stdio.h>          // for FILE, perror, fclose, fopen, stdin, stdout
+#include <stdlib.h>         // for exit, EXIT_FAILURE
+#include <string.h>         // for strcmp
 
 // Open a file or exit if it can't be opened
 
@@ -85,15 +85,16 @@ main(int argc, char *argv[])
             output = fopen_or_exit(output, daffodil_parse.outfile, "w");
 
             // Parse the input file into our infoset.
-            PState      pstate = {input};
-            const char *error_msg = root->erd->parseSelf(root, &pstate);
-            continue_or_exit(error_msg);
+            PState pstate = {input};
+            root->erd->parseSelf(root, &pstate);
+            continue_or_exit(pstate.error_msg);
 
             if (strcmp(daffodil_parse.infoset_converter, "xml") == 0)
             {
                 // Visit the infoset and print XML from it.
-                XMLWriter xmlWriter = {xmlWriterMethods, output};
-                error_msg = walkInfoset((VisitEventHandler *)&xmlWriter, root);
+                XMLWriter   xmlWriter = {xmlWriterMethods, output};
+                const char *error_msg =
+                    walkInfoset((VisitEventHandler *)&xmlWriter, root);
                 continue_or_exit(error_msg);
             }
             else
@@ -123,9 +124,9 @@ main(int argc, char *argv[])
             }
 
             // Unparse our infoset to the output file.
-            UState      ustate = {output};
-            const char *error_msg = root->erd->unparseSelf(root, &ustate);
-            continue_or_exit(error_msg);
+            UState ustate = {output};
+            root->erd->unparseSelf(root, &ustate);
+            continue_or_exit(ustate.error_msg);
         }
 
         // Close our input and out files if we opened them.
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/stack.c b/daffodil-runtime2/src/main/resources/c/libcli/stack.c
index c1814bb..08c1561 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/stack.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/stack.c
@@ -16,10 +16,10 @@
  */
 
 #include "stack.h"
-#include <error.h>   // for error
-#include <stdbool.h> // for bool
-#include <stddef.h>  // for ptrdiff_t
-#include <stdlib.h>  // for EXIT_FAILURE
+#include <error.h>    // for error
+#include <stdbool.h>  // for bool
+#include <stddef.h>   // for ptrdiff_t
+#include <stdlib.h>   // for EXIT_FAILURE
 
 // Initialize stack with preallocated array
 
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/stack.h b/daffodil-runtime2/src/main/resources/c/libcli/stack.h
index bf1cf3a..0db5c32 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/stack.h
+++ b/daffodil-runtime2/src/main/resources/c/libcli/stack.h
@@ -18,9 +18,9 @@
 #ifndef STACK_H
 #define STACK_H
 
-#include <mxml.h>    // for mxml_node_t
-#include <stdbool.h> // for bool
-#include <stddef.h>  // for ptrdiff_t
+#include <mxml.h>     // for mxml_node_t
+#include <stdbool.h>  // for bool
+#include <stddef.h>   // for ptrdiff_t
 
 // Type of element pushed into stack
 
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
index 175ca52..226b015 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.c
@@ -16,14 +16,15 @@
  */
 
 #include "xml_reader.h"
-#include <errno.h>    // for errno
-#include <inttypes.h> // for strtoimax
-#include <mxml.h>     // for mxmlWalkNext, mxmlGetType, mxmlGetElement, ...
-#include <stdint.h>   // for intmax_t, int32_t, INT32_MAX, INT32_MIN
-#include <string.h>   // for strcmp, strlen, strncmp
+#include <errno.h>     // for errno
+#include <inttypes.h>  // for strtoimax, strtoumax
+#include <mxml.h>      // for mxmlWalkNext, mxmlGetType, mxmlGetElement, MXML_DESCEND, MXML_OPAQUE, mxmlDelete, mxmlGetOpaque, mxmlLoadFile, MXML_OPAQUE_CALLBACK
+#include <stdint.h>    // for intmax_t, uintmax_t, int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t, INT16_MAX, INT16_MIN, INT32_MAX, INT32_MIN, INT64_MAX, INT64_MIN, INT8_MAX, INT8_MIN, UINT16_MAX, UINT32_MAX, UINT64_MAX, UINT8_MAX
+#include <stdlib.h>    // for strtod, strtof
+#include <string.h>    // for strcmp, strlen, strncmp
 
 // Convert an XML element's text to a signed integer (BSD function not
-// widely available, so roll our own function based on strtoimax)
+// widely available, so call strtoimax with our own error checking)
 
 static intmax_t
 strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
@@ -31,7 +32,7 @@ strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
 {
     char *endptr = NULL;
 
-    // Clear errno to detect failure after calling strtoimax
+    // Clear errno to detect error after calling strtoimax
     errno = 0;
     const intmax_t value = strtoimax(numptr, &endptr, 10);
 
@@ -60,15 +61,15 @@ strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
     return value;
 }
 
-// Convert an XML element's text to an unsigned integer (roll our own
-// function based on strtoumax)
+// Convert an XML element's text to an unsigned integer (call strtoumax
+// with our own error checking)
 
 static uintmax_t
 strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
 {
     char *endptr = NULL;
 
-    // Clear errno to detect failure after calling strtoumax
+    // Clear errno to detect error after calling strtoumax
     errno = 0;
     const uintmax_t value = strtoumax(numptr, &endptr, 10);
 
@@ -97,6 +98,72 @@ strtounum(const char *numptr, uintmax_t maxval, const char **errstrp)
     return value;
 }
 
+// Convert an XML element's text to a float (call strtof with our own
+// error checking)
+
+static float
+strtofnum(const char *numptr, const char **errstrp)
+{
+    char *endptr = NULL;
+
+    // Clear errno to detect error after calling strtof
+    errno = 0;
+    const float value = strtof(numptr, &endptr);
+
+    // Report any issues converting the string to a number
+    if (errno != 0)
+    {
+        *errstrp = "Error converting XML data to number";
+    }
+    else if (endptr == numptr)
+    {
+        *errstrp = "Found no number in XML data";
+    }
+    else if (*endptr != '\0')
+    {
+        *errstrp = "Found non-number characters in XML data";
+    }
+    else
+    {
+        *errstrp = NULL;
+    }
+
+    return value;
+}
+
+// Convert an XML element's text to a double (call strtod with our own
+// error checking)
+
+static double
+strtodnum(const char *numptr, const char **errstrp)
+{
+    char *endptr = NULL;
+
+    // Clear errno to detect error after calling strtod
+    errno = 0;
+    const double value = strtod(numptr, &endptr);
+
+    // Report any issues converting the string to a number
+    if (errno != 0)
+    {
+        *errstrp = "Error converting XML data to number";
+    }
+    else if (endptr == numptr)
+    {
+        *errstrp = "Found no number in XML data";
+    }
+    else if (*endptr != '\0')
+    {
+        *errstrp = "Found non-number characters in XML data";
+    }
+    else
+    {
+        *errstrp = NULL;
+    }
+
+    return value;
+}
+
 // Read XML data from file before walking infoset
 
 static const char *
@@ -199,10 +266,11 @@ xmlEndComplex(XMLReader *reader, const InfosetBase *base)
     return NULL;
 }
 
-// Read 8, 16, 32, or 64-bit signed/unsigned integer number from XML data
+// Read 8, 16, 32, or 64-bit signed/unsigned integer number or floating point
+// number from XML data
 
 static const char *
-xmlIntegerElem(XMLReader *reader, const ERD *erd, void *intLocation)
+xmlNumberElem(XMLReader *reader, const ERD *erd, void *numLocation)
 {
     // Consume any newlines or whitespace before the element
     while (mxmlGetType(reader->node) == MXML_OPAQUE)
@@ -221,47 +289,55 @@ xmlIntegerElem(XMLReader *reader, const ERD *erd, void *intLocation)
     {
         if (strcmp(name_from_xml, name_from_erd) == 0)
         {
-            // Check for any errors getting the integer number
+            // Check for any errors getting the number
             const char *errstr = NULL;
 
-            // Handle varying bit lengths of both signed & unsigned numbers
+            // Handle varying bit lengths of both signed & unsigned integers and
+            // floating point numbers
             const enum TypeCode typeCode = erd->typeCode;
             switch (typeCode)
             {
             case PRIMITIVE_UINT64:
-                *(uint64_t *)intLocation =
+                *(uint64_t *)numLocation =
                     (uint64_t)strtounum(number_from_xml, UINT64_MAX, &errstr);
                 break;
             case PRIMITIVE_UINT32:
-                *(uint32_t *)intLocation =
+                *(uint32_t *)numLocation =
                     (uint32_t)strtounum(number_from_xml, UINT32_MAX, &errstr);
                 break;
             case PRIMITIVE_UINT16:
-                *(uint16_t *)intLocation =
+                *(uint16_t *)numLocation =
                     (uint16_t)strtounum(number_from_xml, UINT16_MAX, &errstr);
                 break;
             case PRIMITIVE_UINT8:
-                *(uint8_t *)intLocation =
+                *(uint8_t *)numLocation =
                     (uint8_t)strtounum(number_from_xml, UINT8_MAX, &errstr);
                 break;
             case PRIMITIVE_INT64:
-                *(int64_t *)intLocation = (int64_t)strtonum(
+                *(int64_t *)numLocation = (int64_t)strtonum(
                     number_from_xml, INT64_MIN, INT64_MAX, &errstr);
                 break;
             case PRIMITIVE_INT32:
-                *(int32_t *)intLocation = (int32_t)strtonum(
+                *(int32_t *)numLocation = (int32_t)strtonum(
                     number_from_xml, INT32_MIN, INT32_MAX, &errstr);
                 break;
             case PRIMITIVE_INT16:
-                *(int16_t *)intLocation = (int16_t)strtonum(
+                *(int16_t *)numLocation = (int16_t)strtonum(
                     number_from_xml, INT16_MIN, INT16_MAX, &errstr);
                 break;
             case PRIMITIVE_INT8:
-                *(int8_t *)intLocation = (int8_t)strtonum(
+                *(int8_t *)numLocation = (int8_t)strtonum(
                     number_from_xml, INT8_MIN, INT8_MAX, &errstr);
                 break;
+            case PRIMITIVE_FLOAT:
+                *(float *)numLocation = strtofnum(number_from_xml, &errstr);
+                break;
+            case PRIMITIVE_DOUBLE:
+                *(double *)numLocation = strtodnum(number_from_xml, &errstr);
+                break;
             default:
-                errstr = "Unexpected ERD typeCode while reading integer from XML data";
+                errstr = "Unexpected ERD typeCode while reading number from "
+                         "XML data";
                 break;
             }
 
@@ -283,5 +359,5 @@ xmlIntegerElem(XMLReader *reader, const ERD *erd, void *intLocation)
 const VisitEventHandler xmlReaderMethods = {
     (VisitStartDocument)&xmlStartDocument, (VisitEndDocument)&xmlEndDocument,
     (VisitStartComplex)&xmlStartComplex,   (VisitEndComplex)&xmlEndComplex,
-    (VisitIntegerElem)&xmlIntegerElem,
+    (VisitNumberElem)&xmlNumberElem,
 };
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.h b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.h
index 3333f55..57ce1bd 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.h
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_reader.h
@@ -18,9 +18,9 @@
 #ifndef XML_READER_H
 #define XML_READER_H
 
-#include "infoset.h" // for VisitEventHandler, InfosetBase
-#include <mxml.h>    // for mxml_node_t
-#include <stdio.h>   // for FILE
+#include "infoset.h"  // for VisitEventHandler, InfosetBase
+#include <mxml.h>     // for mxml_node_t
+#include <stdio.h>    // for FILE
 
 // XMLReader - infoset visitor with methods to read XML
 
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
index 9a0be6d..073423e 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.c
@@ -16,11 +16,11 @@
  */
 
 #include "xml_writer.h"
-#include "stack.h"  // for stack_is_empty, stack_pop, stack_push, stack_top
-#include <assert.h> // for assert
-#include <mxml.h>   // for mxml_node_t, mxmlNewElement, mxmlNewOpaquef, ...
-#include <stdint.h> // for int32_t
-#include <stdio.h>  // for NULL, fflush
+#include "stack.h"   // for stack_is_empty, stack_pop, stack_push, stack_top, stack_init, stack_is_full
+#include <assert.h>  // for assert
+#include <mxml.h>    // for mxmlNewOpaquef, mxml_node_t, mxmlElementSetAttr, mxmlNewElement, mxmlDelete, mxmlNewXML, mxmlSaveFile, MXML_NO_CALLBACK
+#include <stdint.h>  // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
+#include <stdio.h>   // for NULL, fflush
 
 // Push new XML document on stack.  This function is not
 // thread-safe since it uses static storage.
@@ -90,10 +90,27 @@ xmlEndComplex(XMLWriter *writer, const InfosetBase *base)
     return complex ? NULL : "Underflowed the XML stack";
 }
 
-// Write 8, 16, 32, or 64-bit signed/unsigned integer as element
+// Fix a floating point number to conform to xsd:float syntax if needed
+
+static void
+fixNumberIfNeeded(const char *text)
+{
+    if (text[0] == 'N' && text[1] == 'A')
+    {
+        // xsd:float requires NaN to be capitalized correctly
+        char *modifyInPlace = (char *)text;
+        modifyInPlace[1] = 'a';
+    }
+    // These are not required by xsd:float, only to match runtime1 better
+    //  - Strip + from <f>E+<e> to get <f>E<e> (not worth it)
+    //  - Add .0 to 1 to get 1.0 (not worth it)
+}
+
+// Write 8, 16, 32, or 64-bit signed/unsigned Number or floating point number as
+// element
 
 static const char *
-xmlIntegerElem(XMLWriter *writer, const ERD *erd, const void *intLocation)
+xmlNumberElem(XMLWriter *writer, const ERD *erd, const void *numLocation)
 {
     mxml_node_t *parent = stack_top(&writer->stack);
     const char * name = get_erd_name(erd);
@@ -113,35 +130,46 @@ xmlIntegerElem(XMLWriter *writer, const ERD *erd, const void *intLocation)
     switch (typeCode)
     {
     case PRIMITIVE_UINT64:
-        text = mxmlNewOpaquef(simple, "%lu", *(const uint64_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%lu", *(const uint64_t *)numLocation);
         break;
     case PRIMITIVE_UINT32:
-        text = mxmlNewOpaquef(simple, "%u", *(const uint32_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%u", *(const uint32_t *)numLocation);
         break;
     case PRIMITIVE_UINT16:
-        text = mxmlNewOpaquef(simple, "%hu", *(const uint16_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%hu", *(const uint16_t *)numLocation);
         break;
     case PRIMITIVE_UINT8:
-        text = mxmlNewOpaquef(simple, "%hhu", *(const uint8_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%hhu", *(const uint8_t *)numLocation);
         break;
     case PRIMITIVE_INT64:
-        text = mxmlNewOpaquef(simple, "%li", *(const int64_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%li", *(const int64_t *)numLocation);
         break;
     case PRIMITIVE_INT32:
-        text = mxmlNewOpaquef(simple, "%i", *(const int32_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%i", *(const int32_t *)numLocation);
         break;
     case PRIMITIVE_INT16:
-        text = mxmlNewOpaquef(simple, "%hi", *(const int16_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%hi", *(const int16_t *)numLocation);
         break;
     case PRIMITIVE_INT8:
-        text = mxmlNewOpaquef(simple, "%hhi", *(const int8_t *)intLocation);
+        text = mxmlNewOpaquef(simple, "%hhi", *(const int8_t *)numLocation);
+        break;
+    case PRIMITIVE_FLOAT:
+        // Round-trippable float, shortest possible
+        text = mxmlNewOpaquef(simple, "%.9G", *(const float *)numLocation);
+        fixNumberIfNeeded(mxmlGetOpaque(text));
+        break;
+    case PRIMITIVE_DOUBLE:
+        // Round-trippable double, shortest possible
+        text = mxmlNewOpaquef(simple, "%.17lG", *(const double *)numLocation);
+        fixNumberIfNeeded(mxmlGetOpaque(text));
         break;
     default:
         // Let text remain NULL and report error below
         break;
     }
 
-    return (simple && text) ? NULL : "Error making new simple integer element";
+    return (simple && text) ? NULL
+                            : "Error making new simple numerical element";
 }
 
 // Initialize a struct with our visitor event handler methods
@@ -149,5 +177,5 @@ xmlIntegerElem(XMLWriter *writer, const ERD *erd, const void *intLocation)
 const VisitEventHandler xmlWriterMethods = {
     (VisitStartDocument)&xmlStartDocument, (VisitEndDocument)&xmlEndDocument,
     (VisitStartComplex)&xmlStartComplex,   (VisitEndComplex)&xmlEndComplex,
-    (VisitIntegerElem)&xmlIntegerElem,
+    (VisitNumberElem)&xmlNumberElem,
 };
diff --git a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.h b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.h
index 45d7a45..c49e2f0 100644
--- a/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.h
+++ b/daffodil-runtime2/src/main/resources/c/libcli/xml_writer.h
@@ -18,9 +18,9 @@
 #ifndef XML_WRITER_H
 #define XML_WRITER_H
 
-#include "infoset.h" // for VisitEventHandler
-#include "stack.h"   // for stack_t
-#include <stdio.h>   // for FILE
+#include "infoset.h"  // for VisitEventHandler
+#include "stack.h"    // for stack_t
+#include <stdio.h>    // for FILE
 
 // XMLWriter - infoset visitor with methods to output XML
 
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
index b30f92e..d40c351 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.c
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-#include "infoset.h" // for walkInfoset, VisitEventHandler, ...
+#include "infoset.h"
 #include <string.h>  // for memccpy
 
 // get_erd_name, get_erd_xmlns, get_erd_ns - get name and xmlns
@@ -136,7 +136,7 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
         // We use only one of these variables below depending on typeCode
         const InfosetBase *childNode =
             (const InfosetBase *)((const char *)infoNode + offset);
-        const void *intLocation =
+        const void *numLocation =
             (const void *)((const char *)infoNode + offset);
 
         // Need to handle more element types
@@ -154,8 +154,10 @@ walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
         case PRIMITIVE_INT32:
         case PRIMITIVE_INT16:
         case PRIMITIVE_INT8:
+        case PRIMITIVE_FLOAT:
+        case PRIMITIVE_DOUBLE:
             error_msg =
-                handler->visitIntegerElem(handler, childERD, intLocation);
+                handler->visitNumberElem(handler, childERD, numLocation);
             break;
         }
     }
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
index 523a0d6..d9b614c 100644
--- a/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/infoset.h
@@ -18,9 +18,8 @@
 #ifndef INFOSET_H
 #define INFOSET_H
 
-#include <stddef.h> // for ptrdiff_t
-#include <stdint.h> // for int32_t
-#include <stdio.h>  // for FILE, size_t
+#include <stddef.h>  // for ptrdiff_t, size_t
+#include <stdio.h>   // for FILE
 
 // Prototypes needed for compilation
 
@@ -37,10 +36,8 @@ typedef struct UState             UState;
 typedef struct VisitEventHandler  VisitEventHandler;
 
 typedef void (*ERDInitSelf)(InfosetBase *infoNode);
-typedef const char *(*ERDParseSelf)(InfosetBase * infoNode,
-                                    const PState *pstate);
-typedef const char *(*ERDUnparseSelf)(const InfosetBase *infoNode,
-                                      const UState *     ustate);
+typedef void (*ERDParseSelf)(InfosetBase *infoNode, PState *pstate);
+typedef void (*ERDUnparseSelf)(const InfosetBase *infoNode, UState *ustate);
 
 typedef const char *(*VisitStartDocument)(const VisitEventHandler *handler);
 typedef const char *(*VisitEndDocument)(const VisitEventHandler *handler);
@@ -48,9 +45,8 @@ typedef const char *(*VisitStartComplex)(const VisitEventHandler *handler,
                                          const InfosetBase *      base);
 typedef const char *(*VisitEndComplex)(const VisitEventHandler *handler,
                                        const InfosetBase *      base);
-typedef const char *(*VisitIntegerElem)(const VisitEventHandler *handler,
-                                        const ERD *              erd,
-                                        const void *             intLocation);
+typedef const char *(*VisitNumberElem)(const VisitEventHandler *handler,
+                                       const ERD *erd, const void *numLocation);
 
 // NamedQName - name of an infoset element
 
@@ -73,7 +69,9 @@ enum TypeCode
     PRIMITIVE_INT64,
     PRIMITIVE_INT32,
     PRIMITIVE_INT16,
-    PRIMITIVE_INT8
+    PRIMITIVE_INT8,
+    PRIMITIVE_FLOAT,
+    PRIMITIVE_DOUBLE
 };
 
 // ERD - element runtime data needed to parse/unparse objects
@@ -102,14 +100,16 @@ typedef struct InfosetBase
 
 typedef struct PState
 {
-    FILE *stream; // input to read from
+    FILE *      stream;    // input to read from
+    const char *error_msg; // to stop if an error happens
 } PState;
 
 // UState - unparser state while unparsing infoset
 
 typedef struct UState
 {
-    FILE *stream; // output to write to
+    FILE *      stream;    // output to write to
+    const char *error_msg; // to stop if an error happens
 } UState;
 
 // VisitEventHandler - methods to be called when walking an infoset
@@ -120,7 +120,7 @@ typedef struct VisitEventHandler
     const VisitEndDocument   visitEndDocument;
     const VisitStartComplex  visitStartComplex;
     const VisitEndComplex    visitEndComplex;
-    const VisitIntegerElem   visitIntegerElem;
+    const VisitNumberElem    visitNumberElem;
 } VisitEventHandler;
 
 // get_erd_name, get_erd_xmlns, get_erd_ns - get name and xmlns
@@ -133,7 +133,7 @@ extern const char *get_erd_ns(const ERD *erd);
 // rootElement - return a root element to walk while parsing or unparsing
 
 // (actual definition will be in generated_code.c, not infoset.c)
-extern InfosetBase *rootElement();
+extern InfosetBase *rootElement(void);
 
 // walkInfoset - walk an infoset and call VisitEventHandler methods
 
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
new file mode 100644
index 0000000..87a5f98
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.c
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "parsers.h"
+#include <endian.h>  // for be32toh, be64toh, le32toh, le64toh, be16toh, le16toh
+#include <stdio.h>   // for fread, size_t
+
+// Macros to expand into functions below
+
+#define define_parse_endian_real(endian, type, bits)                           \
+    extern void parse_##endian##_##type(type *number, PState *pstate)          \
+    {                                                                          \
+        if (!pstate->error_msg)                                                \
+        {                                                                      \
+            union                                                              \
+            {                                                                  \
+                char           c_val[sizeof(type)];                            \
+                type           f_val;                                          \
+                uint##bits##_t i_val;                                          \
+            } buffer;                                                          \
+            size_t count =                                                     \
+                fread(&buffer.c_val, 1, sizeof(buffer), pstate->stream);       \
+            if (count < sizeof(buffer))                                        \
+            {                                                                  \
+                pstate->error_msg = eof_or_error_msg(pstate->stream);          \
+            }                                                                  \
+            buffer.i_val = endian##bits##toh(buffer.i_val);                    \
+            *number = buffer.f_val;                                            \
+        }                                                                      \
+    }
+
+#define define_parse_endian_integer(endian, type, bits)                        \
+    extern void parse_##endian##_##type##bits(type##bits##_t *number,          \
+                                              PState *        pstate)          \
+    {                                                                          \
+        if (!pstate->error_msg)                                                \
+        {                                                                      \
+            union                                                              \
+            {                                                                  \
+                char           c_val[sizeof(type##bits##_t)];                  \
+                type##bits##_t i_val;                                          \
+            } buffer;                                                          \
+            size_t count =                                                     \
+                fread(&buffer.c_val, 1, sizeof(buffer), pstate->stream);       \
+            if (count < sizeof(buffer))                                        \
+            {                                                                  \
+                pstate->error_msg = eof_or_error_msg(pstate->stream);          \
+            }                                                                  \
+            *number = endian##bits##toh(buffer.i_val);                         \
+        }                                                                      \
+    }
+
+#define be8toh(var) var
+
+#define le8toh(var) var
+
+// Define functions to parse binary real and integer numbers
+
+define_parse_endian_real(be, double, 64)
+
+define_parse_endian_real(be, float, 32)
+
+define_parse_endian_integer(be, uint, 64)
+
+define_parse_endian_integer(be, uint, 32)
+
+define_parse_endian_integer(be, uint, 16)
+
+define_parse_endian_integer(be, uint, 8)
+
+define_parse_endian_integer(be, int, 64)
+
+define_parse_endian_integer(be, int, 32)
+
+define_parse_endian_integer(be, int, 16)
+
+define_parse_endian_integer(be, int, 8)
+
+define_parse_endian_real(le, double, 64)
+
+define_parse_endian_real(le, float, 32)
+
+define_parse_endian_integer(le, uint, 64)
+
+define_parse_endian_integer(le, uint, 32)
+
+define_parse_endian_integer(le, uint, 16)
+
+define_parse_endian_integer(le, uint, 8)
+
+define_parse_endian_integer(le, int, 64)
+
+define_parse_endian_integer(le, int, 32)
+
+define_parse_endian_integer(le, int, 16)
+
+define_parse_endian_integer(le, int, 8)
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h
new file mode 100644
index 0000000..1a4f831
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/parsers.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef PARSERS_H
+#define PARSERS_H
+
+#include "infoset.h"  // for PState
+#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
+
+// Functions to parse binary floating point numbers and integers
+
+extern void parse_be_double(double *number, PState *pstate);
+extern void parse_be_float(float *number, PState *pstate);
+
+extern void parse_be_uint64(uint64_t *number, PState *pstate);
+extern void parse_be_uint32(uint32_t *number, PState *pstate);
+extern void parse_be_uint16(uint16_t *number, PState *pstate);
+extern void parse_be_uint8(uint8_t *number, PState *pstate);
+
+extern void parse_be_int64(int64_t *number, PState *pstate);
+extern void parse_be_int32(int32_t *number, PState *pstate);
+extern void parse_be_int16(int16_t *number, PState *pstate);
+extern void parse_be_int8(int8_t *number, PState *pstate);
+
+extern void parse_le_double(double *number, PState *pstate);
+extern void parse_le_float(float *number, PState *pstate);
+
+extern void parse_le_uint64(uint64_t *number, PState *pstate);
+extern void parse_le_uint32(uint32_t *number, PState *pstate);
+extern void parse_le_uint16(uint16_t *number, PState *pstate);
+extern void parse_le_uint8(uint8_t *number, PState *pstate);
+
+extern void parse_le_int64(int64_t *number, PState *pstate);
+extern void parse_le_int32(int32_t *number, PState *pstate);
+extern void parse_le_int16(int16_t *number, PState *pstate);
+extern void parse_le_int8(int8_t *number, PState *pstate);
+
+#endif // PARSERS_H
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
new file mode 100644
index 0000000..93cddbd
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.c
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "unparsers.h"
+#include <endian.h>  // for htobe32, htobe64, htole32, htole64, htobe16, htole16
+#include <stdio.h>   // for fwrite, size_t
+
+// Macros to expand into functions below
+
+#define define_unparse_endian_real(endian, type, bits)                         \
+    extern void unparse_##endian##_##type(type number, UState *ustate)         \
+    {                                                                          \
+        if (!ustate->error_msg)                                                \
+        {                                                                      \
+            union                                                              \
+            {                                                                  \
+                char           c_val[sizeof(type)];                            \
+                type           f_val;                                          \
+                uint##bits##_t i_val;                                          \
+            } buffer;                                                          \
+            buffer.f_val = number;                                             \
+            buffer.i_val = hto##endian##bits(buffer.i_val);                    \
+            size_t count =                                                     \
+                fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);       \
+            if (count < sizeof(buffer))                                        \
+            {                                                                  \
+                ustate->error_msg = eof_or_error_msg(ustate->stream);          \
+            }                                                                  \
+        }                                                                      \
+    }
+
+#define define_unparse_endian_integer(endian, type, bits)                      \
+    extern void unparse_##endian##_##type##bits(type##bits##_t number,         \
+                                                UState *       ustate)         \
+    {                                                                          \
+        if (!ustate->error_msg)                                                \
+        {                                                                      \
+            union                                                              \
+            {                                                                  \
+                char           c_val[sizeof(type##bits##_t)];                  \
+                type##bits##_t i_val;                                          \
+            } buffer;                                                          \
+            buffer.i_val = hto##endian##bits(number);                          \
+            size_t count =                                                     \
+                fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);       \
+            if (count < sizeof(buffer))                                        \
+            {                                                                  \
+                ustate->error_msg = eof_or_error_msg(ustate->stream);          \
+            }                                                                  \
+        }                                                                      \
+    }
+
+#define htobe8(var) var
+
+#define htole8(var) var
+
+// Define functions to unparse binary real and integer numbers
+
+define_unparse_endian_real(be, double, 64)
+
+define_unparse_endian_real(be, float, 32)
+
+define_unparse_endian_integer(be, uint, 64)
+
+define_unparse_endian_integer(be, uint, 32)
+
+define_unparse_endian_integer(be, uint, 16)
+
+define_unparse_endian_integer(be, uint, 8)
+
+define_unparse_endian_integer(be, int, 64)
+
+define_unparse_endian_integer(be, int, 32)
+
+define_unparse_endian_integer(be, int, 16)
+
+define_unparse_endian_integer(be, int, 8)
+
+define_unparse_endian_real(le, double, 64)
+
+define_unparse_endian_real(le, float, 32)
+
+define_unparse_endian_integer(le, uint, 64)
+
+define_unparse_endian_integer(le, uint, 32)
+
+define_unparse_endian_integer(le, uint, 16)
+
+define_unparse_endian_integer(le, uint, 8)
+
+define_unparse_endian_integer(le, int, 64)
+
+define_unparse_endian_integer(le, int, 32)
+
+define_unparse_endian_integer(le, int, 16)
+
+define_unparse_endian_integer(le, int, 8)
diff --git a/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h
new file mode 100644
index 0000000..1d2eabd
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/libruntime/unparsers.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UNPARSERS_H
+#define UNPARSERS_H
+
+#include "infoset.h"  // for UState
+#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
+
+// Functions to unparse binary floating point numbers and integers
+
+extern void unparse_be_double(double number, UState *ustate);
+extern void unparse_be_float(float number, UState *ustate);
+
+extern void unparse_be_uint64(uint64_t number, UState *ustate);
+extern void unparse_be_uint32(uint32_t number, UState *ustate);
+extern void unparse_be_uint16(uint16_t number, UState *ustate);
+extern void unparse_be_uint8(uint8_t number, UState *ustate);
+
+extern void unparse_be_int64(int64_t number, UState *ustate);
+extern void unparse_be_int32(int32_t number, UState *ustate);
+extern void unparse_be_int16(int16_t number, UState *ustate);
+extern void unparse_be_int8(int8_t number, UState *ustate);
+
+extern void unparse_le_double(double number, UState *ustate);
+extern void unparse_le_float(float number, UState *ustate);
+
+extern void unparse_le_uint64(uint64_t number, UState *ustate);
+extern void unparse_le_uint32(uint32_t number, UState *ustate);
+extern void unparse_le_uint16(uint16_t number, UState *ustate);
+extern void unparse_le_uint8(uint8_t number, UState *ustate);
+
+extern void unparse_le_int64(int64_t number, UState *ustate);
+extern void unparse_le_int32(int32_t number, UState *ustate);
+extern void unparse_le_int16(int16_t number, UState *ustate);
+extern void unparse_le_int8(int8_t number, UState *ustate);
+
+#endif // UNPARSERS_H
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_ints.c b/daffodil-runtime2/src/main/resources/examples/ex_ints.c
deleted file mode 100644
index 2db53e2..0000000
--- a/daffodil-runtime2/src/main/resources/examples/ex_ints.c
+++ /dev/null
@@ -1,766 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "ex_ints.h" // for generated code structs
-#include <endian.h>         // for be32toh, htobe32, etc.
-#include <stddef.h>         // for ptrdiff_t
-#include <stdio.h>          // for NULL, fread, fwrite, size_t, FILE
-
-// Prototypes needed for compilation
-
-static void        ex_ints_initSelf(ex_ints *instance);
-static const char *ex_ints_parseSelf(ex_ints *instance, const PState *pstate);
-static const char *ex_ints_unparseSelf(const ex_ints *instance, const UState *ustate);
-
-// Metadata singletons
-
-static const ERD be_uint64_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_uint64", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_uint32_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_uint32", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_uint16_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_uint16", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_uint8_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_uint8", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_int64_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_int64", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_int32_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_int32", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_int16_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_int16", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD be_int8_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "be_int8", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_uint64_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_uint64", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_uint32_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_uint32", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_uint16_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_uint16", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_uint8_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_uint8", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_UINT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_int64_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_int64", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT64, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_int32_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_int32", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT32, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_int16_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_int16", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT16, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ERD le_int8_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "le_int8", // namedQName.local
-        NULL, // namedQName.ns
-    },
-    PRIMITIVE_INT8, // typeCode
-    0,               // numChildren
-    NULL,            // offsets
-    NULL,            // childrenERDs
-    NULL,            // initSelf
-    NULL,            // parseSelf
-    NULL,            // unparseSelf
-};
-
-static const ex_ints ex_ints_compute_ERD_offsets;
-
-static const ptrdiff_t ex_ints_offsets[16] = {
-    (char *)&ex_ints_compute_ERD_offsets.be_uint64 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_uint32 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_uint16 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_uint8 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_int64 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_int32 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_int16 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.be_int8 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_uint64 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_uint32 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_uint16 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_uint8 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_int64 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_int32 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_int16 - (char *)&ex_ints_compute_ERD_offsets,
-    (char *)&ex_ints_compute_ERD_offsets.le_int8 - (char *)&ex_ints_compute_ERD_offsets
-};
-
-static const ERD *ex_ints_childrenERDs[16] = {
-    &be_uint64_ERD,
-    &be_uint32_ERD,
-    &be_uint16_ERD,
-    &be_uint8_ERD,
-    &be_int64_ERD,
-    &be_int32_ERD,
-    &be_int16_ERD,
-    &be_int8_ERD,
-    &le_uint64_ERD,
-    &le_uint32_ERD,
-    &le_uint16_ERD,
-    &le_uint8_ERD,
-    &le_int64_ERD,
-    &le_int32_ERD,
-    &le_int16_ERD,
-    &le_int8_ERD
-};
-
-static const ERD ex_ints_ERD = {
-    {
-        NULL, // namedQName.prefix
-        "ex_ints", // namedQName.local
-        "http://example.com", // namedQName.ns
-    },
-    COMPLEX,                         // typeCode
-    16,                               // numChildren
-    ex_ints_offsets,                      // offsets
-    ex_ints_childrenERDs,                 // childrenERDs
-    (ERDInitSelf)&ex_ints_initSelf,       // initSelf
-    (ERDParseSelf)&ex_ints_parseSelf,     // parseSelf
-    (ERDUnparseSelf)&ex_ints_unparseSelf, // unparseSelf
-};
-
-// Return a root element to be used for parsing or unparsing
-
-InfosetBase *
-rootElement()
-{
-    static ex_ints    instance;
-    InfosetBase *root = &instance._base;
-    ex_ints_ERD.initSelf(root);
-    return root;
-}
-
-// Degenerate cases of endian-conversion functions called by code
-// generator since <endian.h> handles only 16, 32, and 64-bit cases
-
-static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
-static inline uint8_t htole8(uint8_t h8b) { return h8b; }
-static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
-static inline uint8_t le8toh(uint8_t le8b) { return le8b; }
-
-// Methods to initialize, parse, and unparse infoset nodes
-
-static void
-ex_ints_initSelf(ex_ints *instance)
-{
-    instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
-    instance->be_uint32 = 0xCCCCCCCC;
-    instance->be_uint16 = 0xCCCC;
-    instance->be_uint8 = 0xCC;
-    instance->be_int64 = 0xCCCCCCCCCCCCCCCC;
-    instance->be_int32 = 0xCCCCCCCC;
-    instance->be_int16 = 0xCCCC;
-    instance->be_int8 = 0xCC;
-    instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
-    instance->le_uint32 = 0xCCCCCCCC;
-    instance->le_uint16 = 0xCCCC;
-    instance->le_uint8 = 0xCC;
-    instance->le_int64 = 0xCCCCCCCCCCCCCCCC;
-    instance->le_int32 = 0xCCCCCCCC;
-    instance->le_int16 = 0xCCCC;
-    instance->le_int8 = 0xCC;
-    instance->_base.erd = &ex_ints_ERD;
-}
-
-static const char *
-ex_ints_parseSelf(ex_ints *instance, const PState *pstate)
-{
-    const char *error_msg = NULL;
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint64_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_uint64 = be64toh(*((uint64_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_uint32 = be32toh(*((uint32_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint16_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_uint16 = be16toh(*((uint16_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint8_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_uint8 = be8toh(*((uint8_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint64_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_int64 = be64toh(*((uint64_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_int32 = be32toh(*((uint32_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint16_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_int16 = be16toh(*((uint16_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint8_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->be_int8 = be8toh(*((uint8_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint64_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_uint64 = le64toh(*((uint64_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_uint32 = le32toh(*((uint32_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint16_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_uint16 = le16toh(*((uint16_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint8_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_uint8 = le8toh(*((uint8_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint64_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_int64 = le64toh(*((uint64_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint32_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_int32 = le32toh(*((uint32_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint16_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_int16 = le16toh(*((uint16_t *)(&buffer)));
-    }
-    if (!error_msg)
-    {
-        char   buffer[sizeof(uint8_t)];
-        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(pstate->stream);
-        }
-        instance->le_int8 = le8toh(*((uint8_t *)(&buffer)));
-    }
-    return error_msg;
-}
-
-static const char *
-ex_ints_unparseSelf(const ex_ints *instance, const UState *ustate)
-{
-    const char *error_msg = NULL;
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint64_t)];
-            uint64_t i_val;
-        } buffer;
-        buffer.i_val = htobe64(instance->be_uint64);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htobe32(instance->be_uint32);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint16_t)];
-            uint16_t i_val;
-        } buffer;
-        buffer.i_val = htobe16(instance->be_uint16);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint8_t)];
-            uint8_t i_val;
-        } buffer;
-        buffer.i_val = htobe8(instance->be_uint8);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint64_t)];
-            uint64_t i_val;
-        } buffer;
-        buffer.i_val = htobe64(instance->be_int64);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htobe32(instance->be_int32);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint16_t)];
-            uint16_t i_val;
-        } buffer;
-        buffer.i_val = htobe16(instance->be_int16);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint8_t)];
-            uint8_t i_val;
-        } buffer;
-        buffer.i_val = htobe8(instance->be_int8);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint64_t)];
-            uint64_t i_val;
-        } buffer;
-        buffer.i_val = htole64(instance->le_uint64);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htole32(instance->le_uint32);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint16_t)];
-            uint16_t i_val;
-        } buffer;
-        buffer.i_val = htole16(instance->le_uint16);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint8_t)];
-            uint8_t i_val;
-        } buffer;
-        buffer.i_val = htole8(instance->le_uint8);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint64_t)];
-            uint64_t i_val;
-        } buffer;
-        buffer.i_val = htole64(instance->le_int64);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint32_t)];
-            uint32_t i_val;
-        } buffer;
-        buffer.i_val = htole32(instance->le_int32);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint16_t)];
-            uint16_t i_val;
-        } buffer;
-        buffer.i_val = htole16(instance->le_int16);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    if (!error_msg)
-    {
-        union
-        {
-            char     c_val[sizeof(uint8_t)];
-            uint8_t i_val;
-        } buffer;
-        buffer.i_val = htole8(instance->le_int8);
-        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-        if (count < sizeof(buffer))
-        {
-            error_msg = eof_or_error_msg(ustate->stream);
-        }
-    }
-    return error_msg;
-}
-
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_nums.c b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
new file mode 100644
index 0000000..7747006
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.c
@@ -0,0 +1,684 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ex_nums.h"
+#include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
+#include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
+#include <math.h>       // for NAN
+#include <stddef.h>     // for NULL, ptrdiff_t
+
+// Prototypes needed for compilation
+
+static void array_initSelf(array *instance);
+static void array_parseSelf(array *instance, PState *pstate);
+static void array_unparseSelf(const array *instance, UState *ustate);
+static void bigEndian_initSelf(bigEndian *instance);
+static void bigEndian_parseSelf(bigEndian *instance, PState *pstate);
+static void bigEndian_unparseSelf(const bigEndian *instance, UState *ustate);
+static void littleEndian_initSelf(littleEndian *instance);
+static void littleEndian_parseSelf(littleEndian *instance, PState *pstate);
+static void littleEndian_unparseSelf(const littleEndian *instance, UState *ustate);
+static void ex_nums_initSelf(ex_nums *instance);
+static void ex_nums_parseSelf(ex_nums *instance, PState *pstate);
+static void ex_nums_unparseSelf(const ex_nums *instance, UState *ustate);
+
+// Metadata singletons
+
+static const ERD be_int16_array_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_float_array_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_float", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_FLOAT, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const array array_compute_offsets;
+
+static const ptrdiff_t array_offsets[6] = {
+    (const char *)&array_compute_offsets.be_int16[0] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_int16[1] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_int16[2] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_float[0] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_float[1] - (const char *)&array_compute_offsets,
+    (const char *)&array_compute_offsets.be_float[2] - (const char *)&array_compute_offsets
+};
+
+static const ERD *array_childrenERDs[6] = {
+    &be_int16_array_ex_nums__ERD,
+    &be_int16_array_ex_nums__ERD,
+    &be_int16_array_ex_nums__ERD,
+    &be_float_array_ex_nums__ERD,
+    &be_float_array_ex_nums__ERD,
+    &be_float_array_ex_nums__ERD
+};
+
+static const ERD array_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "array", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    6,                               // numChildren
+    array_offsets,                      // offsets
+    array_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&array_initSelf,       // initSelf
+    (ERDParseSelf)&array_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&array_unparseSelf, // unparseSelf
+};
+
+static const ERD be_double_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_double", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_float_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_float", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_FLOAT, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint64_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint32_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint16_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_uint8_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_uint8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int64_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int32_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int16_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD be_int8_bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "be_int8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const bigEndian bigEndian_compute_offsets;
+
+static const ptrdiff_t bigEndian_offsets[10] = {
+    (const char *)&bigEndian_compute_offsets.be_double - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_float - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_uint64 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_uint32 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_uint16 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_uint8 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int64 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int32 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int16 - (const char *)&bigEndian_compute_offsets,
+    (const char *)&bigEndian_compute_offsets.be_int8 - (const char *)&bigEndian_compute_offsets
+};
+
+static const ERD *bigEndian_childrenERDs[10] = {
+    &be_double_bigEndian_ex_nums__ERD,
+    &be_float_bigEndian_ex_nums__ERD,
+    &be_uint64_bigEndian_ex_nums__ERD,
+    &be_uint32_bigEndian_ex_nums__ERD,
+    &be_uint16_bigEndian_ex_nums__ERD,
+    &be_uint8_bigEndian_ex_nums__ERD,
+    &be_int64_bigEndian_ex_nums__ERD,
+    &be_int32_bigEndian_ex_nums__ERD,
+    &be_int16_bigEndian_ex_nums__ERD,
+    &be_int8_bigEndian_ex_nums__ERD
+};
+
+static const ERD bigEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "bigEndian", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    10,                               // numChildren
+    bigEndian_offsets,                      // offsets
+    bigEndian_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&bigEndian_initSelf,       // initSelf
+    (ERDParseSelf)&bigEndian_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&bigEndian_unparseSelf, // unparseSelf
+};
+
+static const ERD le_uint64_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint32_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint16_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_uint8_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_uint8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_UINT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int64_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int64", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT64, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int32_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int32", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int16_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int16", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT16, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_int8_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_int8", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT8, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_float_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_float", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_FLOAT, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD le_double_littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "le_double", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_DOUBLE, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const littleEndian littleEndian_compute_offsets;
+
+static const ptrdiff_t littleEndian_offsets[10] = {
+    (const char *)&littleEndian_compute_offsets.le_uint64 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint32 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint16 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_uint8 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_int64 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_int32 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_int16 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_int8 - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_float - (const char *)&littleEndian_compute_offsets,
+    (const char *)&littleEndian_compute_offsets.le_double - (const char *)&littleEndian_compute_offsets
+};
+
+static const ERD *littleEndian_childrenERDs[10] = {
+    &le_uint64_littleEndian_ex_nums__ERD,
+    &le_uint32_littleEndian_ex_nums__ERD,
+    &le_uint16_littleEndian_ex_nums__ERD,
+    &le_uint8_littleEndian_ex_nums__ERD,
+    &le_int64_littleEndian_ex_nums__ERD,
+    &le_int32_littleEndian_ex_nums__ERD,
+    &le_int16_littleEndian_ex_nums__ERD,
+    &le_int8_littleEndian_ex_nums__ERD,
+    &le_float_littleEndian_ex_nums__ERD,
+    &le_double_littleEndian_ex_nums__ERD
+};
+
+static const ERD littleEndian_ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "littleEndian", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    10,                               // numChildren
+    littleEndian_offsets,                      // offsets
+    littleEndian_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&littleEndian_initSelf,       // initSelf
+    (ERDParseSelf)&littleEndian_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&littleEndian_unparseSelf, // unparseSelf
+};
+
+static const ex_nums ex_nums_compute_offsets;
+
+static const ptrdiff_t ex_nums_offsets[3] = {
+    (const char *)&ex_nums_compute_offsets.array - (const char *)&ex_nums_compute_offsets,
+    (const char *)&ex_nums_compute_offsets.bigEndian - (const char *)&ex_nums_compute_offsets,
+    (const char *)&ex_nums_compute_offsets.littleEndian - (const char *)&ex_nums_compute_offsets
+};
+
+static const ERD *ex_nums_childrenERDs[3] = {
+    &array_ex_nums__ERD,
+    &bigEndian_ex_nums__ERD,
+    &littleEndian_ex_nums__ERD
+};
+
+static const ERD ex_nums__ERD = {
+    {
+        NULL, // namedQName.prefix
+        "ex_nums", // namedQName.local
+        "http://example.com", // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    3,                               // numChildren
+    ex_nums_offsets,                      // offsets
+    ex_nums_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&ex_nums_initSelf,       // initSelf
+    (ERDParseSelf)&ex_nums_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&ex_nums_unparseSelf, // unparseSelf
+};
+
+// Return a root element to be used for parsing or unparsing
+
+extern InfosetBase *
+rootElement(void)
+{
+    static ex_nums instance;
+    InfosetBase *root = &instance._base;
+    ex_nums__ERD.initSelf(root);
+    return root;
+}
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+array_initSelf(array *instance)
+{
+    instance->be_int16[0] = 0xCCCC;
+    instance->be_int16[1] = 0xCCCC;
+    instance->be_int16[2] = 0xCCCC;
+    instance->be_float[0] = NAN;
+    instance->be_float[1] = NAN;
+    instance->be_float[2] = NAN;
+    instance->_base.erd = &array_ex_nums__ERD;
+}
+
+static void
+array_parseSelf(array *instance, PState *pstate)
+{
+    parse_be_int16(&instance->be_int16[0], pstate);
+    parse_be_int16(&instance->be_int16[1], pstate);
+    parse_be_int16(&instance->be_int16[2], pstate);
+    parse_be_float(&instance->be_float[0], pstate);
+    parse_be_float(&instance->be_float[1], pstate);
+    parse_be_float(&instance->be_float[2], pstate);
+}
+
+static void
+array_unparseSelf(const array *instance, UState *ustate)
+{
+    unparse_be_int16(instance->be_int16[0], ustate);
+    unparse_be_int16(instance->be_int16[1], ustate);
+    unparse_be_int16(instance->be_int16[2], ustate);
+    unparse_be_float(instance->be_float[0], ustate);
+    unparse_be_float(instance->be_float[1], ustate);
+    unparse_be_float(instance->be_float[2], ustate);
+}
+
+static void
+bigEndian_initSelf(bigEndian *instance)
+{
+    instance->be_double = NAN;
+    instance->be_float = NAN;
+    instance->be_uint64 = 0xCCCCCCCCCCCCCCCC;
+    instance->be_uint32 = 0xCCCCCCCC;
+    instance->be_uint16 = 0xCCCC;
+    instance->be_uint8 = 0xCC;
+    instance->be_int64 = 0xCCCCCCCCCCCCCCCC;
+    instance->be_int32 = 0xCCCCCCCC;
+    instance->be_int16 = 0xCCCC;
+    instance->be_int8 = 0xCC;
+    instance->_base.erd = &bigEndian_ex_nums__ERD;
+}
+
+static void
+bigEndian_parseSelf(bigEndian *instance, PState *pstate)
+{
+    parse_be_double(&instance->be_double, pstate);
+    parse_be_float(&instance->be_float, pstate);
+    parse_be_uint64(&instance->be_uint64, pstate);
+    parse_be_uint32(&instance->be_uint32, pstate);
+    parse_be_uint16(&instance->be_uint16, pstate);
+    parse_be_uint8(&instance->be_uint8, pstate);
+    parse_be_int64(&instance->be_int64, pstate);
+    parse_be_int32(&instance->be_int32, pstate);
+    parse_be_int16(&instance->be_int16, pstate);
+    parse_be_int8(&instance->be_int8, pstate);
+}
+
+static void
+bigEndian_unparseSelf(const bigEndian *instance, UState *ustate)
+{
+    unparse_be_double(instance->be_double, ustate);
+    unparse_be_float(instance->be_float, ustate);
+    unparse_be_uint64(instance->be_uint64, ustate);
+    unparse_be_uint32(instance->be_uint32, ustate);
+    unparse_be_uint16(instance->be_uint16, ustate);
+    unparse_be_uint8(instance->be_uint8, ustate);
+    unparse_be_int64(instance->be_int64, ustate);
+    unparse_be_int32(instance->be_int32, ustate);
+    unparse_be_int16(instance->be_int16, ustate);
+    unparse_be_int8(instance->be_int8, ustate);
+}
+
+static void
+littleEndian_initSelf(littleEndian *instance)
+{
+    instance->le_uint64 = 0xCCCCCCCCCCCCCCCC;
+    instance->le_uint32 = 0xCCCCCCCC;
+    instance->le_uint16 = 0xCCCC;
+    instance->le_uint8 = 0xCC;
+    instance->le_int64 = 0xCCCCCCCCCCCCCCCC;
+    instance->le_int32 = 0xCCCCCCCC;
+    instance->le_int16 = 0xCCCC;
+    instance->le_int8 = 0xCC;
+    instance->le_float = NAN;
+    instance->le_double = NAN;
+    instance->_base.erd = &littleEndian_ex_nums__ERD;
+}
+
+static void
+littleEndian_parseSelf(littleEndian *instance, PState *pstate)
+{
+    parse_le_uint64(&instance->le_uint64, pstate);
+    parse_le_uint32(&instance->le_uint32, pstate);
+    parse_le_uint16(&instance->le_uint16, pstate);
+    parse_le_uint8(&instance->le_uint8, pstate);
+    parse_le_int64(&instance->le_int64, pstate);
+    parse_le_int32(&instance->le_int32, pstate);
+    parse_le_int16(&instance->le_int16, pstate);
+    parse_le_int8(&instance->le_int8, pstate);
+    parse_le_float(&instance->le_float, pstate);
+    parse_le_double(&instance->le_double, pstate);
+}
+
+static void
+littleEndian_unparseSelf(const littleEndian *instance, UState *ustate)
+{
+    unparse_le_uint64(instance->le_uint64, ustate);
+    unparse_le_uint32(instance->le_uint32, ustate);
+    unparse_le_uint16(instance->le_uint16, ustate);
+    unparse_le_uint8(instance->le_uint8, ustate);
+    unparse_le_int64(instance->le_int64, ustate);
+    unparse_le_int32(instance->le_int32, ustate);
+    unparse_le_int16(instance->le_int16, ustate);
+    unparse_le_int8(instance->le_int8, ustate);
+    unparse_le_float(instance->le_float, ustate);
+    unparse_le_double(instance->le_double, ustate);
+}
+
+static void
+ex_nums_initSelf(ex_nums *instance)
+{
+    array_initSelf(&instance->array);
+    bigEndian_initSelf(&instance->bigEndian);
+    littleEndian_initSelf(&instance->littleEndian);
+    instance->_base.erd = &ex_nums__ERD;
+}
+
+static void
+ex_nums_parseSelf(ex_nums *instance, PState *pstate)
+{
+    array_parseSelf(&instance->array, pstate);
+    bigEndian_parseSelf(&instance->bigEndian, pstate);
+    littleEndian_parseSelf(&instance->littleEndian, pstate);
+}
+
+static void
+ex_nums_unparseSelf(const ex_nums *instance, UState *ustate)
+{
+    array_unparseSelf(&instance->array, ustate);
+    bigEndian_unparseSelf(&instance->bigEndian, ustate);
+    littleEndian_unparseSelf(&instance->littleEndian, ustate);
+}
+
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_ints.h b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
similarity index 69%
rename from daffodil-runtime2/src/main/resources/examples/ex_ints.h
rename to daffodil-runtime2/src/main/resources/examples/ex_nums.h
index bc8ffd8..9e2c1bb 100644
--- a/daffodil-runtime2/src/main/resources/examples/ex_ints.h
+++ b/daffodil-runtime2/src/main/resources/examples/ex_nums.h
@@ -18,14 +18,23 @@
 #ifndef GENERATED_CODE_H
 #define GENERATED_CODE_H
 
-#include "infoset.h" // for InfosetBase
-#include <stdint.h>  // for int32_t
+#include "infoset.h"  // for InfosetBase
+#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
 // Define some infoset structures
 
-typedef struct ex_ints
+typedef struct array
 {
     InfosetBase _base;
+    int16_t     be_int16[3];
+    float       be_float[3];
+} array;
+
+typedef struct bigEndian
+{
+    InfosetBase _base;
+    double      be_double;
+    float       be_float;
     uint64_t    be_uint64;
     uint32_t    be_uint32;
     uint16_t    be_uint16;
@@ -34,6 +43,11 @@ typedef struct ex_ints
     int32_t     be_int32;
     int16_t     be_int16;
     int8_t      be_int8;
+} bigEndian;
+
+typedef struct littleEndian
+{
+    InfosetBase _base;
     uint64_t    le_uint64;
     uint32_t    le_uint32;
     uint16_t    le_uint16;
@@ -42,6 +56,16 @@ typedef struct ex_ints
     int32_t     le_int32;
     int16_t     le_int16;
     int8_t      le_int8;
-} ex_ints;
+    float       le_float;
+    double      le_double;
+} littleEndian;
+
+typedef struct ex_nums
+{
+    InfosetBase _base;
+    array array;
+    bigEndian bigEndian;
+    littleEndian littleEndian;
+} ex_nums;
 
 #endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
index 4f2a776..385657c 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
@@ -44,7 +44,7 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
   private var errorStatus: Boolean = false
 
   // Writes C source files into a "c" subdirectory of the given output directory.
-  // Removes the "c" subdirectory if it existed before.
+  // Removes the "c" subdirectory if it existed before.  Returns the "c" subdirectory.
   override def generateCode(rootNS: Option[RefQName], outputDirArg: String): os.Path = {
     // Get the paths of the output directory and its code subdirectory
     val outputDir = os.Path(Paths.get(outputDirArg).toAbsolutePath)
@@ -82,15 +82,14 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     os.write(generatedCodeHeader, codeHeaderText)
     os.write(generatedCodeFile, codeFileText)
 
-    // Return our output directory in case caller wants to call compileCode next
-    outputDir
+    // Return our code directory in case caller wants to call compileCode next
+    codeDir
   }
 
-  // Compiles any C source files inside a "c" subdirectory of the given output directory.
-  // Returns the path of the newly created executable to use in TDML tests or something else.
-  override def compileCode(outputDir: os.Path): os.Path = {
-    // Get the paths of the code subdirectory and the executable we will build
-    val codeDir = outputDir/"c"
+  // Compiles any C source files inside the given code directory.  Returns the path
+  // of the newly created executable to use in TDML tests or somewhere else.
+  override def compileCode(codeDir: os.Path): os.Path = {
+    // Get the path of the executable we will build
     val exe = if (isWindows) codeDir/"daffodil.exe" else codeDir/"daffodil"
 
     try {
@@ -99,14 +98,12 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
       val files = os.walk(codeDir).filter(_.ext == "c")
       val libs = Seq("-lmxml", if (isWindows) "-largp" else "-lpthread")
 
-      // Call the compiler if it was found.  We run the compiler in the output directory,
-      // not in the "c" subdirectory, in order to let the compiler (which might be "zig cc")
-      // cache/reuse previously built files (which might be in a "zig_cache" subdirectory).
-      // We can't let "zig_cache" be put into "c" because we always remove and re-generate
-      // everything in "c" from scratch.
+      // Run the compiler in the code directory (if we found "zig cc"
+      // as a compiler, it will cache previously built files in zig's
+      // global cache directory, not a local zig_cache directory)
       if (compiler.nonEmpty) {
         val result = os.proc(compiler, "-I", codeDir/"libcli", "-I", codeDir/"libruntime",
-          files, libs, "-o", exe).call(cwd = outputDir, stderr = os.Pipe)
+          files, libs, "-o", exe).call(cwd = codeDir, stderr = os.Pipe)
 
         // Report any compiler output as a warning
         if (result.out.text.nonEmpty || result.err.text.nonEmpty) {
@@ -116,7 +113,7 @@ class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
     } catch {
       // Report any subprocess termination error as an error
       case e: os.SubprocessException =>
-        error("Error compiling generated code: %s wd: %s", Misc.getSomeMessage(e).get, outputDir.toString)
+        error("Error compiling generated code: %s wd: %s", Misc.getSomeMessage(e).get, codeDir.toString)
     }
 
     // Report any failure to build the executable as an error
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
index fbf704f..65c2c1c 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
@@ -21,6 +21,8 @@ import org.apache.daffodil.grammar.Gram
 import org.apache.daffodil.grammar.Prod
 import org.apache.daffodil.grammar.RootGrammarMixin
 import org.apache.daffodil.grammar.SeqComp
+import org.apache.daffodil.grammar.primitives.BinaryDouble
+import org.apache.daffodil.grammar.primitives.BinaryFloat
 import org.apache.daffodil.grammar.primitives.BinaryIntegerKnownLength
 import org.apache.daffodil.grammar.primitives.CaptureContentLengthEnd
 import org.apache.daffodil.grammar.primitives.CaptureContentLengthStart
@@ -31,6 +33,7 @@ import org.apache.daffodil.grammar.primitives.ElementParseAndUnspecifiedLength
 import org.apache.daffodil.grammar.primitives.OrderedSequence
 import org.apache.daffodil.grammar.primitives.ScalarOrderedSequenceChild
 import org.apache.daffodil.grammar.primitives.SpecifiedLengthImplicit
+import org.apache.daffodil.runtime2.generators.BinaryFloatCodeGenerator
 import org.apache.daffodil.runtime2.generators.BinaryIntegerKnownLengthCodeGenerator
 import org.apache.daffodil.runtime2.generators.CodeGeneratorState
 import org.apache.daffodil.runtime2.generators.ElementParseAndUnspecifiedLengthCodeGenerator
@@ -42,6 +45,7 @@ import scala.annotation.tailrec
 
 object Runtime2CodeGenerator
   extends BinaryIntegerKnownLengthCodeGenerator
+    with BinaryFloatCodeGenerator
     with ElementParseAndUnspecifiedLengthCodeGenerator
     with OrderedSequenceCodeGenerator
     with SeqCompCodeGenerator {
@@ -58,10 +62,16 @@ object Runtime2CodeGenerator
       case g: OrderedSequence => orderedSequenceGenerateCode(g, state)
       case g: ElementParseAndUnspecifiedLength => elementParseAndUnspecifiedLengthGenerateCode(g, state)
       case g: BinaryIntegerKnownLength => binaryIntegerKnownLengthGenerateCode(g, state)
-      case _: CaptureContentLengthStart => // not generating code here
-      case _: CaptureContentLengthEnd => // not generating code here
-      case _: CaptureValueLengthStart => //not generating code here
-      case _: CaptureValueLengthEnd => // not generating code here
+      case g: BinaryFloat => binaryFloatGenerateCode(g.e, 32, state)
+      case g: BinaryDouble => binaryFloatGenerateCode(g.e, 64, state)
+      case _: CaptureContentLengthStart => noop
+      case _: CaptureContentLengthEnd => noop
+      case _: CaptureValueLengthStart => noop
+      case _: CaptureValueLengthEnd => noop
       case _ => gram.SDE("Code generation not supported for: %s", Misc.getNameFromClass(gram))
     }
+
+  private def noop: Unit = {
+    // Not generating code here, but can use as a breakpoint
+  }
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala
new file mode 100644
index 0000000..2567ae0
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryFloatCodeGenerator.scala
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2.generators
+
+import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.schema.annotation.props.gen.ByteOrder
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+
+trait BinaryFloatCodeGenerator {
+
+  def binaryFloatGenerateCode(e: ElementBase, lengthInBits: Int, cgState: CodeGeneratorState): Unit = {
+    // For the time being this is a very limited back end.
+    // So there are some restrictions to enforce.
+    assert(lengthInBits == 32 || lengthInBits == 64)
+    val byteOrder: ByteOrder = {
+      e.schemaDefinitionUnless(e.byteOrderEv.isConstant, "Runtime dfdl:byteOrder expressions not supported.")
+      val bo = e.byteOrderEv.constValue
+      bo
+    }
+
+    // Use a NAN to mark our field as uninitialized in case parsing or unparsing
+    // fails to set the field.
+    val fieldName = e.namedQName.local
+    val float = if (lengthInBits == 32) "float" else "double"
+    val conv = if (byteOrder eq ByteOrder.BigEndian) "be" else "le"
+    val arraySize = if (e.occursCountKind == OccursCountKind.Fixed) e.maxOccurs else 0
+
+    def addSimpleTypeStatements(deref: String): Unit = {
+      val initStatement = s"    instance->$fieldName$deref = NAN;"
+      val parseStatement = s"    parse_${conv}_$float(&instance->$fieldName$deref, pstate);"
+      val unparseStatement = s"    unparse_${conv}_$float(instance->$fieldName$deref, ustate);"
+      cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+    }
+    if (arraySize > 0)
+      for (i <- 0 until arraySize)
+        addSimpleTypeStatements(s"[$i]")
+    else
+      addSimpleTypeStatements("")
+  }
+}
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
index f31a162..c3ac488 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
@@ -18,35 +18,29 @@
 package org.apache.daffodil.runtime2.generators
 
 import org.apache.daffodil.grammar.primitives.BinaryIntegerKnownLength
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 import org.apache.daffodil.schema.annotation.props.gen.{ BitOrder, ByteOrder }
 
 trait BinaryIntegerKnownLengthCodeGenerator {
 
   def binaryIntegerKnownLengthGenerateCode(g: BinaryIntegerKnownLength, cgState: CodeGeneratorState): Unit = {
     // For the time being this is a very limited back end.
-    // So there are numerous restrictions to enforce.
+    // So there are some restrictions to enforce.
     val e = g.e
-    val fieldName = e.namedQName.local
     val lengthInBits: Long = {
       e.schemaDefinitionUnless(e.elementLengthInBitsEv.isConstant, "Runtime dfdl:length expressions not supported.")
       val len = e.elementLengthInBitsEv.constValue.get
       len
     }
-
+    e.schemaDefinitionUnless(e.bitOrder eq BitOrder.MostSignificantBitFirst, "Only dfdl:bitOrder 'mostSignificantBitFirst' is supported.")
     val byteOrder: ByteOrder = {
       e.schemaDefinitionUnless(e.byteOrderEv.isConstant, "Runtime dfdl:byteOrder expressions not supported.")
       val bo = e.byteOrderEv.constValue
       bo
     }
 
-    // We eventually want to lift this restriction.
-    if (e.bitOrder ne BitOrder.MostSignificantBitFirst)
-      e.SDE("Only dfdl:bitOrder 'mostSignificantBitFirst' is supported.")
-    if (e.alignmentValueInBits.intValue() % 8 != 0)
-      e.SDE("Only alignment to 8-bit (1 byte) boundaries is supported.")
-
-    // Use an unusual memory bit pattern (magic debug value) to mark fields as
-    // uninitialized in case generated code fails to set them during parsing.
+    // Use an unusual memory bit pattern (magic debug value) to mark our field
+    // as uninitialized in case parsing or unparsing fails to set the field.
     val initialValue = lengthInBits match {
       case 8 => "0xCC"
       case 16 => "0xCCCC"
@@ -54,34 +48,21 @@ trait BinaryIntegerKnownLengthCodeGenerator {
       case 64 => "0xCCCCCCCCCCCCCCCC"
       case _ => e.SDE("Lengths other than 8, 16, 32, or 64 bits are not supported.")
     }
-    val initStatement = s"    instance->$fieldName = $initialValue;"
+    val fieldName = e.namedQName.local
+    val integer = if (g.signed) s"int${lengthInBits}" else s"uint${lengthInBits}"
     val conv = if (byteOrder eq ByteOrder.BigEndian) "be" else "le"
-    val parseStatement =
-      s"""    if (!error_msg)
-         |    {
-         |        char   buffer[sizeof(uint${lengthInBits}_t)];
-         |        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
-         |        if (count < sizeof(buffer))
-         |        {
-         |            error_msg = eof_or_error_msg(pstate->stream);
-         |        }
-         |        instance->$fieldName = ${conv}${lengthInBits}toh(*((uint${lengthInBits}_t *)(&buffer)));
-         |    }""".stripMargin
-    val unparseStatement =
-      s"""    if (!error_msg)
-         |    {
-         |        union
-         |        {
-         |            char     c_val[sizeof(uint${lengthInBits}_t)];
-         |            uint${lengthInBits}_t i_val;
-         |        } buffer;
-         |        buffer.i_val = hto${conv}${lengthInBits}(instance->$fieldName);
-         |        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
-         |        if (count < sizeof(buffer))
-         |        {
-         |            error_msg = eof_or_error_msg(ustate->stream);
-         |        }
-         |    }""".stripMargin
-    cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+    val arraySize = if (e.occursCountKind == OccursCountKind.Fixed) e.maxOccurs else 0
+
+    def addSimpleTypeStatements(deref: String): Unit = {
+      val initStatement = s"    instance->$fieldName$deref = $initialValue;"
+      val parseStatement = s"    parse_${conv}_$integer(&instance->$fieldName$deref, pstate);"
+      val unparseStatement = s"    unparse_${conv}_$integer(instance->$fieldName$deref, ustate);"
+      cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+    }
+    if (arraySize > 0)
+      for (i <- 0 until arraySize)
+        addSimpleTypeStatements(s"[$i]")
+    else
+      addSimpleTypeStatements("")
   }
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
index f629f14..a1db02c 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -20,7 +20,10 @@ package org.apache.daffodil.runtime2.generators
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.dsom.GlobalElementDecl
+import org.apache.daffodil.dsom.SchemaComponent
 import org.apache.daffodil.exceptions.ThrowsSDE
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 
 import scala.collection.mutable
 
@@ -34,15 +37,35 @@ class CodeGeneratorState {
   private val finalStructs = mutable.ArrayBuffer[String]()
   private val finalImplementation = mutable.ArrayBuffer[String]()
 
+  // Builds a name for the given element that needs to be unique in C file scope
+  private def qualifiedName(context: ElementBase): String = {
+    def buildName(sc: SchemaComponent, sb: StringBuilder): StringBuilder = {
+      sc match {
+        case gd: GlobalElementDecl => sb ++= gd.namedQName.local += '_'
+        case eb: ElementBase => sb ++= eb.namedQName.local += '_'
+        case _ => // don't include other schema components in qualified name
+      }
+      sc.optLexicalParent.foreach {
+        buildName(_, sb)
+      }
+      sb
+    }
+    val sb = buildName(context, new StringBuilder)
+    sb.toString()
+  }
+
+  // Returns the given element's local name (doesn't have to be unique)
+  private def localName(context: ElementBase): String = context.namedQName.local
+
   def addImplementation(context: ElementBase): Unit = {
-    val C = context.namedQName.local
+    val C = localName(context)
     val initStatements = structs.top.initStatements.mkString("\n")
     val parserStatements = structs.top.parserStatements.mkString("\n")
     val unparserStatements = structs.top.unparserStatements.mkString("\n")
     val prototypeFunctions =
-      s"""static void        ${C}_initSelf($C *instance);
-         |static const char *${C}_parseSelf($C *instance, const PState *pstate);
-         |static const char *${C}_unparseSelf(const $C *instance, const UState *ustate);""".stripMargin
+      s"""static void ${C}_initSelf($C *instance);
+         |static void ${C}_parseSelf($C *instance, PState *pstate);
+         |static void ${C}_unparseSelf(const $C *instance, UState *ustate);""".stripMargin
     prototypes += prototypeFunctions
     val functions =
       s"""static void
@@ -51,20 +74,16 @@ class CodeGeneratorState {
          |$initStatements
          |}
          |
-         |static const char *
-         |${C}_parseSelf($C *instance, const PState *pstate)
+         |static void
+         |${C}_parseSelf($C *instance, PState *pstate)
          |{
-         |    const char *error_msg = NULL;
          |$parserStatements
-         |    return error_msg;
          |}
          |
-         |static const char *
-         |${C}_unparseSelf(const $C *instance, const UState *ustate)
+         |static void
+         |${C}_unparseSelf(const $C *instance, UState *ustate)
          |{
-         |    const char *error_msg = NULL;
          |$unparserStatements
-         |    return error_msg;
          |}
          |""".stripMargin
     finalImplementation += functions
@@ -72,7 +91,7 @@ class CodeGeneratorState {
 
   private def defineQNameInit(context: ElementBase): String = {
     val prefix = context.namedQName.prefix.map(p => s""""$p"""").getOrElse("NULL")
-    val local = context.namedQName.local
+    val local = localName(context)
     val nsUri = context.namedQName.namespace.toStringOrNullIfNoNS
     // Optimize away ns declaration if possible, although this approach may not be entirely correct
     val parentNsUri = context.enclosingElements.headOption.map(_.namedQName.namespace.toStringOrNullIfNoNS).getOrElse("no-ns")
@@ -87,13 +106,14 @@ class CodeGeneratorState {
   }
 
   def addComplexTypeERD(context: ElementBase): Unit = {
-    val C = context.namedQName.local
-    val count = structs.top.declarations.length
+    val C = localName(context)
+    val qn = qualifiedName(context)
+    val count = structs.top.offsetComputations.length
     val offsetComputations = structs.top.offsetComputations.mkString(",\n")
     val erdComputations = structs.top.erdComputations.mkString(",\n")
     val qnameInit = defineQNameInit(context)
     val complexERD =
-      s"""static const $C ${C}_compute_ERD_offsets;
+      s"""static const $C ${C}_compute_offsets;
          |
          |static const ptrdiff_t ${C}_offsets[$count] = {
          |$offsetComputations
@@ -103,7 +123,7 @@ class CodeGeneratorState {
          |$erdComputations
          |};
          |
-         |static const ERD ${C}_ERD = {
+         |static const ERD ${qn}_ERD = {
          |$qnameInit
          |    COMPLEX,                         // typeCode
          |    $count,                               // numChildren
@@ -118,7 +138,8 @@ class CodeGeneratorState {
   }
 
   def addStruct(context: ElementBase): Unit = {
-    val C = context.namedQName.local
+    val C = localName(context)
+    val qn = qualifiedName(context)
     val declarations = structs.top.declarations.mkString("\n")
     val struct =
       s"""typedef struct $C
@@ -128,7 +149,7 @@ class CodeGeneratorState {
          |} $C;
          |""".stripMargin
     finalStructs += struct
-    val initStatement = s"    instance->_base.erd = &${C}_ERD;"
+    val initStatement = s"    instance->_base.erd = &${qn}_ERD;"
     structs.top.initStatements += initStatement
   }
 
@@ -139,26 +160,18 @@ class CodeGeneratorState {
   }
 
   def addComplexTypeStatements(child: ElementBase): Unit = {
-    val C = child.namedQName.local
+    val C = localName(child)
     val e = child.name
     val initStatement = s"    ${C}_initSelf(&instance->$e);"
-    val parseStatement =
-      s"""    if (!error_msg)
-         |    {
-         |        error_msg = ${C}_parseSelf(&instance->$e, pstate);
-         |    }""".stripMargin
-    val unparseStatement =
-      s"""    if (!error_msg)
-         |    {
-         |        error_msg = ${C}_unparseSelf(&instance->$e, ustate);
-         |    }""".stripMargin
+    val parseStatement = s"    ${C}_parseSelf(&instance->$e, pstate);"
+    val unparseStatement = s"    ${C}_unparseSelf(&instance->$e, ustate);"
     structs.top.initStatements += initStatement
     structs.top.parserStatements += parseStatement
     structs.top.unparserStatements += unparseStatement
   }
 
   def pushComplexElement(context: ElementBase): Unit = {
-    val C = context.namedQName.local
+    val C = localName(context)
     structs.push(new ComplexCGState(C))
   }
 
@@ -167,7 +180,7 @@ class CodeGeneratorState {
   }
 
   def addSimpleTypeERD(context: ElementBase): Unit = {
-    val e = context.namedQName.local
+    val qn = qualifiedName(context)
     val qnameInit = defineQNameInit(context)
     val typeCode = context.optPrimType.get match {
       case PrimType.UnsignedLong => "PRIMITIVE_UINT64"
@@ -178,10 +191,12 @@ class CodeGeneratorState {
       case PrimType.Int => "PRIMITIVE_INT32"
       case PrimType.Short => "PRIMITIVE_INT16"
       case PrimType.Byte => "PRIMITIVE_INT8"
+      case PrimType.Float => "PRIMITIVE_FLOAT"
+      case PrimType.Double => "PRIMITIVE_DOUBLE"
       case p: PrimType => context.SDE("PrimType %s not supported yet.", p.toString)
     }
     val erd =
-      s"""static const ERD ${e}_ERD = {
+      s"""static const ERD ${qn}_ERD = {
          |$qnameInit
          |    $typeCode, // typeCode
          |    0,               // numChildren
@@ -198,11 +213,20 @@ class CodeGeneratorState {
 
   def addComputations(child: ElementBase): Unit = {
     val C = structs.top.C
-    val e = child.namedQName.local
-    val offsetComputation = s"    (char *)&${C}_compute_ERD_offsets.$e - (char *)&${C}_compute_ERD_offsets"
-    val erdComputation = s"    &${e}_ERD"
-    structs.top.offsetComputations += offsetComputation
-    structs.top.erdComputations += erdComputation
+    val e = localName(child)
+    val qn = qualifiedName(child)
+    val arraySize = if (child.occursCountKind == OccursCountKind.Fixed) child.maxOccurs else 0
+    def addComputation(deref: String): Unit = {
+      val offsetComputation = s"    (const char *)&${C}_compute_offsets.$e$deref - (const char *)&${C}_compute_offsets"
+      val erdComputation = s"    &${qn}_ERD"
+      structs.top.offsetComputations += offsetComputation
+      structs.top.erdComputations += erdComputation
+    }
+    if (arraySize > 0)
+      for (i <- 0 until arraySize)
+        addComputation(s"[$i]")
+    else
+      addComputation("")
   }
 
   def addFieldDeclaration(context: ThrowsSDE, child: ElementBase): Unit = {
@@ -217,12 +241,16 @@ class CodeGeneratorState {
         case PrimType.Int => "int32_t    "
         case PrimType.Short => "int16_t    "
         case PrimType.Byte => "int8_t     "
+        case PrimType.Float => "float      "
+        case PrimType.Double => "double     "
         case x => context.SDE("Unsupported primitive type: " + x)
       }
     } else {
-      child.namedQName.local + "         "
+      localName(child)
     }
-    structs.top.declarations += s"    $definition ${child.name};"
+    val e = child.name
+    val arrayDef = if (child.occursCountKind == OccursCountKind.Fixed) s"[${child.maxOccurs}]" else ""
+    structs.top.declarations += s"    $definition $e$arrayDef;"
   }
 
   def generateCodeHeader: String = {
@@ -231,8 +259,8 @@ class CodeGeneratorState {
       s"""#ifndef GENERATED_CODE_H
          |#define GENERATED_CODE_H
          |
-         |#include "infoset.h" // for InfosetBase
-         |#include <stdint.h>  // for int32_t
+         |#include "infoset.h"  // for InfosetBase
+         |#include <stdint.h>   // for int16_t, int32_t, int64_t, int8_t, uint16_t, uint32_t, uint64_t, uint8_t
 
          |// Define some infoset structures
          |
@@ -247,10 +275,11 @@ class CodeGeneratorState {
     val erds = this.erds.mkString("\n")
     val finalImplementation = this.finalImplementation.mkString("\n")
     val code =
-      s"""#include "generated_code.h" // for generated code structs
-         |#include <endian.h>         // for be32toh, htobe32, etc.
-         |#include <stddef.h>         // for ptrdiff_t
-         |#include <stdio.h>          // for NULL, fread, fwrite, size_t, FILE
+      s"""#include "generated_code.h"
+         |#include "parsers.h"    // for parse_be_double, parse_be_float, parse_be_int16, parse_be_int32, parse_be_int64, parse_be_int8, parse_be_uint16, parse_be_uint32, parse_be_uint64, parse_be_uint8, parse_le_double, parse_le_float, parse_le_int16, parse_le_int32, parse_le_int64, parse_le_int8, parse_le_uint16, parse_le_uint32, parse_le_uint64, parse_le_uint8
+         |#include "unparsers.h"  // for unparse_be_double, unparse_be_float, unparse_be_int16, unparse_be_int32, unparse_be_int64, unparse_be_int8, unparse_be_uint16, unparse_be_uint32, unparse_be_uint64, unparse_be_uint8, unparse_le_double, unparse_le_float, unparse_le_int16, unparse_le_int32, unparse_le_int64, unparse_le_int8, unparse_le_uint16, unparse_le_uint32, unparse_le_uint64, unparse_le_uint8
+         |#include <math.h>       // for NAN
+         |#include <stddef.h>     // for NULL, ptrdiff_t
          |
          |// Prototypes needed for compilation
          |
@@ -261,23 +290,15 @@ class CodeGeneratorState {
          |$erds
          |// Return a root element to be used for parsing or unparsing
          |
-         |InfosetBase *
-         |rootElement()
+         |extern InfosetBase *
+         |rootElement(void)
          |{
-         |    static $rootElementName    instance;
+         |    static $rootElementName instance;
          |    InfosetBase *root = &instance._base;
-         |    ${rootElementName}_ERD.initSelf(root);
+         |    ${rootElementName}__ERD.initSelf(root);
          |    return root;
          |}
          |
-         |// Degenerate cases of endian-conversion functions called by code
-         |// generator since <endian.h> handles only 16, 32, and 64-bit cases
-         |
-         |static inline uint8_t htobe8(uint8_t h8b) { return h8b; }
-         |static inline uint8_t htole8(uint8_t h8b) { return h8b; }
-         |static inline uint8_t be8toh(uint8_t be8b) { return be8b; }
-         |static inline uint8_t le8toh(uint8_t le8b) { return le8b; }
-         |
          |// Methods to initialize, parse, and unparse infoset nodes
          |
          |$finalImplementation
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
index 97e2e4b..a18698f 100644
--- a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
@@ -17,7 +17,6 @@
 
 package org.apache.daffodil.tdml.processor.runtime2
 
-import dev.dirs.ProjectDirectories
 import org.apache.daffodil.api._
 import org.apache.daffodil.compiler.Compiler
 import org.apache.daffodil.externalvars.Binding
@@ -107,20 +106,20 @@ final class TDMLDFDLProcessorFactory private(
       // Create a CodeGenerator from the DFDL schema for the C language
       val generator = pf.forLanguage("c")
 
-      // Generate the C source code in our cache directory
+      // Generate the C source code in a temporary unique directory
       val rootNS = QName.refQNameFromExtendedSyntax(optRootName.getOrElse("")).toOption
-      val directories = ProjectDirectories.from("org", "Apache Software Foundation", "Daffodil")
-      val outputDir = generator.generateCode(rootNS, directories.cacheDir)
+      val tempDir = os.temp.dir()
+      val codeDir = generator.generateCode(rootNS, tempDir.toString)
 
       // Compile the generated code into an executable
-      val executable = generator.compileCode(outputDir)
+      val executable = generator.compileCode(codeDir)
 
       // Summarize the result of compiling the schema for the test
       val compileResult = if (generator.isError) {
         Left(generator.getDiagnostics) // C code compilation diagnostics
       } else {
         // Create a processor for running the test using the executable
-        val processor = new Runtime2TDMLDFDLProcessor(executable)
+        val processor = new Runtime2TDMLDFDLProcessor(tempDir, executable)
         Right((generator.getDiagnostics, processor))
       }
       compileResult
@@ -136,7 +135,7 @@ final class TDMLDFDLProcessorFactory private(
  * XML Infosets, feeding to the unparser, creating XML from the result created by the
  * [[Runtime2DataProcessor]]. All the "real work" is done by [[Runtime2DataProcessor]].
  */
-class Runtime2TDMLDFDLProcessor(executable: os.Path) extends TDMLDFDLProcessor {
+class Runtime2TDMLDFDLProcessor(tempDir: os.Path, executable: os.Path) extends TDMLDFDLProcessor {
 
   override type R = Runtime2TDMLDFDLProcessor
 
@@ -178,7 +177,7 @@ class Runtime2TDMLDFDLProcessor(executable: os.Path) extends TDMLDFDLProcessor {
     val pr = dataProcessor.parse(is)
     anyErrors = pr.isError
     diagnostics = pr.getDiagnostics
-    new Runtime2TDMLParseResult(pr)
+    new Runtime2TDMLParseResult(pr, tempDir)
   }
 
   // Run the C code, collect and save the unparsed data with any errors and
@@ -187,13 +186,12 @@ class Runtime2TDMLDFDLProcessor(executable: os.Path) extends TDMLDFDLProcessor {
   // the unparsed data on its standard output, and write any error messages
   // on its standard output (all done in [[Runtime2DataProcessor.unparse]]).
   override def unparse(infosetXML: scala.xml.Node, outStream: java.io.OutputStream): TDMLUnparseResult = {
-    val tempDir = null
-    val tempInputFile = XMLUtils.convertNodeToTempFile(infosetXML, tempDir)
+    val tempInputFile = XMLUtils.convertNodeToTempFile(infosetXML, tempDir.toIO)
     val inStream = os.read.inputStream(os.Path(tempInputFile))
     val upr = dataProcessor.unparse(inStream, outStream)
     anyErrors = upr.isError
     diagnostics = upr.getDiagnostics
-    new Runtime2TDMLUnparseResult(upr)
+    new Runtime2TDMLUnparseResult(upr, tempDir)
   }
 
   def unparse(parseResult: TDMLParseResult, outStream: java.io.OutputStream): TDMLUnparseResult = {
@@ -201,7 +199,7 @@ class Runtime2TDMLDFDLProcessor(executable: os.Path) extends TDMLDFDLProcessor {
   }
 }
 
-final class Runtime2TDMLParseResult(pr: ParseResult) extends TDMLParseResult {
+final class Runtime2TDMLParseResult(pr: ParseResult, tempDir: os.Path) extends TDMLParseResult {
   override def addDiagnostic(failure: Diagnostic): Unit = pr.addDiagnostic(failure)
 
   override def getResult: Node = pr.infosetAsXML
@@ -213,9 +211,11 @@ final class Runtime2TDMLParseResult(pr: ParseResult) extends TDMLParseResult {
   override def isProcessingError: Boolean = pr.isProcessingError
 
   override def getDiagnostics: Seq[Diagnostic] = pr.getDiagnostics
+
+  override def cleanUp(): Unit = os.remove.all(tempDir)
 }
 
-final class Runtime2TDMLUnparseResult(upr: UnparseResult) extends TDMLUnparseResult {
+final class Runtime2TDMLUnparseResult(upr: UnparseResult, tempDir: os.Path) extends TDMLUnparseResult {
   override def bitPos0b: Long = upr.finalBitPos0b
 
   override def finalBitPos0b: Long = upr.finalBitPos0b
@@ -229,4 +229,6 @@ final class Runtime2TDMLUnparseResult(upr: UnparseResult) extends TDMLUnparseRes
   override def isProcessingError: Boolean = upr.isProcessingError
 
   override def getDiagnostics: Seq[Diagnostic] = upr.getDiagnostics
+
+  override def cleanUp(): Unit = os.remove.all(tempDir)
 }
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
index 5998338..06355f0 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
@@ -19,10 +19,9 @@
 <xs:schema
     elementFormDefault="qualified"
     targetNamespace="http://example.com"
+    xmlns="http://example.com"
     xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
-    xmlns:ex="http://example.com"
-    xmlns:xs="http://www.w3.org/2001/XMLSchema"
-    xmlns="http://example.com">
+    xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
     <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
 
@@ -31,67 +30,56 @@
             <dfdl:format
                 byteOrder="bigEndian"
                 encoding="UTF-8"
-                lengthUnits="bits"
                 representation="binary"
                 ref="GeneralFormat"/>
         </xs:appinfo>
     </xs:annotation>
 
-    <xs:element name="ex_ints">
+    <xs:element name="ex_nums">
         <xs:complexType>
             <xs:sequence>
-                <xs:element name="be_uint64" type="xs:unsignedLong" />
-                <xs:element name="be_uint32" type="xs:unsignedInt" />
-                <xs:element name="be_uint16" type="xs:unsignedShort" />
-                <xs:element name="be_uint8" type="xs:unsignedByte" />
-                <xs:element name="be_int64" type="xs:long" />
-                <xs:element name="be_int32" type="xs:int" />
-                <xs:element name="be_int16" type="xs:short" />
-                <xs:element name="be_int8" type="xs:byte" />
-                <xs:element name="le_uint64" type="xs:unsignedLong" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_uint32" type="xs:unsignedInt" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_uint16" type="xs:unsignedShort" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_uint8" type="xs:unsignedByte" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_int64" type="xs:long" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_int32" type="xs:int" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_int16" type="xs:short" dfdl:byteOrder="littleEndian" />
-                <xs:element name="le_int8" type="xs:byte" dfdl:byteOrder="littleEndian" />
-            </xs:sequence>
-        </xs:complexType>
-    </xs:element>
-
-    <xs:simpleType
-        name="int16"
-        dfdl:length="16"
-        dfdl:lengthKind="explicit">
-        <xs:restriction base="xs:short"/>
-    </xs:simpleType>
-    <xs:simpleType
-        name="uint8"
-        dfdl:length="8"
-        dfdl:lengthKind="explicit">
-        <xs:restriction base="xs:unsignedByte"/>
-    </xs:simpleType>
-    <xs:simpleType
-        name="uint16"
-        dfdl:length="16"
-        dfdl:lengthKind="explicit">
-        <xs:restriction base="xs:unsignedShort"/>
-    </xs:simpleType>
-
-    <xs:element name="orion_command">
-        <xs:complexType>
-            <xs:sequence>
-                <xs:element name="sync0" type="uint8" fixed="208"/>
-                <xs:element name="sync1" type="uint8" fixed="13"/>
-                <xs:element name="id" type="uint8" fixed="1"/>
-                <xs:element name="length" type="uint8" fixed="7"/>
-                <xs:element name="pan" type="int16"/>
-                <xs:element name="tilt" type="int16"/>
-                <xs:element name="mode" type="uint8" fixed="80"/>
-                <xs:element name="stabilized" type="uint8" fixed="0"/>
-                <xs:element name="impulse" type="uint8" fixed="0"/>
-                <xs:element name="checksum" type="uint16"/>
+                <xs:element name="array">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="be_int16" type="xs:short"
+                                        minOccurs="3" maxOccurs="3" dfdl:occursCountKind="fixed" />
+                            <xs:element name="be_float" type="xs:float"
+                                        minOccurs="3" maxOccurs="3" dfdl:occursCountKind="fixed" />
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+                <xs:element name="bigEndian">
+                  <xs:complexType>
+                    <xs:sequence>
+                      <xs:element name="be_double" type="xs:double" />
+                      <xs:element name="be_float" type="xs:float" />
+                      <xs:element name="be_uint64" type="xs:unsignedLong" />
+                      <xs:element name="be_uint32" type="xs:unsignedInt" />
+                      <xs:element name="be_uint16" type="xs:unsignedShort" />
+                      <xs:element name="be_uint8" type="xs:unsignedByte" />
+                      <xs:element name="be_int64" type="xs:long" />
+                      <xs:element name="be_int32" type="xs:int" />
+                      <xs:element name="be_int16" type="xs:short" />
+                      <xs:element name="be_int8" type="xs:byte" />
+                    </xs:sequence>
+                  </xs:complexType>
+                </xs:element>
+                <xs:element name="littleEndian">
+                  <xs:complexType>
+                    <xs:sequence>
+                      <xs:element name="le_uint64" type="xs:unsignedLong" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_uint32" type="xs:unsignedInt" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_uint16" type="xs:unsignedShort" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_uint8" type="xs:unsignedByte" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_int64" type="xs:long" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_int32" type="xs:int" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_int16" type="xs:short" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_int8" type="xs:byte" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_float" type="xs:float" dfdl:byteOrder="littleEndian" />
+                      <xs:element name="le_double" type="xs:double" dfdl:byteOrder="littleEndian" />
+                    </xs:sequence>
+                  </xs:complexType>
+                </xs:element>
             </xs:sequence>
         </xs:complexType>
     </xs:element>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
index 3db679c..09021a3 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
@@ -1,31 +1,28 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
 
-http://www.apache.org/licenses/LICENSE-2.0
+      http://www.apache.org/licenses/LICENSE-2.0
 
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
 -->
 
 <tdml:testSuite
-  defaultConfig="config-runtime2"
   defaultImplementations="daffodil daffodil-runtime2"
   defaultRoundTrip="onePass"
-  description="TDML tests for runtime2"
-  suiteName="TestRuntime2"
+  description="TDML tests for daffodil-runtime2"
   xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
   xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
-  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
-  xmlns="http://example.com">
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
 
   <tdml:defineConfig name="config-runtime1">
     <daf:tunables>
@@ -40,54 +37,58 @@ limitations under the License.
   </tdml:defineConfig>
 
   <tdml:parserTestCase
-    description="Parse example ex_ints"
+    config="config-runtime1"
+    description="ex_nums parse test with runtime1"
     model="TestRuntime2.dfdl.xsd"
-    name="ex_ints_parse"
-    root="ex_ints">
+    name="ex_nums_parse1"
+    root="ex_nums">
     <tdml:document>
-      <tdml:documentPart type="file">ex_ints_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_ints_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="Unparse example ex_ints"
+    config="config-runtime1"
+    description="ex_nums unparse test with runtime1"
     model="TestRuntime2.dfdl.xsd"
-    name="ex_ints_unparse"
-    root="ex_ints">
+    name="ex_nums_unparse1"
+    root="ex_nums">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">ex_ints_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse1.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">ex_ints_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
   <tdml:parserTestCase
-    description="Parse example orion_command"
+    config="config-runtime2"
+    description="ex_nums parse test with runtime2"
     model="TestRuntime2.dfdl.xsd"
-    name="orion_command_parse"
-    root="orion_command">
+    name="ex_nums_parse2"
+    root="ex_nums">
     <tdml:document>
-      <tdml:documentPart type="file">orion_command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">orion_command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
   </tdml:parserTestCase>
 
   <tdml:unparserTestCase
-    description="Unparse example orion_command"
+    config="config-runtime2"
+    description="ex_nums unparse test with runtime2"
     model="TestRuntime2.dfdl.xsd"
-    name="orion_command_unparse"
-    root="orion_command">
+    name="ex_nums_unparse2"
+    root="ex_nums">
     <tdml:infoset>
-      <tdml:dfdlInfoset type="file">orion_command_unparse.xml</tdml:dfdlInfoset>
+      <tdml:dfdlInfoset type="file">ex_nums_unparse2.xml</tdml:dfdlInfoset>
     </tdml:infoset>
     <tdml:document>
-      <tdml:documentPart type="file">orion_command_parse.dat</tdml:documentPart>
+      <tdml:documentPart type="file">ex_nums_parse.dat</tdml:documentPart>
     </tdml:document>
   </tdml:unparserTestCase>
 
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat
new file mode 100644
index 0000000..3995cb0
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
similarity index 90%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse.xml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
index 8cda886..9a1d4a1 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_unparse.xml
@@ -16,15 +16,15 @@
   limitations under the License.
 -->
 
-<orion_command xmlns="http://example.com">
+<idl:Command xmlns:idl="urn:idl:1.0">
   <sync0>208</sync0>
-  <sync1>12</sync1>
+  <sync1>13</sync1>
   <id>1</id>
   <length>7</length>
   <pan>-999</pan>
-  <tilt>-21231</tilt>
+  <tilt>-1231</tilt>
   <mode>80</mode>
   <stabilized>0</stabilized>
   <impulse>0</impulse>
   <checksum>30149</checksum>
-</orion_command>
+</idl:Command>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat
deleted file mode 100644
index e16cc72..0000000
Binary files a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat and /dev/null differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat
new file mode 100644
index 0000000..7df03f3
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml
new file mode 100644
index 0000000..d30a688
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse1.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<ex_nums xmlns="http://example.com">
+  <array>
+    <be_int16>1</be_int16>
+    <be_int16>2</be_int16>
+    <be_int16>3</be_int16>
+    <be_float>1.0</be_float>
+    <be_float>INF</be_float>
+    <be_float>NaN</be_float>
+  </array>
+  <bigEndian>
+    <be_double>1.7976931348623157E308</be_double>
+    <be_float>3.4028235E38</be_float>
+    <be_uint64>64</be_uint64>
+    <be_uint32>32</be_uint32>
+    <be_uint16>16</be_uint16>
+    <be_uint8>8</be_uint8>
+    <be_int64>-64</be_int64>
+    <be_int32>-32</be_int32>
+    <be_int16>-16</be_int16>
+    <be_int8>-8</be_int8>
+  </bigEndian>
+  <littleEndian>
+    <le_uint64>64</le_uint64>
+    <le_uint32>32</le_uint32>
+    <le_uint16>16</le_uint16>
+    <le_uint8>8</le_uint8>
+    <le_int64>-64</le_int64>
+    <le_int32>-32</le_int32>
+    <le_int16>-16</le_int16>
+    <le_int8>-8</le_int8>
+    <le_float>-1.17549435E-38</le_float>
+    <le_double>-2.2250738585072014E-308</le_double>
+  </littleEndian>
+</ex_nums>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml
new file mode 100644
index 0000000..f45a9fc
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_unparse2.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<ex_nums xmlns="http://example.com">
+  <array>
+    <be_int16>1</be_int16>
+    <be_int16>2</be_int16>
+    <be_int16>3</be_int16>
+    <be_float>1</be_float>
+    <be_float>INF</be_float>
+    <be_float>NaN</be_float>
+  </array>
+  <bigEndian>
+    <be_double>1.7976931348623157E+308</be_double>
+    <be_float>3.40282347E+38</be_float>
+    <be_uint64>64</be_uint64>
+    <be_uint32>32</be_uint32>
+    <be_uint16>16</be_uint16>
+    <be_uint8>8</be_uint8>
+    <be_int64>-64</be_int64>
+    <be_int32>-32</be_int32>
+    <be_int16>-16</be_int16>
+    <be_int8>-8</be_int8>
+  </bigEndian>
+  <littleEndian>
+    <le_uint64>64</le_uint64>
+    <le_uint32>32</le_uint32>
+    <le_uint16>16</le_uint16>
+    <le_uint8>8</le_uint8>
+    <le_int64>-64</le_int64>
+    <le_int32>-32</le_int32>
+    <le_int16>-16</le_int16>
+    <le_int8>-8</le_int8>
+    <le_float>-1.17549435E-38</le_float>
+    <le_double>-2.2250738585072014E-308</le_double>
+  </littleEndian>
+</ex_nums>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
new file mode 100644
index 0000000..8b37108
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.dfdl.xsd
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/" xmlns:idl="urn:idl:1.0" targetNamespace="urn:idl:1.0">
+  <xs:annotation>
+    <xs:appinfo source="http://www.ogf.org/dfdl/">
+      <dfdl:defineFormat name="defaults">
+        <dfdl:format alignment="8" alignmentUnits="bits" binaryBooleanFalseRep="0" binaryBooleanTrueRep="1" binaryFloatRep="ieee" binaryNumberCheckPolicy="lax" binaryNumberRep="binary" bitOrder="mostSignificantBitFirst" byteOrder="bigEndian" choiceLengthKind="implicit" encoding="utf-8" encodingErrorPolicy="replace" escapeSchemeRef="" fillByte="%#r20;" floating="no" ignoreCase="no" initiatedContent="no" initiator="" leadingSkip="0" lengthKind="implicit" lengthUnits="bits" occursCountKind= [...]
+      </dfdl:defineFormat>
+      <dfdl:format ref="idl:defaults"/>
+    </xs:appinfo>
+  </xs:annotation>
+  <xs:simpleType name="int8" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:byte"/>
+  </xs:simpleType>
+  <xs:simpleType name="int16" dfdl:length="16" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:short"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint8" dfdl:length="8" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedByte"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint16" dfdl:length="16" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedShort"/>
+  </xs:simpleType>
+  <xs:simpleType name="uint32" dfdl:length="32" dfdl:lengthKind="explicit">
+    <xs:restriction base="xs:unsignedInt"/>
+  </xs:simpleType>
+  <xs:element name="Command">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+        <xs:element name="id" fixed="1" type="idl:uint8"/>
+        <xs:element name="length" fixed="7" type="idl:uint8"/>
+        <xs:element name="pan" type="idl:int16"/>
+        <xs:element name="tilt">
+          <xs:simpleType>
+            <xs:restriction base="idl:int16">
+              <xs:minInclusive value="-1396"/>
+              <xs:maxInclusive value="733"/>
+            </xs:restriction>
+          </xs:simpleType>
+        </xs:element>
+        <xs:element name="mode" fixed="80" type="idl:uint8"/>
+        <xs:element name="stabilized" fixed="0" type="idl:uint8"/>
+        <xs:element name="impulse" fixed="0" type="idl:uint8"/>
+        <xs:element name="checksum" type="idl:uint16"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="CameraState">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+        <xs:element name="id" fixed="97" type="idl:uint8"/>
+        <xs:element name="length" fixed="5" type="idl:uint8"/>
+        <xs:element name="zoom" type="idl:int16"/>
+        <xs:element name="focus" type="idl:int16"/>
+        <xs:element name="index" fixed="0" type="idl:uint8"/>
+        <xs:element name="checksum" type="idl:uint16"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+  <xs:element name="VideoSettings">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="sync0" fixed="208" type="idl:uint8"/>
+        <xs:element name="sync1" fixed="13" type="idl:uint8"/>
+        <xs:element name="id" fixed="98" type="idl:uint8"/>
+        <xs:element name="length" fixed="14" type="idl:uint8"/>
+        <xs:element name="destIp">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="item" minOccurs="4" maxOccurs="4" dfdl:occursCountKind="fixed" type="idl:uint8"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="port" type="idl:uint16"/>
+        <xs:element name="bitrate" fixed="0" type="idl:uint32"/>
+        <xs:element name="ttl" fixed="0" type="idl:int8"/>
+        <xs:element name="streamType" fixed="0" type="idl:uint8"/>
+        <xs:element name="mjpegQuality" fixed="0" type="idl:uint8"/>
+        <xs:element name="saveSettingsAndTsPacketCount" fixed="0" type="idl:uint8"/>
+        <xs:element name="checksum" type="idl:uint16"/>
+      </xs:sequence>
+    </xs:complexType>
+  </xs:element>
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
new file mode 100644
index 0000000..110322d
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion-command.tdml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<tdml:testSuite
+  defaultConfig="config-runtime2"
+  defaultImplementations="daffodil daffodil-runtime2"
+  defaultRoundTrip="onePass"
+  description="TDML tests for orion-command"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData">
+
+  <tdml:defineConfig name="config-runtime1">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:defineConfig name="config-runtime2">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:parserTestCase
+    description="orion-command Command parse test"
+    model="orion-command.dfdl.xsd"
+    name="command_parse"
+    root="Command">
+    <tdml:document>
+      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="orion-command Command unparse test"
+    model="orion-command.dfdl.xsd"
+    name="command_unparse"
+    root="Command">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">command_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">command_parse.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+  <tdml:parserTestCase
+    description="orion-command VideoSettings parse test"
+    model="orion-command.dfdl.xsd"
+    name="video_settings_parse"
+    root="VideoSettings">
+    <tdml:document>
+      <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="orion-command VideoSettings unparse test"
+    model="orion-command.dfdl.xsd"
+    name="video_settings_unparse"
+    root="VideoSettings">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">video_settings_unparse.xml</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">video_settings_parse.dat</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat
deleted file mode 100644
index 4484b44..0000000
Binary files a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat and /dev/null differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat
new file mode 100644
index 0000000..4605ef8
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_unparse.xml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
similarity index 63%
rename from daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_unparse.xml
rename to daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
index 8874561..0307283 100644
--- a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_unparse.xml
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_unparse.xml
@@ -16,21 +16,22 @@
   limitations under the License.
 -->
 
-<ex_ints xmlns="http://example.com">
-  <be_uint64>64</be_uint64>
-  <be_uint32>32</be_uint32>
-  <be_uint16>16</be_uint16>
-  <be_uint8>8</be_uint8>
-  <be_int64>-64</be_int64>
-  <be_int32>-32</be_int32>
-  <be_int16>-16</be_int16>
-  <be_int8>-8</be_int8>
-  <le_uint64>64</le_uint64>
-  <le_uint32>32</le_uint32>
-  <le_uint16>16</le_uint16>
-  <le_uint8>8</le_uint8>
-  <le_int64>-64</le_int64>
-  <le_int32>-32</le_int32>
-  <le_int16>-16</le_int16>
-  <le_int8>-8</le_int8>
-</ex_ints>
+<idl:VideoSettings xmlns:idl="urn:idl:1.0">
+  <sync0>208</sync0>
+  <sync1>13</sync1>
+  <id>98</id>
+  <length>14</length>
+  <destIp>
+    <item>1</item>
+    <item>2</item>
+    <item>3</item>
+    <item>4</item>
+  </destIp>
+  <port>8080</port>
+  <bitrate>0</bitrate>
+  <ttl>0</ttl>
+  <streamType>0</streamType>
+  <mjpegQuality>0</mjpegQuality>
+  <saveSettingsAndTsPacketCount>0</saveSettingsAndTsPacketCount>
+  <checksum>3073</checksum>
+</idl:VideoSettings>
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
index f64d6b9..3069efa 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
@@ -39,15 +39,15 @@ import org.junit.Test
  * as you could want.
  */
 class TestCodeGenerator {
-  // Ensure all tests remove outputDir after using it
-  var outputDir: os.Path = _
+  // Ensure all tests remove tempDir after using it
+  var tempDir: os.Path = _
 
   @Before def before(): Unit = {
-    outputDir = os.temp.dir()
+    tempDir = os.temp.dir()
   }
 
   @After def after(): Unit = {
-    os.remove.all(outputDir)
+    os.remove.all(tempDir)
   }
 
   // Define a simple DFDL test schema for debugging our code path
@@ -90,20 +90,20 @@ class TestCodeGenerator {
     val cg = pf.forLanguage("c")
 
     // Generate code from the test schema successfully
-    val outputDir = cg.generateCode(None, s"${this.outputDir}")
+    val codeDir = cg.generateCode(None, tempDir.toString)
     assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
-    assert(os.exists(outputDir))
-    assert(os.exists(outputDir/"c"/"libruntime"/"generated_code.c"))
+    assert(os.exists(codeDir))
+    assert(os.exists(codeDir/"libruntime"/"generated_code.c"))
   }
 
   @Test def test_compileCode_success(): Unit = {
     // Create a CodeGenerator and generate code from the test schema
     val pf = Compiler().compileNode(testSchema)
     val cg = pf.forLanguage("c")
-    val outputDir = cg.generateCode(None, s"${this.outputDir}")
+    val codeDir = cg.generateCode(None, tempDir.toString)
 
     // Compile the generated code into an executable successfully
-    val executable = cg.compileCode(outputDir)
+    val executable = cg.compileCode(codeDir)
     assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
     assert(os.exists(executable))
   }
@@ -112,8 +112,8 @@ class TestCodeGenerator {
     // Compile the test schema into a C executable
     val pf = Compiler().compileNode(testSchema)
     val cg = pf.forLanguage("c")
-    val outputDir = cg.generateCode(None, s"${this.outputDir}")
-    val executable = cg.compileCode(outputDir)
+    val codeDir = cg.generateCode(None, tempDir.toString)
+    val executable = cg.compileCode(codeDir)
 
     // Create a Runtime2DataProcessor and parse a binary int32 number successfully
     val dp = new Runtime2DataProcessor(executable)
@@ -129,8 +129,8 @@ class TestCodeGenerator {
     // Compile the test schema into a C executable
     val pf = Compiler().compileNode(testSchema)
     val cg = pf.forLanguage("c")
-    val outputDir = cg.generateCode(None, s"${this.outputDir}")
-    val executable = cg.compileCode(outputDir)
+    val codeDir = cg.generateCode(None, tempDir.toString)
+    val executable = cg.compileCode(codeDir)
 
     // Create a Runtime2DataProcessor and unparse a binary int32 number successfully
     val dp = new Runtime2DataProcessor(executable)
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
similarity index 68%
copy from daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
copy to daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
index 88d7e12..939d9ca 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestOrionCommand.scala
@@ -21,18 +21,18 @@ import org.junit.Test
 import org.apache.daffodil.tdml.Runner
 import org.junit.AfterClass
 
-object TestRuntime2 {
+object TestOrionCommand {
   val testDir = "/org/apache/daffodil/runtime2/"
-  val runner = Runner(testDir, "TestRuntime2.tdml")
+  val runner = Runner(testDir, "orion-command.tdml")
 
   @AfterClass def shutDown(): Unit = { runner.reset }
 }
 
-class TestRuntime2 {
-  import TestRuntime2._
+class TestOrionCommand {
+  import TestOrionCommand._
 
-  @Test def test_ex_ints_parse(): Unit = { runner.runOneTest("ex_ints_parse") }
-  @Test def test_ex_ints_unparse(): Unit = { runner.runOneTest("ex_ints_unparse") }
-  @Test def test_orion_command_parse(): Unit = { runner.runOneTest("orion_command_parse") }
-  @Test def test_orion_command_unparse(): Unit = { runner.runOneTest("orion_command_unparse") }
+  @Test def test_command_parse(): Unit = { runner.runOneTest("command_parse") }
+  @Test def test_command_unparse(): Unit = { runner.runOneTest("command_unparse") }
+  @Test def test_video_settings_parse(): Unit = { runner.runOneTest("video_settings_parse") }
+  @Test def test_video_settings_unparse(): Unit = { runner.runOneTest("video_settings_unparse") }
 }
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
index 88d7e12..719acae 100644
--- a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
@@ -31,8 +31,8 @@ object TestRuntime2 {
 class TestRuntime2 {
   import TestRuntime2._
 
-  @Test def test_ex_ints_parse(): Unit = { runner.runOneTest("ex_ints_parse") }
-  @Test def test_ex_ints_unparse(): Unit = { runner.runOneTest("ex_ints_unparse") }
-  @Test def test_orion_command_parse(): Unit = { runner.runOneTest("orion_command_parse") }
-  @Test def test_orion_command_unparse(): Unit = { runner.runOneTest("orion_command_unparse") }
+  @Test def test_ex_nums_parse1(): Unit = { runner.runOneTest("ex_nums_parse1") }
+  @Test def test_ex_nums_unparse1(): Unit = { runner.runOneTest("ex_nums_unparse1") }
+  @Test def test_ex_nums_parse2(): Unit = { runner.runOneTest("ex_nums_parse2") }
+  @Test def test_ex_nums_unparse2(): Unit = { runner.runOneTest("ex_nums_unparse2") }
 }
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index a337045..f11cd27 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -28,7 +28,6 @@ import java.nio.CharBuffer
 import java.nio.LongBuffer
 import java.nio.charset.CoderResult
 import java.nio.charset.{Charset => JavaCharset}
-import java.nio.file.Files
 
 import scala.language.postfixOps
 import scala.util.Try
@@ -900,9 +899,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
 
         // we should never need blobs if we're expecting an error even if we
         // don't get errors. So clean them up immediately
-        actual.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
+        actual.cleanUp()
 
         val isErr: Boolean =
           if (actual.isProcessingError) true
@@ -1155,9 +1152,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
         // Done with the first parse result, safe to clean up blobs if there
         // was success. This won't get called on failure, which is fine--leave
         // blobs around for debugging
-        firstParseResult.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
+        firstParseResult.cleanUp()
       }
       case OnePassRoundTrip => {
         val outStream = new java.io.ByteArrayOutputStream()
@@ -1172,9 +1167,7 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
         // Done with the first parse result, safe to clean up blobs if there
         // was success. This won't get called on failure, which is fine--leave
         // blobs around for debugging
-        firstParseResult.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
+        firstParseResult.cleanUp()
       }
       case TwoPassRoundTrip => {
         //
@@ -1199,12 +1192,8 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
         // Done with the first and second parse resultrs, safe to clean up
         // blobs if there was success. This won't get called on failure, which
         // is fine--leave blobs around for debugging
-        firstParseResult.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
-        actual.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
+        firstParseResult.cleanUp()
+        actual.cleanUp()
       }
       case ThreePassRoundTrip => {
         //
@@ -1248,12 +1237,8 @@ case class ParserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
         // Done with the first parse result and second parse results. Safe to
         // clean up blobs if there was success. Leave them around for debugging
         // if there was a failure
-        firstParseResult.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
-        secondParseResult.getBlobPaths.foreach { blobPath =>
-          Files.delete(blobPath)
-        }
+        firstParseResult.cleanUp()
+        secondParseResult.cleanUp()
       }
     }
 
@@ -1409,11 +1394,12 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
       // Done with the parse results, safe to clean up blobs if there was
       // success. This won't get called on failure, which is fine--leave blobs
       // around for debugging
-      parseActual.getBlobPaths.foreach { blobPath =>
-        Files.delete(blobPath)
-      }
-
+      parseActual.cleanUp()
     }
+
+    // Done with the unparse results, safe to clean up any temporary files
+    // if they were not already cleaned up by parseActual.cleanUp() above
+    actual.cleanUp()
   }
 
   def runUnparserExpectErrors(
@@ -1477,6 +1463,10 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
             }
           }
         }
+
+        // Done with the unparse results, safe to clean up any temporary files
+        actual.cleanUp()
+
         processor.getDiagnostics ++ actual.getDiagnostics ++ dataErrors
       }
     }
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/processor/TDMLDFDLProcessor.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/processor/TDMLDFDLProcessor.scala
index 48fa414..f8a7769 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/processor/TDMLDFDLProcessor.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/processor/TDMLDFDLProcessor.scala
@@ -124,7 +124,10 @@ trait TDMLResult {
   def isValidationError: Boolean
   def isProcessingError: Boolean
   def getDiagnostics: Seq[Diagnostic]
-
+  /**
+   * Deletes any temporary files that have been generated
+   */
+  def cleanUp(): Unit
 }
 
 trait TDMLParseResult extends TDMLResult {
diff --git a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/DaffodilTDMLDFDLProcessor.scala b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/DaffodilTDMLDFDLProcessor.scala
index 523b8c0..fc9141b 100644
--- a/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/DaffodilTDMLDFDLProcessor.scala
+++ b/daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/processor/DaffodilTDMLDFDLProcessor.scala
@@ -21,6 +21,7 @@ import java.io.ByteArrayInputStream
 import java.io.ByteArrayOutputStream
 import java.io.OutputStreamWriter
 import java.nio.channels.Channels
+import java.nio.file.Files
 import java.nio.file.Path
 import java.nio.file.Paths
 
@@ -433,6 +434,8 @@ final class DaffodilTDMLParseResult(actual: DFDL.ParseResult, outputter: TDMLInf
   override def currentLocation: DataLocation = actual.resultState.currentLocation
 
   override def addDiagnostic(diag: Diagnostic): Unit = actual.addDiagnostic(diag)
+
+  override def cleanUp(): Unit = getBlobPaths.foreach { Files.delete }
 }
 
 final class DaffodilTDMLUnparseResult(actual: DFDL.UnparseResult, outStream: java.io.OutputStream) extends TDMLUnparseResult {
@@ -452,6 +455,8 @@ final class DaffodilTDMLUnparseResult(actual: DFDL.UnparseResult, outStream: jav
   override def getDiagnostics: Seq[Diagnostic] = actual.getDiagnostics
 
   override def bitPos0b: Long = ustate.bitPos0b
+
+  override def cleanUp(): Unit = { /* do nothing */ }
 }
 
 class DaffodilTDMLSAXErrorHandler extends ErrorHandler with WithDiagnostics {
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 61bb2bc..e879778 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -31,7 +31,6 @@ object Dependencies {
     "jline" % "jline" % "2.14.6",
     "com.typesafe" % "config" % "1.4.1",
     "com.lihaoyi" %% "os-lib" % "0.7.1", // for generating C source files
-    "dev.dirs" % "directories" % "21" // for caching compiled C files
   )
 
   lazy val infoset = Seq(
diff --git a/project/Rat.scala b/project/Rat.scala
index 803027b..2b646d2 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -107,8 +107,9 @@ object Rat {
     file("daffodil-japi/src/test/resources/test/japi/myData16.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myData19.dat"),
     file("daffodil-japi/src/test/resources/test/japi/myDataBroken.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_ints_parse.dat"),
-    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/orion_command_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/command_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/ex_nums_parse.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/video_settings_parse.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/01very_simple.txt"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData2.dat"),

[daffodil] 01/09: WIP: Add runtime2 backend with C code generator

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

jinterrante pushed a commit to branch runtime2-2202
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 8a2c1f4de9c6dbdf79e48b2d5d0cc58845731ab4
Author: John Interrante <in...@research.ge.com>
AuthorDate: Sun Sep 20 11:42:14 2020 -0400

    WIP: Add runtime2 backend with C code generator
    
    Add a new C code generator runtime2 backend to Daffodil.  Use a
    runtime2-2202 branch, not the main branch, to invite collaboration on
    building out code generator and shine light on any issues.  Our goal
    is to implement the smallest possible subset of DFDL in runtime2 as
    described in the "Runtime 2 Design" table of
    <https://cwiki.apache.org/confluence/display/DAFFODIL/WIP%3A+Daffodil+Runtime+2>.
    
    At this point, code generator generates C code to parse and unparse
    only 32-bit big-endian binary signed integers.  However, you already
    can run TDML tests and generate C code into an output directory with
    daffodil commands like these,
    
    ```bash
    $ cd daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/
    $ daffodil test TestRuntime2.tdml
    Creating DFDL Test Suite for TestRuntime2.tdml
    [Pass] parse_int32
    [Pass] unparse_int32
    
    Total: 2, Pass: 2, Fail: 0, Not Found: 0
    $ daffodil generate c -s TestRuntime2.dfdl.xsd outdir
    $ ls -R outdir/
    outdir/:
    c
    
    outdir/c:
    daffodil_argp.c  daffodil_argp.h  daffodil_main.c  generated_code.c  generated_code.h  infoset.c  infoset.h  stack.c  stack.h  xml_reader.c  xml_reader.h  xml_writer.c  xml_writer.h
    ```
    
    Note we will need to rebase the runtime2-2202 branch from time to time
    to keep up with changes on the main branch.  In order to avoid
    problems pulling new changes into your checkout of the runtime2-2202
    branch and seeing what was changed, you will want to use these
    specific commands:
    
    ```bash
    git switch runtime2-2202
    git pull --rebase
    git diff ORIG_HEAD..HEAD
    ```
    
    You will need a C11 or C18 compiler ("zig cc", "gcc", "clang", or
    "cc") and a tiny XML library ("libmxml.a" with header file "mxml.h").
    You can install both of them on many systems using installable binary
    packages or build and install the library from its source (the GitHub
    repository "michaelrsweet/mxml").
    
    DAFFODIL-2202
    ______________________________________________________________________
    
    Questions & loose ends:
    
    1. We want to generate C code that parses and unparses binary data as
    securely as possible.  Can we develop C functions that are more secure
    than what the current code generator uses, such as a library of parser
    combinator functions?  That will be our goal as we build out the code
    generator.
    
    2. In CodeGeneratorState.scala's defineQNameInit method, how should we
    handle multiple xmls=ns declarations?
    
    3. How much do you want the "daffodil generate" command to build an
    executable for you?  Right now "daffodil generate c" only generates C
    source files just like its name says.  I'm not sure how many
    developers will want to use the C-based CLI we've implemented in order
    to run TDML tests.  Would you want "daffodil generate c" to build an
    executable that can convert data files to XML files (outdir/c/daffodil
    parse <opts>) and back to data files (outdir/c/daffodil unparse
    <opts>)?  Or should "daffodil generate c" just give you the C source
    files so you can take whatever you need and throw away whatever you
    don't need like the CLI and XML reader/writer?
    
    4. Should we make alternative runtime backends more pluggable by using
    SPI?  For now, I've taken the easiest way (using Class.forName with a
    match expression) in Compiler.scala and TDMLRunner.scala which allows
    daffodil-core to call runtime2 without having compile time
    dependencies on any runtime2 class.
    
    5. I've avoided using heap-allocated storage anywhere in the C source
    files by using only statically allocated storage to keep the code
    simple and avoid security problems, but we may need to change some
    buffer sizes later (see char[9999] in infoset.c and mxml_node_t[100]
    in xml_writer.c).  Note that the MXML library does use heap-allocated
    storage (it copies all the strings passed into it and our XML
    reader/writer has to free MXML documents after using them), but we
    need the XML reader/writer only for running TDML tests.
---
 .github/workflows/main.yml                         |  56 +++-
 .github/workflows/sonarcloud.yml                   |  35 ++-
 build.sbt                                          |  40 ++-
 .../daffodil/generating/TestCLIGenerateC.scala     | 198 ++++++++++++++
 .../src/main/scala/org/apache/daffodil/Main.scala  | 104 ++++++-
 .../org/apache/daffodil/compiler/Compiler.scala    |  32 ++-
 .../org/apache/daffodil/dsom/ElementBase.scala     |  32 +--
 .../daffodil/grammar/ElementBaseGrammarMixin.scala |   9 +-
 .../daffodil/grammar/ElementDeclGrammarMixin.scala |   5 +-
 .../org/apache/daffodil/grammar/Grammar.scala      |   6 +-
 .../org/apache/daffodil/grammar/GrammarTerm.scala  |   2 +-
 .../org/apache/daffodil/grammar/Production.scala   |   6 +-
 .../grammar/primitives/ElementCombinator.scala     |  48 ++--
 .../primitives/PrimitivesBinaryNumber.scala        |   5 +-
 .../grammar/primitives/SequenceChild.scala         |  11 +-
 .../grammar/primitives/SequenceCombinator.scala    |  14 +-
 .../grammar/primitives/SpecifiedLength.scala       |   1 -
 .../resources/org/apache/daffodil/xsd/tdml.xsd     |   1 +
 .../resources/org/apache/daffodil/xsd/dafext.xsd   |   8 +
 .../apache/daffodil/api/DFDLParserUnparser.scala   |  40 ++-
 .../apache/daffodil/processors/DataProcessor.scala |  13 +-
 daffodil-runtime2/src/main/resources/.clang-format |  22 ++
 .../src/main/resources/c/daffodil_argp.c           | 302 +++++++++++++++++++++
 .../src/main/resources/c/daffodil_argp.h           |  46 +++-
 .../src/main/resources/c/daffodil_main.c           | 137 ++++++++++
 daffodil-runtime2/src/main/resources/c/infoset.c   | 204 ++++++++++++++
 daffodil-runtime2/src/main/resources/c/infoset.h   | 139 ++++++++++
 daffodil-runtime2/src/main/resources/c/stack.c     |  85 ++++++
 daffodil-runtime2/src/main/resources/c/stack.h     |  63 +++++
 .../src/main/resources/c/xml_reader.c              | 210 ++++++++++++++
 .../src/main/resources/c/xml_reader.h              |  30 +-
 .../src/main/resources/c/xml_writer.c              | 118 ++++++++
 .../src/main/resources/c/xml_writer.h              |  28 +-
 .../src/main/resources/examples/ex_int32.c         | 260 ++++++++++++++++++
 .../src/main/resources/examples/ex_int32.h         |  30 +-
 .../apache/daffodil/runtime2/CodeGenerator.scala   | 179 ++++++++++++
 .../daffodil/runtime2/Runtime2CodeGenerator.scala  |  67 +++++
 .../daffodil/runtime2/Runtime2DataProcessor.scala  | 206 ++++++++++++++
 .../BinaryIntegerKnownLengthCodeGenerator.scala    |  91 +++++++
 .../runtime2/generators/CodeGeneratorState.scala   | 280 +++++++++++++++++++
 ...entParseAndUnspecifiedLengthCodeGenerator.scala |  55 ++++
 .../generators/OrderedSequenceCodeGenerator.scala  |  24 +-
 .../runtime2/generators/SeqCompCodeGenerator.scala |  20 +-
 .../runtime2/Runtime2TDMLDFDLProcessor.scala       | 232 ++++++++++++++++
 .../apache/daffodil/runtime2/TestRuntime2.dfdl.xsd |  50 ++++
 .../org/apache/daffodil/runtime2/TestRuntime2.tdml |  67 +++++
 .../org/apache/daffodil/runtime2/parse_int32       | Bin 0 -> 12 bytes
 .../org/apache/daffodil/runtime2/unparse_int32     |  25 ++
 .../daffodil/runtime2/TestCodeGenerator.scala      | 144 ++++++++++
 .../apache/daffodil/runtime2/TestRuntime2.scala    |  24 +-
 .../org/apache/daffodil/tdml/TDMLRunner.scala      |   9 +-
 project/Dependencies.scala                         |   6 +-
 project/Rat.scala                                  |   1 +
 project/plugins.sbt                                |   2 +
 sonar-project.properties                           |   3 +-
 55 files changed, 3617 insertions(+), 208 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 12ae8c8..38bfa61 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -25,30 +25,60 @@ jobs:
       matrix:
         java_version: [ 8, 11, 15 ]
         scala_version: [ 2.12.11 ]
-        os: [ 'ubuntu-latest', 'windows-latest' ]
-    env:
-      SBT: sbt -J-Xms1024m -J-Xmx5120m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m ++${{ matrix.scala_version }} coverage
-      SBTNOCOV: sbt -J-Xms1024m -J-Xmx5120m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m ++${{ matrix.scala_version }}
+        os: [ ubuntu-20.04, windows-latest ]
+        include:
+          - os: ubuntu-20.04
+            shell: bash
+          - os: windows-latest
+            shell: msys2 {0}
 
     runs-on: ${{ matrix.os }}
     defaults:
       run:
-        shell: bash
-
+        shell: ${{ matrix.shell }}
+    env:
+      SBT: sbt -J-Xms1024m -J-Xmx5120m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m ++${{ matrix.scala_version }} coverage
+      SBTNOCOV: sbt -J-Xms1024m -J-Xmx5120m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m ++${{ matrix.scala_version }}
     steps:
 
       ############################################################
       # Setup
       ############################################################
 
-      - name: Checkout Repository
-        uses: actions/checkout@v2.0.0
+      - name: Install Dependencies (Linux)
+        if: runner.os == 'Linux'
+        run: sudo apt-get install -y libmxml-dev
+
+      - name: Install Dependencies (Windows)
+        if: runner.os == 'Windows'
+        uses: msys2/setup-msys2@v2
+        with:
+          install: gcc libargp-devel make pkg-config
+          path-type: inherit
 
-      - name: Install Java
-        uses: actions/setup-java@v1
+      - name: Check out mxml source (Windows)
+        if: runner.os == 'Windows'
+        uses: actions/checkout@v2.3.4
+        with:
+          repository: michaelrsweet/mxml
+          path: mxml
+
+      - name: Install mxml library (Windows)
+        if: runner.os == 'Windows'
+        run: |
+          cd mxml
+          ./configure --prefix=/usr --disable-shared --disable-threads
+          make
+          make install
+          
+      - name: Setup Java
+        uses: actions/setup-java@v1.4.3
         with:
           java-version: ${{ matrix.java_version }}
 
+      - name: Check out Repository
+        uses: actions/checkout@v2.3.4
+
       ############################################################
       # Build & Package
       ############################################################
@@ -62,9 +92,9 @@ jobs:
       - name: Package Zip & Tar
         run: $SBTNOCOV daffodil-cli/universal:packageBin daffodil-cli/universal:packageZipTarball
 
-      - name: Package RPM
-        run: $SBTNOCOV daffodil-cli/rpm:packageBin
+      - name: Package RPM (Linux)
         if: runner.os == 'Linux'
+        run: $SBTNOCOV daffodil-cli/rpm:packageBin
 
       ############################################################
       # Test
@@ -83,4 +113,4 @@ jobs:
         run: $SBT coverageAggregate
 
       - name: Upload Coverage Report
-        uses: codecov/codecov-action@v1
+        uses: codecov/codecov-action@v1.3.1
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
index 218e2a9..b20fe7d 100644
--- a/.github/workflows/sonarcloud.yml
+++ b/.github/workflows/sonarcloud.yml
@@ -14,24 +14,42 @@
 # limitations under the License.
 
 name: SonarCloud Workflow
+
 on: [push]
+
 jobs:
   sonarCloudTrigger:
     if: github.repository == 'apache/daffodil'
-    name: SonarCloud Trigger
-    runs-on: ubuntu-latest
+    name: SonarCloud ${{ matrix.java_version }}, Scala ${{ matrix.scala_version }}, ${{ matrix.os }}
     strategy:
-      fail-fast: false
       matrix:
-        scala_version: [ '2.12.11']
+        java_version: [ 11 ]
+        scala_version: [ 2.12.11 ]
+        os: [ ubuntu-20.04 ]
+
+    runs-on: ${{ matrix.os }}
+    env:
+      SBT: sbt -J-Xms1024m -J-Xmx5120m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m ++${{ matrix.scala_version }}
     steps:
 
       ############################################################
       # Setup
       ############################################################
 
-      - name: Checkout Repository
-        uses: actions/checkout@v2.0.0
+      - name: Install Dependencies (Linux)
+        if: runner.os == 'Linux'
+        run: sudo apt-get install -y libmxml-dev
+
+      - name: Setup Java
+        uses: actions/setup-java@v1.4.3
+        with:
+          java-version: ${{ matrix.java_version }}
+
+      - name: Check out Repository
+        uses: actions/checkout@v2.3.4
+        # Disabling shallow clone is recommended for improving reporting
+        with:
+          fetch-depth: 0
 
       ############################################################
       # Build & Scan
@@ -39,12 +57,9 @@ jobs:
 
       - name: Compile
         run: $SBT compile test:compile it:compile
-        shell: bash
-        env:
-          SBT: sbt -J-Xms1024m -J-Xmx5120m -J-XX:ReservedCodeCacheSize=512m -J-XX:MaxMetaspaceSize=1024m ++${{ matrix.scala_version }} coverage
 
       - name: SonarCloud Scan
-        uses: sonarsource/sonarcloud-github-action@master
+        uses: sonarsource/sonarcloud-github-action@v1.5
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
           SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
diff --git a/build.sbt b/build.sbt
index 486fccc..ed2beb0 100644
--- a/build.sbt
+++ b/build.sbt
@@ -15,6 +15,10 @@
  * limitations under the License.
  */
 
+import sbt.io.Path.flatRebase
+import sbtcc._
+import scala.collection.immutable.ListSet
+
 // Silence an errant sbt linter warning about unused sbt settings. For some
 // reason, the sbt linter thinks the below settings are set but not used, which
 // leads to a bunch of noisy warnings. But they clearly are used. Seems to be a
@@ -29,9 +33,9 @@ lazy val genManaged = taskKey[Unit]("Generate managed sources and resources")
 lazy val genProps = taskKey[Seq[File]]("Generate properties scala source")
 lazy val genSchemas = taskKey[Seq[File]]("Generated DFDL schemas")
 
-lazy val daffodil         = Project("daffodil", file(".")).configs(IntegrationTest)
+lazy val daffodil         = project.in(file(".")).configs(IntegrationTest)
                               .enablePlugins(JavaUnidocPlugin, ScalaUnidocPlugin)
-                              .aggregate(macroLib, propgen, lib, io, runtime1, runtime1Unparser, core, japi, sapi, tdmlLib, tdmlProc, cli, udf, schematron, test, testIBM1, tutorials, testStdLayout)
+                              .aggregate(macroLib, propgen, lib, io, runtime1, runtime1Unparser, runtime2, core, japi, sapi, tdmlLib, tdmlProc, cli, udf, schematron, test, testIBM1, tutorials, testStdLayout)
                               .settings(commonSettings, nopublish, ratSettings, unidocSettings)
 
 lazy val macroLib         = Project("daffodil-macro-lib", file("daffodil-macro-lib")).configs(IntegrationTest)
@@ -57,6 +61,34 @@ lazy val runtime1Unparser = Project("daffodil-runtime1-unparser", file("daffodil
                               .dependsOn(runtime1, lib % "test->test", runtime1 % "test->test")
                               .settings(commonSettings)
 
+val runtime2CFiles        = Library("libruntime2.a")
+lazy val runtime2         = Project("daffodil-runtime2", file("daffodil-runtime2")).configs(IntegrationTest)
+                              .enablePlugins(CcPlugin)
+                              .dependsOn(core, core % "test->test", tdmlProc)
+                              .settings(commonSettings)
+                              .settings(publishArtifact in (Compile, packageDoc) := false)
+                              .settings(
+                                Compile / ccTargets := ListSet(runtime2CFiles),
+                                Compile / cSources  := Map(
+                                  runtime2CFiles -> (
+                                    ((Compile / resourceDirectory).value / "c" * GlobFilter("*.c")).get() ++
+                                    ((Compile / resourceDirectory).value / "examples" * GlobFilter("*.c")).get()
+                                  )
+                                ),
+                                Compile / cIncludeDirectories := Map(
+                                  runtime2CFiles -> Seq(
+                                    (Compile / resourceDirectory).value / "c",
+                                    (Compile / resourceDirectory).value / "examples"
+                                  )
+                                ),
+                                Compile / cFlags := (Compile / cFlags).value.withDefaultValue(Seq(
+                                  "-g",
+                                  "-Wall",
+                                  "-Wextra",
+                                  "-Wno-missing-field-initializers",
+                                ))
+                              )
+
 lazy val core             = Project("daffodil-core", file("daffodil-core")).configs(IntegrationTest)
                               .dependsOn(runtime1Unparser, udf, lib % "test->test", runtime1 % "test->test")
                               .settings(commonSettings)
@@ -78,7 +110,7 @@ lazy val tdmlProc         = Project("daffodil-tdml-processor", file("daffodil-td
                               .settings(commonSettings)
 
 lazy val cli              = Project("daffodil-cli", file("daffodil-cli")).configs(IntegrationTest)
-                              .dependsOn(tdmlProc, sapi, japi, schematron % Runtime, udf % "it->test") // causes sapi/japi to be pulled in to the helper zip/tar
+                              .dependsOn(tdmlProc, runtime2, sapi, japi, schematron % Runtime, udf % "it->test") // causes runtime2/sapi/japi to be pulled into the helper zip/tar
                               .settings(commonSettings, nopublish)
                               .settings(libraryDependencies ++= Dependencies.cli)
 
@@ -131,7 +163,7 @@ lazy val commonSettings = Seq(
     "-Xfatal-warnings",
     "-Xxml:-coalescing",
     "-Xfuture"
-),
+  ),
   // add scalac options that are version specific
   scalacOptions ++= scalacCrossOptions(scalaVersion.value),
   // Workaround issue that some options are valid for javac, not javadoc.
diff --git a/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
new file mode 100644
index 0000000..9b5c9b3
--- /dev/null
+++ b/daffodil-cli/src/it/scala/org/apache/daffodil/generating/TestCLIGenerateC.scala
@@ -0,0 +1,198 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.generating
+
+import org.junit.Test
+import org.junit.Before
+import org.junit.After
+import org.apache.daffodil.CLI.Util
+import net.sf.expectit.matcher.Matchers.contains
+import net.sf.expectit.matcher.Matchers.eof
+
+class TestCLIGenerateC {
+
+  val daffodil: String = Util.binPath
+  val outputDir: os.Path = os.pwd/"generate_tmp"
+  lazy val schemaFile: String = if (Util.isWindows) Util.cmdConvert(sf) else sf
+  val sf: String = Util.daffodilPath("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd")
+
+  @Before def before(): Unit = {
+    os.remove.all(outputDir)
+  }
+
+  @After def after(): Unit = {
+    os.remove.all(outputDir)
+  }
+
+  @Test def test_CLI_Generate_schema(): Unit = {
+    val generateCmd = s"$daffodil generate c -s $schemaFile $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("")
+    try {
+      shell.sendLine(generateCmd)
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+
+    assert(os.exists(outputDir/"c"/"generated_code.c"))
+  }
+
+  @Test def test_CLI_Generate_noC_error(): Unit = {
+    val generateCmd = s"$daffodil generate -s $schemaFile $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("Unknown option 's'"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+  }
+
+  @Test def test_CLI_Generate_otherThanC_error(): Unit = {
+    val generateCmd = s"$daffodil generate vhld -s $schemaFile $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("Excess arguments provided: 'vhld"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+  }
+
+  @Test def test_CLI_Generate_noSchema_error(): Unit = {
+    val generateCmd = s"$daffodil generate c $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("Required option 'schema' not found"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+  }
+
+  @Test def test_CLI_Generate_twoSchema_error(): Unit = {
+    val generateCmd = s"$daffodil generate c -s $schemaFile -s $schemaFile $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("you should provide exactly one argument"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+  }
+
+  @Test def test_CLI_Generate_verbose(): Unit = {
+    val generateCmd = s"$daffodil -v generate c -s $schemaFile $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("[info] Time (compiling)"))
+      shell.expect(contains("[info] Time (generating)"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+
+    assert(os.exists(outputDir/"c"/"generated_code.c"))
+  }
+
+  @Test def test_CLI_Generate_root(): Unit = {
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com}ex_int32 $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("")
+    try {
+      shell.sendLine(generateCmd)
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+
+    assert(os.exists(outputDir/"c"/"generated_code.c"))
+  }
+
+  @Test def test_CLI_Generate_root_error(): Unit = {
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {ex}ex_int32 $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("Schema Definition Error"))
+      shell.expect(contains("No global element found for {ex}ex_int32"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+  }
+
+  @Test def test_CLI_Generate_namespaceNoRoot_error(): Unit = {
+    val generateCmd = s"$daffodil generate c -s $schemaFile -r {http://example.com} $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("", expectErr = true)
+    try {
+      shell.sendLine(generateCmd)
+      shell.expect(contains("'{http://example.com}' - wrong arguments format"))
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+  }
+
+  @Test def test_CLI_Generate_tunable(): Unit = {
+    val generateCmd = s"$daffodil generate c -s $schemaFile -T parseUnparsePolicy=parseOnly $outputDir"
+    val exitCmd = "exit"
+
+    val shell = Util.start("")
+    try {
+      shell.sendLine(generateCmd)
+      shell.sendLine(exitCmd)
+      shell.expect(eof())
+    } finally {
+      shell.close()
+    }
+
+    assert(os.exists(outputDir/"c"/"generated_code.c"))
+  }
+}
diff --git a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
index a94672b..75a0a0c 100644
--- a/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
+++ b/daffodil-cli/src/main/scala/org/apache/daffodil/Main.scala
@@ -37,7 +37,6 @@ import scala.concurrent.Future
 import scala.concurrent.duration.Duration
 import scala.xml.Node
 import scala.xml.SAXParseException
-
 import javax.xml.parsers.DocumentBuilderFactory
 import javax.xml.parsers.SAXParserFactory
 import javax.xml.transform.TransformerFactory
@@ -502,11 +501,48 @@ class CLIConf(arguments: Array[String]) extends scallop.ScallopConf(arguments)
     val info = tally(descr = "increment test result information output level, one level for each -i")
   }
 
+  // Generate Subcommand Options
+  val generate = new scallop.Subcommand("generate") {
+    descr("generate <language> code from a DFDL schema")
+
+    banner("""|Usage: daffodil [GLOBAL_OPTS] generate <language> [SUBCOMMAND_OPTS]
+              |""".stripMargin)
+    shortSubcommandsHelp()
+    footer("""|
+              |Run 'daffodil generate <language> --help' for subcommand specific options""".stripMargin)
+
+    val c = new scallop.Subcommand("c") {
+      banner("""|Usage: daffodil generate c -s <schema> [-r [{namespace}]<root>]
+                |                           [-c <file>] [outputDir]
+                |
+                |Generate C code from a DFDL schema to parse or unparse data
+                |
+                |Generate Options:""".stripMargin)
+
+      descr("generate C code from a DFDL schema")
+      helpWidth(76)
+
+      val language = "c"
+      val schema = opt[URI]("schema", required = true, argName = "file", descr = "the annotated DFDL schema to use to generate source code.")
+      val rootNS = opt[RefQName]("root", argName = "node", descr = "the root element of the XML file to use.  An optional namespace may be provided. This needs to be one of the top-level elements of the DFDL schema defined with --schema. Requires --schema. If not supplied uses the first element of the first schema")
+      val tunables = props[String]('T', keyName = "tunable", valueName = "value", descr = "daffodil tunable to be used when compiling schema.")
+      val config = opt[String](short = 'c', argName = "file", descr = "path to file containing configuration items.")
+      val outputDir = trailArg[String](required = false, descr = "output directory in which to generate source code. If not specified, uses current directory.")
+
+      validateOpt(schema) {
+        case None => Left("No schemas specified using the --schema option")
+        case _ => Right(Unit)
+      }
+    }
+    addSubcommand(c)
+  }
+
   addSubcommand(parse)
   addSubcommand(performance)
   addSubcommand(unparse)
   addSubcommand(save)
   addSubcommand(test)
+  addSubcommand(generate)
 
   mutuallyExclusive(trace, debug) // cannot provide both --trace and --debug
   requireSubcommand()
@@ -654,7 +690,7 @@ object Main extends Logging {
 
   def createProcessorFromSchema(schema: URI, rootNS: Option[RefQName], path: Option[String],
     tunables: Map[String, String],
-    mode: ValidationMode.Type) = {
+    mode: ValidationMode.Type): Option[DFDL.DataProcessor] = {
     val compiler = {
       val c = Compiler().withTunables(tunables)
       rootNS match {
@@ -685,6 +721,31 @@ object Main extends Logging {
     pf
   }
 
+  def createGeneratorFromSchema(schema: URI, rootNS: Option[RefQName], tunables: Map[String, String],
+                                language: String): Option[DFDL.CodeGenerator] = {
+    val compiler = {
+      val c = Compiler().withTunables(tunables)
+      rootNS match {
+        case None => c
+        case Some(RefQName(_, root, ns)) => c.withDistinguishedRootNode(root, ns.toStringOrNullIfNoNS)
+      }
+    }
+
+    val schemaSource = URISchemaSource(schema)
+    val cg = Timer.getResult("compiling", {
+      val processorFactory = compiler.compileSource(schemaSource)
+      if (!processorFactory.isError) {
+        val generator = processorFactory.forLanguage(language)
+        displayDiagnostics(generator)
+        Some(generator)
+      } else {
+        displayDiagnostics(processorFactory)
+        None
+      }
+    })
+    cg
+  }
+
   // write blobs to $PWD/daffodil-blobs/*.bin
   val blobDir = Paths.get(System.getProperty("user.dir"), "daffodil-blobs")
   val blobSuffix = ".bin"
@@ -1379,11 +1440,42 @@ object Main extends Logging {
         0
       }
 
-      case _ => {
-        // This should never happen, this is caught by validation
-        Assert.impossible()
-        // 1
+      case Some(conf.generate) => {
+        conf.subcommands match {
+          case List(conf.generate, conf.generate.c) => {
+            val generateOpts = conf.generate.c
+
+            // Read any config file and any tunables given as arguments
+            val cfgFileNode = generateOpts.config.toOption match {
+              case None => None
+              case Some(pathToConfig) => Some(this.loadConfigurationFile(pathToConfig))
+            }
+            val tunables = retrieveTunables(generateOpts.tunables, cfgFileNode)
+
+            // Create a CodeGenerator from the DFDL schema
+            val generator = createGeneratorFromSchema(generateOpts.schema(), generateOpts.rootNS.toOption,
+              tunables, generateOpts.language)
+
+            // Ask the CodeGenerator to generate source code from the DFDL schema
+            val rootNS = generateOpts.rootNS.toOption
+            val outputDir = generateOpts.outputDir.toOption.getOrElse(".")
+            val rc = generator match {
+              case Some(generator) => {
+                Timer.getResult("generating", generator.generateCode(rootNS, outputDir))
+                displayDiagnostics(generator)
+                if (generator.isError) 1 else 0
+              }
+              case None => 1
+            }
+            rc
+          }
+          // Required to avoid "match may not be exhaustive", but should never happen
+          case _ => Assert.impossible()
+        }
       }
+
+      // Required to avoid "match may not be exhaustive", but should never happen
+      case _ => Assert.impossible()
     }
 
     ret
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala b/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
index 3c74654..714ac12 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/compiler/Compiler.scala
@@ -26,6 +26,7 @@ import java.util.zip.GZIPInputStream
 import java.util.zip.ZipException
 
 import scala.collection.immutable.Queue
+import scala.util.Try
 import scala.xml.Node
 import org.apache.daffodil.api.DFDL
 import org.apache.daffodil.api.DaffodilSchemaSource
@@ -108,6 +109,27 @@ final class ProcessorFactory private(
 
   override def onPath(xpath: String) = sset.onPath(xpath)
 
+  override def forLanguage(language: String): DFDL.CodeGenerator = {
+    Assert.usage(!isError)
+
+    // Do a poor man's pluggable code generator implementation - we can replace
+    // it after we observe how the validator SPI evolves and wait for our
+    // requirements to become clearer
+    val className = language match {
+      case "c" => "org.apache.daffodil.runtime2.CodeGenerator"
+      case _ => s"code generator; source language $language is not supported"
+    }
+    import scala.language.existentials // Needed to make next line compile
+    val clazz = Try(Class.forName(className))
+    val constructor = clazz.map { _.getDeclaredConstructor(sset.root.getClass) }
+    val tryInstance = constructor.map { _.newInstance(sset.root).asInstanceOf[DFDL.CodeGenerator] }
+    val codeGenerator = tryInstance.recover {
+      case ex => throw new InvalidParserException("Error creating " + className, ex)
+    }.get
+
+    codeGenerator
+  }
+
   override def isError = sset.isError
 
   @deprecated("Use arguments to Compiler.compileSource or compileFile.", "2.6.0")
@@ -163,7 +185,7 @@ class Compiler private (var validateDFDLSchemas: Boolean,
   }
 
   @deprecated("Use constructor argument.", "2.6.0")
-  def setValidateDFDLSchemas(value: Boolean) = validateDFDLSchemas = value
+  def setValidateDFDLSchemas(value: Boolean): Unit = validateDFDLSchemas = value
 
   def withValidateDFDLSchemas(value: Boolean) = copy(validateDFDLSchemas = value)
 
@@ -279,10 +301,10 @@ class Compiler private (var validateDFDLSchemas: Boolean,
       //
       case cnf: ClassNotFoundException => {
         val cpString =
-          if (Misc.classPath.length == 0) " empty."
+          if (Misc.classPath.isEmpty) " empty."
           else ":\n" + Misc.classPath.mkString("\n\t")
         val fmtMsg = "%s\nThe class may not exist in this Java JVM version (%s), or it is missing from the classpath which is%s"
-        val msg = fmtMsg.format(cnf.getMessage(), scala.util.Properties.javaVersion, cpString)
+        val msg = fmtMsg.format(cnf.getMessage, scala.util.Properties.javaVersion, cpString)
         throw new InvalidParserException(msg, cnf)
       }
     }
@@ -329,10 +351,10 @@ class Compiler private (var validateDFDLSchemas: Boolean,
     val err = pf.isError
     val diags = pf.getDiagnostics // might be warnings even if not isError
     if (err) {
-      Assert.invariant(diags.length > 0)
+      Assert.invariant(diags.nonEmpty)
       log(LogLevel.Compile, "Compilation (ProcessorFactory) produced %d errors/warnings.", diags.length)
     } else {
-      if (diags.length > 0) {
+      if (diags.nonEmpty) {
         log(LogLevel.Compile, "Compilation (ProcessorFactory) produced %d warnings.", diags.length)
       } else {
         log(LogLevel.Compile, "ProcessorFactory completed with no errors.")
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
index e1435d9..965dfd9 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/dsom/ElementBase.scala
@@ -32,7 +32,7 @@ import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.dpath.InvalidPrimitiveDataException
 import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.api.WarnID
-import java.lang.{Integer => JInt}
+import java.lang.{ Integer => JInt }
 
 import org.apache.daffodil.dsom.walker.ElementBaseView
 import org.apache.daffodil.infoset.DataValue
@@ -122,8 +122,6 @@ trait ElementBase
    */
   def typeDef: TypeBase
 
-  private lazy val optRepValueSet = optSimpleType.flatMap(_.optRepValueSet)
-
   /**
    * The DPathElementInfo objects referenced within an IVC
    * that calls dfdl:contentLength( thingy )
@@ -441,12 +439,12 @@ trait ElementBase
   }
 
   final lazy val isParentUnorderedSequence: Boolean = {
-    optLexicalParent.map { lp =>
+    optLexicalParent.exists { lp =>
       lp match {
         case s: SequenceTermBase if !s.isOrdered => true
         case _ => false
       }
-    }.getOrElse(false)
+    }
   }
 
   private def getImplicitAlignmentInBits(thePrimType: PrimType, theRepresentation: Representation): Int = {
@@ -793,16 +791,16 @@ trait ElementBase
 
   import org.apache.daffodil.dsom.FacetTypes._
 
-  private lazy val hasPattern: Boolean = typeDef.optRestriction.map { _.hasPattern }.getOrElse(false)
-  private lazy val hasEnumeration: Boolean = typeDef.optRestriction.map { _.hasEnumeration }.getOrElse(false)
-  protected lazy val hasMinLength = typeDef.optRestriction.map { _.hasMinLength }.getOrElse(false)
-  protected lazy val hasMaxLength = typeDef.optRestriction.map { _.hasMaxLength }.getOrElse(false)
-  private lazy val hasMinInclusive = typeDef.optRestriction.map { _.hasMinInclusive }.getOrElse(false)
-  private lazy val hasMaxInclusive = typeDef.optRestriction.map { _.hasMaxInclusive }.getOrElse(false)
-  private lazy val hasMinExclusive = typeDef.optRestriction.map { _.hasMinExclusive }.getOrElse(false)
-  private lazy val hasMaxExclusive = typeDef.optRestriction.map { _.hasMaxExclusive }.getOrElse(false)
-  private lazy val hasTotalDigits = typeDef.optRestriction.map { _.hasTotalDigits }.getOrElse(false)
-  private lazy val hasFractionDigits = typeDef.optRestriction.map { _.hasFractionDigits }.getOrElse(false)
+  private lazy val hasPattern: Boolean = typeDef.optRestriction.exists(_.hasPattern)
+  private lazy val hasEnumeration: Boolean = typeDef.optRestriction.exists(_.hasEnumeration)
+  protected lazy val hasMinLength = typeDef.optRestriction.exists(_.hasMinLength)
+  protected lazy val hasMaxLength = typeDef.optRestriction.exists(_.hasMaxLength)
+  private lazy val hasMinInclusive = typeDef.optRestriction.exists(_.hasMinInclusive)
+  private lazy val hasMaxInclusive = typeDef.optRestriction.exists(_.hasMaxInclusive)
+  private lazy val hasMinExclusive = typeDef.optRestriction.exists(_.hasMinExclusive)
+  private lazy val hasMaxExclusive = typeDef.optRestriction.exists(_.hasMaxExclusive)
+  private lazy val hasTotalDigits = typeDef.optRestriction.exists(_.hasTotalDigits)
+  private lazy val hasFractionDigits = typeDef.optRestriction.exists(_.hasFractionDigits)
 
   final lazy val patternValues: Seq[FacetValueR] = {
     Assert.invariant(hasPattern)
@@ -843,7 +841,7 @@ trait ElementBase
         // we convert to the number type.
         //
         // This means we cannot check and SDE here on incorrect simple type.
-        return (zeroBD, unbBD)
+        (zeroBD, unbBD)
       }
       case st: SimpleTypeDefBase if st.optRepTypeElement.isDefined => (st.optRepTypeElement.get.minLength, st.optRepTypeElement.get.maxLength)
       case st: SimpleTypeDefBase if st.optRestriction.isDefined => {
@@ -1072,8 +1070,6 @@ trait ElementBase
     }
   }
 
-  private def gcd(a: Int, b: Int): Int = if (b == 0) a else gcd(b, a % b)
-
   /**
    * Changed to a warning - DFDL WG decided to make this check optional, but it
    * is still useful as a warning.
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
index 14be1d7..61da856 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementBaseGrammarMixin.scala
@@ -18,14 +18,11 @@
 package org.apache.daffodil.grammar
 
 import java.lang.{ Long => JLong }
-import scala.Boolean
-import scala.Long
 import org.apache.daffodil.api.WarnID
 import org.apache.daffodil.dpath.NodeInfo
 import org.apache.daffodil.dpath.NodeInfo.PrimType
 import org.apache.daffodil.dsom.PrefixLengthQuasiElementDecl
 import org.apache.daffodil.dsom.ElementBase
-import org.apache.daffodil.dsom.ExpressionCompilers
 import org.apache.daffodil.dsom.InitiatedTerminatedMixin
 import org.apache.daffodil.dsom.TunableLimitExceededError
 import org.apache.daffodil.exceptions.Assert
@@ -1016,7 +1013,7 @@ trait ElementBaseGrammarMixin
     }
 
   private def withDelimiterStack(body: => Gram) = {
-    if (hasDelimiters || immediatelyEnclosingModelGroup.map(_.hasDelimiters).getOrElse(false)) DelimiterStackCombinatorElement(this, body)
+    if (hasDelimiters || immediatelyEnclosingModelGroup.exists(_.hasDelimiters)) DelimiterStackCombinatorElement(this, body)
     else body
   }
 
@@ -1185,7 +1182,7 @@ trait ElementBaseGrammarMixin
     val exprNamespaces = exprProp.location.namespaces
     val qn = GlobalQName(Some("daf"), "outputValueCalc", XMLUtils.dafintURI)
     val expr = ExpressionCompilers.AnyRef.compileExpression(
-      qn, primType, exprText, exprNamespaces, dpathCompileInfo, false, self, dpathCompileInfo)
+      qn, primType, exprText, exprNamespaces, dpathCompileInfo, isEvaluatedAbove = false, self, dpathCompileInfo)
     expr
   }
 
@@ -1299,7 +1296,7 @@ trait ElementBaseGrammarMixin
       val len = optLengthConstant.get
       val maxLengthLong = maxLength.longValueExact
       val minLengthLong = minLength.longValueExact
-      def warn(m: String, value: Long) = SDW(WarnID.FacetExplicitLengthOutOfRange, "Explicit dfdl:length of %s is out of range for facet %sLength='%s'.", len, m, value)
+      def warn(m: String, value: Long): Unit = SDW(WarnID.FacetExplicitLengthOutOfRange, "Explicit dfdl:length of %s is out of range for facet %sLength='%s'.", len, m, value)
       if (maxLengthLong != -1 && len > maxLengthLong) warn("max", maxLengthLong)
       Assert.invariant(minLengthLong >= 0)
       if (minLengthLong > 0 && len < minLengthLong) warn("min", minLengthLong)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
index f0bc051..c294f68 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
@@ -17,8 +17,8 @@
 
 package org.apache.daffodil.grammar
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
 import org.apache.daffodil.dsom.Root
+import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
 
 trait RootGrammarMixin
   extends LocalElementGrammarMixin // can be repeating if not root
@@ -29,6 +29,5 @@ trait RootGrammarMixin
     UnicodeByteOrderMark(this) ~ documentElement
   }
 
-  private def documentElement = enclosedElement
-
+  def documentElement = enclosedElement
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala
index 4941037..9b75e5f 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Grammar.scala
@@ -41,7 +41,7 @@ abstract class BinaryGram(context: SchemaComponent, childrenArg: Seq[Gram]) exte
   protected def open: String
   protected def close: String
 
-  protected final lazy val children = {
+  lazy val children = {
     val c = childrenArg
     c
   }
@@ -87,7 +87,7 @@ class SeqComp private (context: SchemaComponent, children: Seq[Gram]) extends Bi
 
   final override lazy val parser = {
     if (parserChildren.isEmpty) new NadaParser(context.runtimeData)
-    else if (parserChildren.length == 1) parserChildren(0)
+    else if (parserChildren.length == 1) parserChildren.head
     else new SeqCompParser(context.runtimeData, parserChildren.toVector)
   }
 
@@ -105,7 +105,7 @@ class SeqComp private (context: SchemaComponent, children: Seq[Gram]) extends Bi
 
   final override lazy val unparser = {
     if (unparserChildren.isEmpty) new NadaUnparser(context.runtimeData)
-    else if (unparserChildren.length == 1) unparserChildren(0)
+    else if (unparserChildren.length == 1) unparserChildren.head
     else new SeqCompUnparser(context.runtimeData, unparserChildren.toVector)
   }
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
index db042a9..cc464bc 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/GrammarTerm.scala
@@ -65,7 +65,7 @@ abstract class Gram(contextArg: SchemaComponent)
 
   val forWhat: ParserOrUnparser = BothParserAndUnparser
 
-  final val context: SchemaComponent = contextArg
+  val context: SchemaComponent = contextArg
 
   def term = context.asInstanceOf[Term]
 
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Production.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Production.scala
index 40a4580..d10ef4e 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Production.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/Production.scala
@@ -41,7 +41,11 @@ import org.apache.daffodil.util.LogLevel
  * Prod objects are not required. They essentially provide some useful debug capability
  * because a grammar term object will display as it's name, not as some anonymous object.
  */
-final class Prod(nameArg: String, val sc: SchemaComponent, guard: Boolean, gramArg: => Gram, override val forWhat: ParserOrUnparser)
+final class Prod(nameArg: String,
+                 val sc: SchemaComponent,
+                 val guard: Boolean,
+                 gramArg: => Gram,
+                 override val forWhat: ParserOrUnparser)
   extends NamedGram(sc) {
 
   final override def deref = gram
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
index 3918f7f..2421e90 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/ElementCombinator.scala
@@ -23,13 +23,13 @@ import org.apache.daffodil.exceptions.Assert
 import org.apache.daffodil.grammar.Gram
 import org.apache.daffodil.grammar.NamedGram
 import org.apache.daffodil.grammar.Terminal
-import org.apache.daffodil.processors.parsers.ElementParser
-import org.apache.daffodil.processors.parsers.ElementParserInputValueCalc
-import org.apache.daffodil.processors.parsers.Parser
 import org.apache.daffodil.processors.parsers.CaptureEndOfContentLengthParser
 import org.apache.daffodil.processors.parsers.CaptureEndOfValueLengthParser
 import org.apache.daffodil.processors.parsers.CaptureStartOfContentLengthParser
 import org.apache.daffodil.processors.parsers.CaptureStartOfValueLengthParser
+import org.apache.daffodil.processors.parsers.ElementParser
+import org.apache.daffodil.processors.parsers.ElementParserInputValueCalc
+import org.apache.daffodil.processors.parsers.Parser
 import org.apache.daffodil.processors.unparsers.CaptureEndOfContentLengthUnparser
 import org.apache.daffodil.processors.unparsers.CaptureEndOfValueLengthUnparser
 import org.apache.daffodil.processors.unparsers.CaptureStartOfContentLengthUnparser
@@ -41,10 +41,10 @@ import org.apache.daffodil.processors.unparsers.ElementUnparserInputValueCalc
 import org.apache.daffodil.processors.unparsers.ElementUnspecifiedLengthUnparser
 import org.apache.daffodil.processors.unparsers.ElementUnusedUnparser
 import org.apache.daffodil.processors.unparsers.LeftCenteredPaddingUnparser
-import org.apache.daffodil.processors.unparsers.SimpleTypeRetryUnparser
 import org.apache.daffodil.processors.unparsers.OnlyPaddingUnparser
 import org.apache.daffodil.processors.unparsers.RightCenteredPaddingUnparser
 import org.apache.daffodil.processors.unparsers.RightFillUnparser
+import org.apache.daffodil.processors.unparsers.SimpleTypeRetryUnparser
 import org.apache.daffodil.processors.unparsers.Unparser
 import org.apache.daffodil.schema.annotation.props.gen.LengthKind
 import org.apache.daffodil.schema.annotation.props.gen.Representation
@@ -67,18 +67,18 @@ import org.apache.daffodil.grammar.EmptyGram
  * is going to make it worse.
  */
 class ElementCombinator(
-  context: ElementBase,
-  eBeforeContent: Gram,
-  eValue: Gram,
-  eAfterValue: Gram,
-  repTypeElementGram: Gram = EmptyGram
-  )
+  override val context: ElementBase,
+  val eBeforeContent: Gram,
+  val eValue: Gram,
+  val eAfterValue: Gram,
+  val repTypeElementGram: Gram = EmptyGram
+)
   extends NamedGram(context)
   with Padded {
 
   override def toString = subComb.toString()
 
-  private lazy val subComb = new ElementParseAndUnspecifiedLength(context, eBeforeContent,
+  lazy val subComb = new ElementParseAndUnspecifiedLength(context, eBeforeContent,
     eValue, eAfterValue, repTypeElementGram)
 
   override lazy val parser: Parser = {
@@ -105,7 +105,7 @@ class ElementCombinator(
     else Maybe(eAfterValue.unparser)
 
   private lazy val eReptypeUnparser: Maybe[Unparser] = repTypeElementGram.maybeUnparser
-    
+
   override lazy val unparser: Unparser = {
     if (context.isOutputValueCalc) {
       new ElementOVCSpecifiedLengthUnparser(
@@ -133,7 +133,6 @@ class ElementCombinator(
       subComb.unparser
     }
   }
-
 }
 
 case class ElementUnused(ctxt: ElementBase)
@@ -282,8 +281,11 @@ case class CaptureValueLengthEnd(ctxt: ElementBase)
       new NadaUnparser(ctxt.erd)
 }
 
-
-class ElementParseAndUnspecifiedLength(context: ElementBase, eBeforeGram: Gram, eGram: Gram, eAfterGram: Gram, repTypeElementGram: Gram)
+class ElementParseAndUnspecifiedLength(override val context: ElementBase,
+                                       val eBeforeGram: Gram,
+                                       val eGram: Gram,
+                                       val eAfterGram: Gram,
+                                       val repTypeElementGram: Gram)
   extends ElementCombinatorBase(context, eBeforeGram, eGram, eAfterGram, repTypeElementGram) {
 
   lazy val parser: Parser =
@@ -330,10 +332,10 @@ class ElementParseAndUnspecifiedLength(context: ElementBase, eBeforeGram: Gram,
   }
 }
 
-abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eGram: Gram, eGramAfter: Gram, repTypeElementGram:Gram)
+abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eGram: Gram, eGramAfter: Gram, repTypeElementGram: Gram)
   extends NamedGram(context) {
 
-  override def toString() = "<element name='" + name + "'>" + eGram.toString() + "</element>"
+  override def toString: String = "<element name='" + name + "'>" + eGram.toString + "</element>"
 
   // The order of things matters in some cases, so to be consistent we'll always use the
   // same order even when it doesn't matter
@@ -352,10 +354,10 @@ abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eG
   lazy val patDiscrim = {
     val pd = context.discriminatorStatements.filter(_.testKind == TestKind.Pattern)
     Assert.invariant(pd.size <= 1)
-    if (pd.size == 0) {
+    if (pd.isEmpty) {
       Maybe.Nope
     } else {
-      pd(0).gram(context).maybeParser
+      pd.head.gram(context).maybeParser
     }
   }
   lazy val patAssert = context.assertStatements.filter(_.testKind == TestKind.Pattern).map(_.gram(context).parser).toArray
@@ -363,10 +365,10 @@ abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eG
   lazy val testDiscrim = {
     val td = context.discriminatorStatements.filter(_.testKind == TestKind.Expression)
     Assert.invariant(td.size <= 1)
-    if (td.size == 0) {
+    if (td.isEmpty) {
       Maybe.Nope
     } else {
-      td(0).gram(context).maybeParser
+      td.head.gram(context).maybeParser
     }
   }
   lazy val testAssert = context.assertStatements.filter(_.testKind == TestKind.Expression).map(_.gram(context).parser).toArray
@@ -376,7 +378,7 @@ abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eG
   lazy val eParser: Maybe[Parser] = eGram.maybeParser
 
   lazy val eAfterParser: Maybe[Parser] = eGramAfter.maybeParser
-  
+
   lazy val eRepTypeParser: Maybe[Parser] = repTypeElementGram.maybeParser
 
   def parser: Parser
@@ -388,7 +390,7 @@ abstract class ElementCombinatorBase(context: ElementBase, eGramBefore: Gram, eG
   lazy val eUnparser: Maybe[Unparser] = eGram.maybeUnparser
 
   lazy val eAfterUnparser: Maybe[Unparser] = eGramAfter.maybeUnparser
-  
+
   lazy val eRepTypeUnparser: Maybe[Unparser] = repTypeElementGram.maybeUnparser
 
   def unparser: Unparser
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesBinaryNumber.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesBinaryNumber.scala
index 3e1423c..0939725 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesBinaryNumber.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/PrimitivesBinaryNumber.scala
@@ -47,13 +47,16 @@ class BinaryIntegerRuntimeLength(val e: ElementBase, signed: Boolean) extends Te
   override lazy val unparser: Unparser = new BinaryIntegerRuntimeLengthUnparser(e.elementRuntimeData, signed, e.lengthEv, e.lengthUnits)
 }
 
-class BinaryIntegerKnownLength(val e: ElementBase, signed: Boolean, lengthInBits: Long) extends Terminal(e, true) {
+class BinaryIntegerKnownLength(val e: ElementBase,
+                               val signed: Boolean,
+                               val lengthInBits: Long) extends Terminal(e, true) {
 
   override lazy val parser = {
     new BinaryIntegerKnownLengthParser(e.elementRuntimeData, signed, lengthInBits.toInt)
   }
 
   override lazy val unparser: Unparser = new BinaryIntegerKnownLengthUnparser(e.elementRuntimeData, signed, lengthInBits.toInt)
+
 }
 
 class BinaryIntegerPrefixedLength(val e: ElementBase, signed: Boolean) extends Terminal(e, true) {
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
index cf60870..ea6ed3c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceChild.scala
@@ -17,17 +17,16 @@
 
 package org.apache.daffodil.grammar.primitives
 
-import org.apache.daffodil.grammar._
-import org.apache.daffodil.dsom._
-import org.apache.daffodil.processors.unparsers._
-import org.apache.daffodil.processors.parsers._
 import org.apache.daffodil.dpath.NodeInfo
+import org.apache.daffodil.dsom._
 import org.apache.daffodil.exceptions.Assert
-import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
+import org.apache.daffodil.grammar._
+import org.apache.daffodil.processors.parsers._
+import org.apache.daffodil.processors.unparsers._
 import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
 import org.apache.daffodil.schema.annotation.props.gen.LengthKind
+import org.apache.daffodil.schema.annotation.props.gen.OccursCountKind
 import org.apache.daffodil.schema.annotation.props.gen.Representation
-import org.apache.daffodil.processors.parsers._
 
 /**
  * A SequenceChild is exactly that, a child Term of a Sequence
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
index f6f9185..2a4b035 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SequenceCombinator.scala
@@ -17,12 +17,12 @@
 
 package org.apache.daffodil.grammar.primitives
 
-import org.apache.daffodil.grammar.Terminal
-import org.apache.daffodil.grammar.Gram
 import org.apache.daffodil.dsom._
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.grammar.Terminal
 import org.apache.daffodil.processors.parsers._
-import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
 import org.apache.daffodil.processors.unparsers._
+import org.apache.daffodil.schema.annotation.props.SeparatorSuppressionPolicy
 import org.apache.daffodil.util.Misc
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.MaybeInt
@@ -31,14 +31,14 @@ import org.apache.daffodil.util.MaybeInt
  * Base class for all kinds of sequences.
  */
 abstract class SequenceCombinator(sq: SequenceTermBase, sequenceChildren: Seq[SequenceChild])
-  extends Terminal(sq, sequenceChildren.length > 0) {
+  extends Terminal(sq, sequenceChildren.nonEmpty) {
 
   /**
    * Shorthand for getting the sequence runtime data.
    */
   val srd = sq.sequenceRuntimeData
 
-  override def toString() =
+  override def toString: String =
     "<" + Misc.getNameFromClass(this) + ">" +
       sequenceChildren.map { _.toString() }.mkString +
       "</" + Misc.getNameFromClass(this) + ">"
@@ -70,7 +70,7 @@ class OrderedSequence(sq: SequenceTermBase, sequenceChildrenArg: Seq[SequenceChi
   // the mta parser differently to avoid this
   private lazy val sepUnparser = sepGram.unparser
 
-  private lazy val sequenceChildren = sequenceChildrenArg.toVector
+  lazy val sequenceChildren = sequenceChildrenArg.toVector
 
   override lazy val parser: Parser = sq.hasSeparator match {
     case true => new OrderedSeparatedSequenceParser(
@@ -148,10 +148,8 @@ class UnorderedSequence(sq: SequenceTermBase, sequenceChildrenArg: Seq[SequenceC
 
   private lazy val sequenceChildren = sequenceChildrenArg.toVector
 
-
   private lazy val parsers = alternatives.map(_.parser)
 
-
   override lazy val parser: Parser = {
 
     lazy val choiceParser = new ChoiceParser(srd, parsers.toVector)
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala
index f1934d2..7c112b7 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala
+++ b/daffodil-core/src/main/scala/org/apache/daffodil/grammar/primitives/SpecifiedLength.scala
@@ -141,7 +141,6 @@ class SpecifiedLengthImplicit(e: ElementBase, eGram: => Gram, nBits: Long)
     eParser,
     e.elementRuntimeData,
     nBits)
-
 }
 
 class SpecifiedLengthPrefixed(e: ElementBase, eGram: => Gram, bitsMultiplier: Int)
diff --git a/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd b/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
index 2cd8bfc..8371293 100644
--- a/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
+++ b/daffodil-lib/src/main/resources/org/apache/daffodil/xsd/tdml.xsd
@@ -101,6 +101,7 @@
   <simpleType name="implementationItem">
     <restriction base="xs:token">
       <enumeration value="daffodil"/>
+      <enumeration value="daffodil-runtime2"/>
       <enumeration value="ibm"/>
     </restriction>
   </simpleType>
diff --git a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
index fcdb128..40c9a33 100644
--- a/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
+++ b/daffodil-propgen/src/main/resources/org/apache/daffodil/xsd/dafext.xsd
@@ -504,6 +504,14 @@
             </xs:documentation>
           </xs:annotation>
         </xs:element>
+        <xs:element name="tdmlImplementation" type="xs:string" default="daffodil" minOccurs="0">
+          <xs:annotation>
+            <xs:documentation>
+              TDMLDFDLProcessorFactory implementation to use when running TDML tests.
+              Allowed values are "daffodil" (default), "daffodil-runtime2", and "ibm".
+            </xs:documentation>
+          </xs:annotation>
+        </xs:element>
         <xs:element name="tempFilePath" type="xs:string" default="This string is ignored. Default value is taken from java.io.tmpdir property"  minOccurs="0">
           <xs:annotation>
             <xs:documentation>
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/api/DFDLParserUnparser.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/api/DFDLParserUnparser.scala
index b0f27ca..1f0ee1a 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/api/DFDLParserUnparser.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/api/DFDLParserUnparser.scala
@@ -32,6 +32,7 @@ import org.apache.daffodil.util.Coroutine
 import org.apache.daffodil.util.Maybe
 import org.apache.daffodil.util.Maybe.Nope
 import org.xml.sax.SAXException
+import org.apache.daffodil.xml.RefQName
 
 /**
  * This file contains traits that define an abstract API that any DFDL processor
@@ -111,7 +112,7 @@ object DFDL {
     def setExternalDFDLVariable(name: String, namespace: String, value: String): Unit
 
     /**
-     * Compilation returns a parser factory, which must be interrogated for diagnostics
+     * Compilation returns a [[ProcessorFactory]], which must be interrogated for diagnostics
      * to see if compilation was successful or not.
      */
     def compileSource(
@@ -123,7 +124,8 @@ object DFDL {
   }
 
   /**
-   * The point of processor factory is to allow compilation of the path expression.
+   * The point of [[ProcessorFactory]] is to allow compilation of the path expression
+   * and/or generation of source code to process data matching the compiled schema
    */
   trait ProcessorFactory extends WithDiagnostics {
 
@@ -147,11 +149,41 @@ object DFDL {
     @deprecated("Use arguments to Compiler.compileSource or compileFile.", "2.6.0")
     def setDistinguishedRootNode(name: String, namespace: String = null): Unit
 
+    /**
+     * Returns a [[DataProcessor]] to process data matching a compiled XPath expression
+     * @param xpath XPath expression in DFDL schema that data should match (you can use only "/" at this time)
+     */
     def onPath(xpath: String): DataProcessor
+
+    /**
+     * Returns a [[CodeGenerator]] to generate code from a DFDL schema to parse or unparse data
+     * @param language source language for generated code (you can use only "c" at this time)
+     */
+    def forLanguage(language: String): CodeGenerator
   }
 
-  trait DataProcessor extends WithDiagnostics {
+  /**
+   * Source code generation and compilation is performed with a language-specific [[CodeGenerator]],
+   * which must be interrogated for diagnostics to see if each call was successful or not.
+   */
+  trait CodeGenerator extends WithDiagnostics {
+    /**
+     * Generates language-specific code from a DFDL schema to parse or unparse data
+     * @param rootNS one of the top-level elements of the DFDL schema (if not supplied, uses first top-level element)
+     * @param outputDir output directory in which to generate code
+     * @return path of output directory containing generated code
+     */
+    def generateCode(rootNS: Option[RefQName], outputDir: String): os.Path
+
+    /**
+     * Compiles the generated code so it can be used by a TDML test or something else
+     * @param outputDir path of output directory containing generated code
+     * @return path of executable built from generated code
+     */
+    def compileCode(outputDir: os.Path): os.Path
+  }
 
+  trait DataProcessorBase {
     /**
      * Returns a data processor with all the same state, but the validation mode changed to that of the argument.
      *
@@ -184,7 +216,9 @@ object DFDL {
     def setTunable(tunable: String, value: String): Unit
     @deprecated("Use withTunables.", "2.6.0")
     def setTunables(tunables: Map[String,String]): Unit
+}
 
+  trait DataProcessor extends DataProcessorBase with WithDiagnostics {
     /**
      * Creates a new instance of XMLReader for SAX Parsing
      */
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
index 50c0692..903ff08 100644
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/processors/DataProcessor.scala
@@ -27,17 +27,17 @@ import java.nio.file.Files
 import java.util.zip.GZIPOutputStream
 
 import scala.collection.immutable.Queue
+import scala.collection.mutable
 
 import org.apache.daffodil.Implicits._; object INoWarn4 {
   ImplicitsSuppressUnusedImportWarning() }
+import org.apache.daffodil.api.DFDL
+import org.apache.daffodil.api.DaffodilTunables
 import org.apache.daffodil.api.ValidationException
 import org.apache.daffodil.api.ValidationFailure
+import org.apache.daffodil.api.ValidationMode
 import org.apache.daffodil.api.ValidationResult
 import org.apache.daffodil.api.Validator
-import org.apache.daffodil.validation.XercesValidatorFactory
-import org.apache.daffodil.api.DFDL
-import org.apache.daffodil.api.DaffodilTunables
-import org.apache.daffodil.api.ValidationMode
 import org.apache.daffodil.api.WithDiagnostics
 import org.apache.daffodil.debugger.Debugger
 import org.apache.daffodil.dsom.TunableLimitExceededError
@@ -678,7 +678,6 @@ class DataProcessor private (
       UnparseError(Nope, One(state.currentLocation), "Expected no remaining events, but received %s.", ev.get)
     }
   }
-
 }
 
 class ParseResult(dp: DataProcessor, override val resultState: PState)
@@ -689,7 +688,7 @@ class ParseResult(dp: DataProcessor, override val resultState: PState)
    * To be successful here, we need to capture parse/validation
    * errors and add them to the Diagnostics list in the PState.
    *
-   * @param bytes the parsed Infoset
+   * @param bytes the XML infoset from the parse
    */
   def validateResult(bytes: Array[Byte]): Unit = {
     Assert.usage(resultState.processorStatus eq Success)
@@ -732,5 +731,3 @@ class UnparseResult(dp: DataProcessor, ustate: UState)
     encodingInfo.knownEncodingName
   }
 }
-
-
diff --git a/daffodil-runtime2/src/main/resources/.clang-format b/daffodil-runtime2/src/main/resources/.clang-format
new file mode 100644
index 0000000..57fbb91
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/.clang-format
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+AlignConsecutiveDeclarations: true
+AllowShortFunctionsOnASingleLine: None
+AlwaysBreakAfterReturnType: TopLevelDefinitions
+BasedOnStyle: llvm
+BreakBeforeBraces: Allman
+IndentWidth: 4
+KeepEmptyLinesAtTheStartOfBlocks: false
diff --git a/daffodil-runtime2/src/main/resources/c/daffodil_argp.c b/daffodil-runtime2/src/main/resources/c/daffodil_argp.c
new file mode 100644
index 0000000..7e27972
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/daffodil_argp.c
@@ -0,0 +1,302 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "daffodil_argp.h" // for daffodil_cli, daffodil_parse_cli, ...
+#include <argp.h>          // for argp_state, argp_error, error_t, argp_parse
+#include <stdio.h>         // for sprintf
+#include <stdlib.h>        // for putenv, NULL
+#include <string.h>        // for strlen, strcmp
+
+// Initialize our "daffodil" name and version
+
+const char *argp_program_version = "Apache Daffodil (runtime2) 0.1";
+
+// Initialize our "daffodil parse" CLI options
+
+struct daffodil_parse_cli daffodil_parse = {
+    "xml", // default infoset type
+    "-",   // default infile
+    "-",   // default outfile
+};
+
+static const struct argp_option parse_options[] = {
+    {"infoset-type", 'I', "<infoset_type>", 0,
+     "Infoset type to output. Must be one of 'xml' or 'null'"},
+
+    {"output", 'o', "<file>", 0,
+     "Write output to a given file. If not given or is -, output is written to "
+     "stdout"},
+
+    {0}};
+
+static error_t parse_handler(int key, char *arg, struct argp_state *state);
+
+static const char parse_args_doc[] = "[infile]";
+
+static const char parse_doc[] =
+    "\n"
+    "Parse a file using a DFDL schema\n"
+    "\n"
+    "Parse Options:"
+    "\v"
+    " Trailing arguments:\n"
+    "  infile (not required)      input file to parse. "
+    "If not specified, or a value of -, reads from stdin";
+
+static const struct argp parse_argp = {
+    parse_options,  // array of CLI options
+    parse_handler,  // function to get these CLI options
+    parse_args_doc, // short usage documentation
+    parse_doc,      // long help documentation
+};
+
+// Handle callbacks to get our "daffodil parse" CLI options
+
+static error_t
+parse_handler(int key, char *arg, struct argp_state *state)
+{
+    struct daffodil_parse_cli *parse = state->input;
+
+    switch (key)
+    {
+    case 'I':
+        parse->infoset_converter = arg;
+        break;
+
+    case 'o':
+        parse->outfile = arg;
+        break;
+
+    case ARGP_KEY_ARG:
+        if (state->arg_num)
+        {
+            argp_error(state, "too many arguments: %s", arg);
+        }
+        parse->infile = arg;
+        break;
+
+    default:
+        return ARGP_ERR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+// Parse our "daffodil parse" command line interface
+
+static error_t
+parse_daffodil_parse_cli(struct argp_state *state)
+{
+    int    argc = state->argc - state->next + 1;
+    char **argv = &state->argv[state->next - 1];
+    char * old_cmd = argv[0];
+    char   new_cmd[strlen(state->name) + strlen(" parse") + 1];
+
+    sprintf(new_cmd, "%s parse", state->name);
+    argv[0] = new_cmd;
+
+    error_t status = argp_parse(&parse_argp, argc, argv, ARGP_IN_ORDER, &argc,
+                                &daffodil_parse);
+
+    argv[0] = old_cmd;
+    state->next += argc - 1;
+
+    return status;
+}
+
+// Initialize our "daffodil unparse" CLI options
+
+struct daffodil_unparse_cli daffodil_unparse = {
+    "xml", // default infoset type
+    "-",   // default infile
+    "-",   // default outfile
+};
+
+static const struct argp_option unparse_options[] = {
+    {"infoset-type", 'I', "<infoset_type>", 0,
+     "Infoset type to unparse. Must be 'xml'"},
+
+    {"output", 'o', "<file>", 0,
+     "Write output to file. If not given or is -, output is written to "
+     "standard output"},
+
+    {0}};
+
+static error_t unparse_handler(int key, char *arg, struct argp_state *state);
+
+static const char unparse_args_doc[] = "[infile]";
+
+static const char unparse_doc[] =
+    "\n"
+    "Unparse an infoset file using a DFDL schema\n"
+    "\n"
+    "Unparse Options:"
+    "\v"
+    " Trailing arguments:\n"
+    "  infile (not required)      input file to unparse. If not specified, or "
+    "a value of -, reads from stdin";
+
+static const struct argp unparse_argp = {
+    unparse_options,  // array of CLI options
+    unparse_handler,  // function to get these CLI options
+    unparse_args_doc, // short usage documentation
+    unparse_doc,      // long help documentation
+};
+
+// Handle callbacks to get our "daffodil unparse" CLI options
+
+static error_t
+unparse_handler(int key, char *arg, struct argp_state *state)
+{
+    struct daffodil_unparse_cli *unparse = state->input;
+
+    switch (key)
+    {
+    case 'I':
+        unparse->infoset_converter = arg;
+        break;
+
+    case 'o':
+        unparse->outfile = arg;
+        break;
+
+    case ARGP_KEY_ARG:
+        if (state->arg_num)
+        {
+            argp_error(state, "too many arguments: %s", arg);
+        }
+        unparse->infile = arg;
+        break;
+
+    default:
+        return ARGP_ERR_UNKNOWN;
+    }
+
+    return 0;
+}
+
+// Parse our "daffodil unparse" command line interface
+
+static error_t
+parse_daffodil_unparse_cli(struct argp_state *state)
+{
+    int    argc = state->argc - state->next + 1;
+    char **argv = &state->argv[state->next - 1];
+    char * old_cmd = argv[0];
+    char   new_cmd[strlen(state->name) + strlen(" unparse") + 1];
+
+    sprintf(new_cmd, "%s unparse", state->name);
+    argv[0] = new_cmd;
+
+    error_t status = argp_parse(&unparse_argp, argc, argv, ARGP_IN_ORDER, &argc,
+                                &daffodil_unparse);
+
+    argv[0] = old_cmd;
+    state->next += argc - 1;
+
+    return status;
+}
+
+// Initialize our "daffodil" CLI options
+
+struct daffodil_cli daffodil_cli = {
+    DAFFODIL_NONE, // default subcommand
+    0,             // default verbosity
+};
+
+static const struct argp_option daffodil_options[] = {
+    {"verbose", 'v', 0, 0, "Increment verbosity level, one level for each -v",
+     -1},
+
+    {0}};
+
+static error_t daffodil_handler(int key, char *arg, struct argp_state *state);
+
+static const char daffodil_args_doc[] = "<subcommand> [SUBCOMMAND_OPTION...]";
+
+static const char daffodil_doc[] =
+    "\n"
+    "Global Options:"
+    "\v"
+    "Subcommands:\n"
+    "  parse         Parse data to a DFDL infoset\n"
+    "  unparse       Unparse a DFDL infoset\n"
+    "\n"
+    "Run 'daffodil <subcommand> --help' for subcommand specific options";
+
+static const struct argp daffodil_argp = {
+    daffodil_options,  // array of CLI options
+    daffodil_handler,  // function to get these CLI options
+    daffodil_args_doc, // short usage documentation
+    daffodil_doc,      // long help documentation
+};
+
+// Handle callbacks to get our "daffodil" CLI options
+
+static error_t
+daffodil_handler(int key, char *arg, struct argp_state *state)
+{
+    struct daffodil_cli *cli = state->input;
+    error_t              status = 0;
+
+    switch (key)
+    {
+    case 'v':
+        cli->verbosity++;
+        break;
+
+    case ARGP_KEY_ARG:
+        if (strcmp(arg, "parse") == 0)
+        {
+            cli->subcommand = DAFFODIL_PARSE;
+            status = parse_daffodil_parse_cli(state);
+        }
+        else if (strcmp(arg, "unparse") == 0)
+        {
+            cli->subcommand = DAFFODIL_UNPARSE;
+            status = parse_daffodil_unparse_cli(state);
+        }
+        else
+        {
+            argp_error(state, "%s is not a valid subcommand", arg);
+        }
+        break;
+
+    case ARGP_KEY_END:
+        if (cli->subcommand == DAFFODIL_NONE)
+        {
+            argp_error(state, "missing subcommand");
+        }
+        break;
+
+    default:
+        return ARGP_ERR_UNKNOWN;
+    }
+
+    return status;
+}
+
+// Parse our "daffodil" command line interface
+
+error_t
+parse_daffodil_cli(int argc, char **argv)
+{
+    static char *argp_help_fmt = "ARGP_HELP_FMT=no-dup-args-note";
+    putenv(argp_help_fmt); // Do not pass an automatic variable to putenv
+    return argp_parse(&daffodil_argp, argc, argv, ARGP_IN_ORDER, NULL,
+                      &daffodil_cli);
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/main/resources/c/daffodil_argp.h
similarity index 51%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/main/resources/c/daffodil_argp.h
index f0bc051..c870123 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/main/resources/c/daffodil_argp.h
@@ -15,20 +15,42 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+#ifndef DAFFODIL_ARGP_H
+#define DAFFODIL_ARGP_H
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+// Parse our "daffodil" command line interface
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+extern int parse_daffodil_cli(int argc, char **argv);
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
-  }
+// Get our "daffodil" CLI options
 
-  private def documentElement = enclosedElement
+extern struct daffodil_cli
+{
+    enum daffodil_subcommand
+    {
+        DAFFODIL_NONE,
+        DAFFODIL_PARSE,
+        DAFFODIL_UNPARSE
+    } subcommand;
+    int verbosity;
+} daffodil_cli;
 
-}
+// Get our "daffodil parse" CLI options
+
+extern struct daffodil_parse_cli
+{
+    const char *infoset_converter;
+    const char *infile;
+    const char *outfile;
+} daffodil_parse;
+
+// Get our "daffodil unparse" CLI options
+
+extern struct daffodil_unparse_cli
+{
+    const char *infoset_converter;
+    const char *infile;
+    const char *outfile;
+} daffodil_unparse;
+
+#endif // DAFFODIL_ARGP_H
diff --git a/daffodil-runtime2/src/main/resources/c/daffodil_main.c b/daffodil-runtime2/src/main/resources/c/daffodil_main.c
new file mode 100644
index 0000000..ce6d62b
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/daffodil_main.c
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "daffodil_argp.h" // for daffodil_cli, parse_daffodil_cli, ...
+#include "infoset.h"       // for InfosetBase, walkInfoset, rootElement, ...
+#include "xml_reader.h"    // for xmlReaderMethods, XMLReader
+#include "xml_writer.h"    // for xmlWriterMethods, XMLWriter
+#include <error.h>         // for error
+#include <stdio.h>         // for FILE, perror, fclose, fopen, stdin
+#include <stdlib.h>        // for exit, EXIT_FAILURE
+#include <string.h>        // for strcmp
+
+// Open a file or exit if it can't be opened
+
+static FILE *
+fopen_or_exit(FILE *stream, const char *pathname, const char *mode)
+{
+    if (strcmp(pathname, "-") != 0)
+    {
+        stream = fopen(pathname, mode);
+        if (!stream)
+        {
+            perror("Error opening file: ");
+            exit(EXIT_FAILURE);
+        }
+    }
+    return stream;
+}
+
+// Close a stream or exit if it can't be closed
+
+static void
+fclose_or_exit(FILE *stream, FILE *stdin_stdout)
+{
+    if (stream != stdin_stdout && fclose(stream) != 0)
+    {
+        perror("Error closing file: ");
+        exit(EXIT_FAILURE);
+    }
+}
+
+// Print an error and exit if an error occurred or continue otherwise
+
+static void
+continue_or_exit(const char *error_msg)
+{
+    if (error_msg)
+    {
+        error(EXIT_FAILURE, 0, "%s", error_msg);
+    }
+}
+
+// Define our daffodil program's main entry point
+
+int
+main(int argc, char *argv[])
+{
+    // Parse our "daffodil" command line options
+    int status = parse_daffodil_cli(argc, argv);
+
+    if (status == 0)
+    {
+        FILE *       input = stdin;
+        FILE *       output = stdout;
+        InfosetBase *root = rootElement();
+
+        if (daffodil_cli.subcommand == DAFFODIL_PARSE)
+        {
+            // Open our input and output files if given as arguments.
+            input = fopen_or_exit(input, daffodil_parse.infile, "r");
+            output = fopen_or_exit(output, daffodil_parse.outfile, "w");
+
+            // Parse the input file into our infoset.
+            PState      pstate = {input};
+            const char *error_msg = root->erd->parseSelf(root, &pstate);
+            continue_or_exit(error_msg);
+
+            if (strcmp(daffodil_parse.infoset_converter, "xml") == 0)
+            {
+                // Visit the infoset and print XML from it.
+                XMLWriter xmlWriter = {xmlWriterMethods, output};
+                error_msg = walkInfoset((VisitEventHandler *)&xmlWriter, root);
+                continue_or_exit(error_msg);
+            }
+            else
+            {
+                error(EXIT_FAILURE, 0, "Cannot write infoset type '%s'",
+                      daffodil_parse.infoset_converter);
+            }
+        }
+        else if (daffodil_cli.subcommand == DAFFODIL_UNPARSE)
+        {
+            // Open our input and output files if given as arguments.
+            input = fopen_or_exit(input, daffodil_unparse.infile, "r");
+            output = fopen_or_exit(output, daffodil_unparse.outfile, "w");
+
+            if (strcmp(daffodil_unparse.infoset_converter, "xml") == 0)
+            {
+                // Initialize our infoset's values from the XML data.
+                XMLReader   xmlReader = {xmlReaderMethods, input, root};
+                const char *error_msg =
+                    walkInfoset((VisitEventHandler *)&xmlReader, root);
+                continue_or_exit(error_msg);
+            }
+            else
+            {
+                error(EXIT_FAILURE, 0, "Cannot read infoset type '%s'",
+                      daffodil_unparse.infoset_converter);
+            }
+
+            // Unparse our infoset to the output file.
+            UState      ustate = {output};
+            const char *error_msg = root->erd->unparseSelf(root, &ustate);
+            continue_or_exit(error_msg);
+        }
+
+        // Close our input and out files if we opened them.
+        fclose_or_exit(input, stdin);
+        fclose_or_exit(output, stdout);
+    }
+
+    return status;
+}
diff --git a/daffodil-runtime2/src/main/resources/c/infoset.c b/daffodil-runtime2/src/main/resources/c/infoset.c
new file mode 100644
index 0000000..f0c8bff
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/infoset.c
@@ -0,0 +1,204 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "infoset.h" // for walkInfoset, VisitEventHandler, ...
+#include <string.h>  // for memccpy
+
+// get_erd_name, get_erd_xmlns, get_erd_ns - get name and xmlns
+// attribute/value from ERD to use on XML element
+
+const char *
+get_erd_name(const ERD *erd)
+{
+    static char name[9999];
+    char *      next = name;
+    char *      last = name + sizeof(name) - 1;
+
+    if (next && erd->namedQName.prefix)
+    {
+        next = memccpy(next, erd->namedQName.prefix, 0, last - next);
+        if (next)
+        {
+            --next;
+        }
+    }
+    if (next && erd->namedQName.prefix)
+    {
+        next = memccpy(next, ":", 0, last - next);
+        if (next)
+        {
+            --next;
+        }
+    }
+    if (next)
+    {
+        next = memccpy(next, erd->namedQName.local, 0, last - next);
+        if (next)
+        {
+            --next;
+        }
+    }
+    if (!next)
+    {
+        *last = 0;
+    }
+
+    return name;
+}
+
+const char *
+get_erd_xmlns(const ERD *erd)
+{
+    if (erd->namedQName.ns)
+    {
+        static char xmlns[9999];
+        char *      next = xmlns;
+        char *      last = xmlns + sizeof(xmlns) - 1;
+
+        next = memccpy(next, "xmlns", 0, last - next);
+        if (next)
+        {
+            --next;
+        }
+
+        if (next && erd->namedQName.prefix)
+        {
+            next = memccpy(next, ":", 0, last - next);
+            if (next)
+            {
+                --next;
+            }
+        }
+        if (next && erd->namedQName.prefix)
+        {
+            next = memccpy(next, erd->namedQName.prefix, 0, last - next);
+            if (next)
+            {
+                --next;
+            }
+        }
+        if (!next)
+        {
+            *last = 0;
+        }
+
+        return xmlns;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+const char *
+get_erd_ns(const ERD *erd)
+{
+    return erd->namedQName.ns;
+}
+
+// walkInfosetNode - recursively walk an infoset node and call
+// VisitEventHandler methods
+
+static const char *
+walkInfosetNode(const VisitEventHandler *handler, const InfosetBase *infoNode)
+{
+    const char *error_msg = NULL;
+
+    // Start visiting the node
+    if (!error_msg)
+    {
+        error_msg = handler->visitStartComplex(handler, infoNode);
+    }
+
+    // Walk the node's children recursively
+    const size_t      count = infoNode->erd->numChildren;
+    const ERD **const childrenERDs = infoNode->erd->childrenERDs;
+    const ptrdiff_t * offsets = infoNode->erd->offsets;
+
+    for (size_t i = 0; i < count && !error_msg; i++)
+    {
+        ptrdiff_t  offset = offsets[i];
+        const ERD *childERD = childrenERDs[i];
+        // We use only one of these variables below depending on typeCode
+        const InfosetBase *childNode =
+            (const InfosetBase *)((const char *)infoNode + offset);
+        const int32_t *intLocation =
+            (const int32_t *)((const char *)infoNode + offset);
+
+        // Need to handle more element types
+        enum TypeCode typeCode = childERD->typeCode;
+        switch (typeCode)
+        {
+        case COMPLEX:
+            error_msg = walkInfosetNode(handler, childNode);
+            break;
+        case PRIMITIVE_INT32:
+            error_msg = handler->visitInt32Elem(handler, childERD, intLocation);
+            break;
+        }
+    }
+
+    // End visiting the node
+    if (!error_msg)
+    {
+        error_msg = handler->visitEndComplex(handler, infoNode);
+    }
+
+    return error_msg;
+}
+
+// walkInfoset - walk an infoset and call VisitEventHandler methods
+
+const char *
+walkInfoset(const VisitEventHandler *handler, const InfosetBase *infoset)
+{
+    const char *error_msg = NULL;
+
+    if (!error_msg)
+    {
+        error_msg = handler->visitStartDocument(handler);
+    }
+    if (!error_msg)
+    {
+        error_msg = walkInfosetNode(handler, infoset);
+    }
+    if (!error_msg)
+    {
+        error_msg = handler->visitEndDocument(handler);
+    }
+
+    return error_msg;
+}
+
+// eof_or_error_msg - check if a stream has its eof or error indicator set
+
+const char *
+eof_or_error_msg(FILE *stream)
+{
+    if (feof(stream))
+    {
+        return "Found eof indicator after reading stream";
+    }
+    else if (ferror(stream))
+    {
+        return "Found error indicator after reading stream";
+    }
+    else
+    {
+        return NULL;
+    }
+}
diff --git a/daffodil-runtime2/src/main/resources/c/infoset.h b/daffodil-runtime2/src/main/resources/c/infoset.h
new file mode 100644
index 0000000..459557c
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/infoset.h
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef INFOSET_H
+#define INFOSET_H
+
+#include <stddef.h> // for ptrdiff_t
+#include <stdint.h> // for int32_t
+#include <stdio.h>  // for FILE, size_t
+
+// Prototypes needed for compilation
+
+struct ElementRuntimeData;
+struct InfosetBase;
+struct PState;
+struct UState;
+struct VisitEventHandler;
+
+typedef struct ElementRuntimeData ERD;
+typedef struct InfosetBase        InfosetBase;
+typedef struct PState             PState;
+typedef struct UState             UState;
+typedef struct VisitEventHandler  VisitEventHandler;
+
+typedef void (*ERDInitSelf)(InfosetBase *infoNode);
+typedef const char *(*ERDParseSelf)(InfosetBase * infoNode,
+                                    const PState *pstate);
+typedef const char *(*ERDUnparseSelf)(const InfosetBase *infoNode,
+                                      const UState *     ustate);
+
+typedef const char *(*VisitStartDocument)(const VisitEventHandler *handler);
+typedef const char *(*VisitEndDocument)(const VisitEventHandler *handler);
+typedef const char *(*VisitStartComplex)(const VisitEventHandler *handler,
+                                         const InfosetBase *      base);
+typedef const char *(*VisitEndComplex)(const VisitEventHandler *handler,
+                                       const InfosetBase *      base);
+typedef const char *(*VisitInt32Elem)(const VisitEventHandler *handler,
+                                      const ERD *erd, const int32_t *location);
+
+// NamedQName - name of an infoset element
+
+typedef struct NamedQName
+{
+    const char *prefix; // prefix (optional, may be NULL)
+    const char *local;  // local name
+    const char *ns;     // namespace URI (optional, may be NULL)
+} NamedQName;
+
+// TypeCode - type of an infoset element
+
+enum TypeCode
+{
+    COMPLEX,
+    PRIMITIVE_INT32
+};
+
+// ERD - element runtime data needed to parse/unparse objects
+
+typedef struct ElementRuntimeData
+{
+    const NamedQName    namedQName;
+    const enum TypeCode typeCode;
+    const size_t        numChildren;
+    const ptrdiff_t *   offsets;
+    const ERD **        childrenERDs;
+
+    const ERDInitSelf    initSelf;
+    const ERDParseSelf   parseSelf;
+    const ERDUnparseSelf unparseSelf;
+} ERD;
+
+// InfosetBase - representation of an infoset element
+
+typedef struct InfosetBase
+{
+    const ERD *erd;
+} InfosetBase;
+
+// PState - parser state while parsing input
+
+typedef struct PState
+{
+    FILE *stream; // input to read from
+} PState;
+
+// UState - unparser state while unparsing infoset
+
+typedef struct UState
+{
+    FILE *stream; // output to write to
+} UState;
+
+// VisitEventHandler - methods to be called when walking an infoset
+
+typedef struct VisitEventHandler
+{
+    const VisitStartDocument visitStartDocument;
+    const VisitEndDocument   visitEndDocument;
+    const VisitStartComplex  visitStartComplex;
+    const VisitEndComplex    visitEndComplex;
+    const VisitInt32Elem     visitInt32Elem;
+} VisitEventHandler;
+
+// get_erd_name, get_erd_xmlns, get_erd_ns - get name and xmlns
+// attribute/value from ERD to use for XML element
+
+extern const char *get_erd_name(const ERD *erd);
+extern const char *get_erd_xmlns(const ERD *erd);
+extern const char *get_erd_ns(const ERD *erd);
+
+// rootElement - return a root element to walk while parsing or unparsing
+
+// (actual definition will be in generated_code.c, not infoset.c)
+extern InfosetBase *rootElement();
+
+// walkInfoset - walk an infoset and call VisitEventHandler methods
+
+extern const char *walkInfoset(const VisitEventHandler *handler,
+                               const InfosetBase *      infoset);
+
+// eof_or_error_msg - check if a stream has its eof or error indicator set
+
+extern const char *eof_or_error_msg(FILE *stream);
+
+#endif // INFOSET_H
diff --git a/daffodil-runtime2/src/main/resources/c/stack.c b/daffodil-runtime2/src/main/resources/c/stack.c
new file mode 100644
index 0000000..c1814bb
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/stack.c
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stack.h"
+#include <error.h>   // for error
+#include <stdbool.h> // for bool
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>  // for EXIT_FAILURE
+
+// Initialize stack with preallocated array
+
+void
+stack_init(stack_t *p_stack, stack_item_t *p_array, ptrdiff_t capacity)
+{
+    p_stack->p_after = p_array;
+    p_stack->p_array = p_array;
+    p_stack->capacity = capacity;
+}
+
+// Check whether stack is empty
+
+bool
+stack_is_empty(stack_t *p_stack)
+{
+    return p_stack->p_after == p_stack->p_array;
+}
+
+// Check whether stack is full
+
+bool
+stack_is_full(stack_t *p_stack)
+{
+    ptrdiff_t count = p_stack->p_after - p_stack->p_array;
+    return count >= p_stack->capacity;
+}
+
+// Pop element from stack
+
+stack_item_t
+stack_pop(stack_t *p_stack)
+{
+    if (stack_is_empty(p_stack))
+    {
+        error(EXIT_FAILURE, 0, "Stack underflow - program terminated");
+    }
+    return *(--p_stack->p_after);
+}
+
+// Push element into stack
+
+void
+stack_push(stack_t *p_stack, stack_item_t item)
+{
+    if (stack_is_full(p_stack))
+    {
+        error(EXIT_FAILURE, 0, "Stack overflow - program terminated");
+    }
+    *(p_stack->p_after++) = item;
+}
+
+// Get stack's top element
+
+stack_item_t
+stack_top(stack_t *p_stack)
+{
+    if (stack_is_empty(p_stack))
+    {
+        error(EXIT_FAILURE, 0, "Stack empty - program terminated");
+    }
+    return *(p_stack->p_after - 1);
+}
diff --git a/daffodil-runtime2/src/main/resources/c/stack.h b/daffodil-runtime2/src/main/resources/c/stack.h
new file mode 100644
index 0000000..bf1cf3a
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/stack.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STACK_H
+#define STACK_H
+
+#include <mxml.h>    // for mxml_node_t
+#include <stdbool.h> // for bool
+#include <stddef.h>  // for ptrdiff_t
+
+// Type of element pushed into stack
+
+typedef mxml_node_t *stack_item_t;
+
+// Implement stack using preallocated array
+
+typedef struct
+{
+    stack_item_t *p_after;  // Pointer to one past top element
+    stack_item_t *p_array;  // Pointer to stack's array
+    ptrdiff_t     capacity; // Size of stack's array
+} stack_t;
+
+// Initialize stack with preallocated array
+
+extern void stack_init(stack_t *p_stack, stack_item_t *p_array,
+                       ptrdiff_t capacity);
+
+// Check whether stack is empty
+
+extern bool stack_is_empty(stack_t *p_stack);
+
+// Check whether stack is full
+
+extern bool stack_is_full(stack_t *p_stack);
+
+// Pop element from stack
+
+extern stack_item_t stack_pop(stack_t *p_stack);
+
+// Push element into stack
+
+extern void stack_push(stack_t *p_stack, stack_item_t item);
+
+// Get stack's top element
+
+extern stack_item_t stack_top(stack_t *p_stack);
+
+#endif // STACK_H
diff --git a/daffodil-runtime2/src/main/resources/c/xml_reader.c b/daffodil-runtime2/src/main/resources/c/xml_reader.c
new file mode 100644
index 0000000..34035d3
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/xml_reader.c
@@ -0,0 +1,210 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "xml_reader.h"
+#include <errno.h>    // for errno
+#include <inttypes.h> // for strtoimax
+#include <mxml.h>     // for mxmlWalkNext, mxmlGetType, mxmlGetElement, ...
+#include <stdint.h>   // for intmax_t, int32_t, INT32_MAX, INT32_MIN
+#include <string.h>   // for strcmp, strlen, strncmp
+
+// Convert an XML element's text to an integer (BSD function not
+// widely available, so roll our own function based on strtoimax)
+
+static intmax_t
+strtonum(const char *numptr, intmax_t minval, intmax_t maxval,
+         const char **errstrp)
+{
+    char *endptr = NULL;
+
+    // Clear errno to detect failure after calling strtoimax
+    errno = 0;
+    const intmax_t value = strtoimax(numptr, &endptr, 10);
+
+    // Report any issues converting the string to a number
+    if (errno != 0)
+    {
+        *errstrp = "Error converting XML data to integer";
+    }
+    else if (endptr == numptr)
+    {
+        *errstrp = "Found no number in XML data";
+    }
+    else if (*endptr != '\0')
+    {
+        *errstrp = "Found non-number characters in XML data";
+    }
+    else if (value < minval || value > maxval || maxval < minval)
+    {
+        *errstrp = "Number in XML data out of range";
+    }
+    else
+    {
+        *errstrp = NULL;
+    }
+
+    return value;
+}
+
+// Read XML data from file before walking infoset
+
+static const char *
+xmlStartDocument(XMLReader *reader)
+{
+    // Load the XML data into memory
+    reader->xml = mxmlLoadFile(NULL, reader->stream, MXML_OPAQUE_CALLBACK);
+    reader->node = reader->xml;
+    if (!reader->node)
+    {
+        return "Unable to read XML data from input file";
+    }
+
+    // Consume the <?xml line if there is one
+    const char *name = mxmlGetElement(reader->node);
+    if (name && strncmp(name, "?xml", strlen("?xml")) == 0)
+    {
+        do
+        {
+            reader->node =
+                mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+        } while (mxmlGetType(reader->node) == MXML_OPAQUE);
+        name = mxmlGetElement(reader->node);
+    }
+
+    // Consume a comment if there is one
+    if (name && strncmp(name, "!--", strlen("!--")) == 0)
+    {
+        do
+        {
+            reader->node =
+                mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+        } while (mxmlGetType(reader->node) == MXML_OPAQUE);
+    }
+
+    return reader->node ? NULL : "Ran out of XML data";
+}
+
+// Delete XML data after walking infoset
+
+static const char *
+xmlEndDocument(XMLReader *reader)
+{
+    // Consume any remaining newlines or whitespace
+    while (mxmlGetType(reader->node) == MXML_OPAQUE)
+    {
+        reader->node = mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+    }
+
+    // Check whether we have consumed all of the XML data
+    if (reader->node)
+    {
+        // This code path exits the program - no need to call mxmlDelete
+        return "Did not consume all of the XML data";
+    }
+
+    // Free the storage allocated to hold the XML data
+    mxmlDelete(reader->xml);
+    reader->xml = NULL;
+    reader->node = NULL;
+    return NULL;
+}
+
+// Continue walking both XML data and infoset in lockstep
+
+static const char *
+xmlStartComplex(XMLReader *reader, const InfosetBase *base)
+{
+    // Consume any newlines or whitespace before the element
+    while (mxmlGetType(reader->node) == MXML_OPAQUE)
+    {
+        reader->node = mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+    }
+
+    // Get the element and consume it
+    const char *name_from_xml = mxmlGetElement(reader->node);
+    const char *name_from_erd = get_erd_name(base->erd);
+    reader->node = mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+
+    // Check whether we are walking both XML data and infoset in lockstep
+    if (name_from_xml && name_from_erd)
+    {
+        return strcmp(name_from_xml, name_from_erd) == 0
+                   ? NULL
+                   : "Found mismatch between XML data and infoset";
+    }
+    else
+    {
+        return "Ran out of XML data";
+    }
+}
+
+// Consume XML data only on start events, not end events
+
+static const char *
+xmlEndComplex(XMLReader *reader, const InfosetBase *base)
+{
+    (void)reader;
+    (void)base;
+    return NULL;
+}
+
+// Read 32-bit integer value from XML data
+
+static const char *
+xmlInt32Elem(XMLReader *reader, const ERD *erd, int32_t *location)
+{
+    // Consume any newlines or whitespace before the element
+    while (mxmlGetType(reader->node) == MXML_OPAQUE)
+    {
+        reader->node = mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+    }
+
+    // Get the element and consume it
+    const char *name_from_xml = mxmlGetElement(reader->node);
+    const char *name_from_erd = get_erd_name(erd);
+    const char *number_from_xml = mxmlGetOpaque(reader->node);
+    reader->node = mxmlWalkNext(reader->node, reader->xml, MXML_DESCEND);
+
+    // Check whether we are walking both XML data and infoset in lockstep
+    if (name_from_xml && name_from_erd)
+    {
+        if (strcmp(name_from_xml, name_from_erd) == 0)
+        {
+            // Check for any errors getting the 32-bit integer
+            const char *errstr = NULL;
+            *location = (int32_t)strtonum(number_from_xml, INT32_MIN, INT32_MAX,
+                                          &errstr);
+            return errstr;
+        }
+        else
+        {
+            return "Found mismatch between XML data and infoset";
+        }
+    }
+    else
+    {
+        return "Ran out of XML data";
+    }
+}
+
+// Initialize a struct with our visitor event handler methods
+
+const VisitEventHandler xmlReaderMethods = {
+    (VisitStartDocument)&xmlStartDocument, (VisitEndDocument)&xmlEndDocument,
+    (VisitStartComplex)&xmlStartComplex,   (VisitEndComplex)&xmlEndComplex,
+    (VisitInt32Elem)&xmlInt32Elem,
+};
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/main/resources/c/xml_reader.h
similarity index 58%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/main/resources/c/xml_reader.h
index f0bc051..3333f55 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/main/resources/c/xml_reader.h
@@ -15,20 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+#ifndef XML_READER_H
+#define XML_READER_H
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+#include "infoset.h" // for VisitEventHandler, InfosetBase
+#include <mxml.h>    // for mxml_node_t
+#include <stdio.h>   // for FILE
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+// XMLReader - infoset visitor with methods to read XML
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
-  }
+typedef struct XMLReader
+{
+    const VisitEventHandler handler;
+    FILE *                  stream;
+    InfosetBase *           root;
+    mxml_node_t *           xml;
+    mxml_node_t *           node;
+} XMLReader;
 
-  private def documentElement = enclosedElement
+// XMLReader methods to pass to walkInfoset method
 
-}
+extern const VisitEventHandler xmlReaderMethods;
+
+#endif // XML_READER_H
diff --git a/daffodil-runtime2/src/main/resources/c/xml_writer.c b/daffodil-runtime2/src/main/resources/c/xml_writer.c
new file mode 100644
index 0000000..2db0ce4
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/c/xml_writer.c
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "xml_writer.h"
+#include "stack.h"  // for stack_is_empty, stack_pop, stack_push, stack_top
+#include <assert.h> // for assert
+#include <mxml.h>   // for mxml_node_t, mxmlNewElement, mxmlNewOpaquef, ...
+#include <stdint.h> // for int32_t
+#include <stdio.h>  // for NULL, fflush
+
+// Push new XML document on stack.  This function is not
+// thread-safe since it uses static storage.
+
+static const char *
+xmlStartDocument(XMLWriter *writer)
+{
+#define MAX_DEPTH 100
+    static mxml_node_t *array[MAX_DEPTH];
+    stack_init(&writer->stack, array, MAX_DEPTH);
+
+    mxml_node_t *xml = mxmlNewXML("1.0");
+    stack_push(&writer->stack, xml);
+    return xml ? NULL : "Error making new XML declaration";
+}
+
+// Pop completed XML document off stack and write it to stream
+
+static const char *
+xmlEndDocument(XMLWriter *writer)
+{
+    mxml_node_t *xml = stack_pop(&writer->stack);
+    assert(stack_is_empty(&writer->stack));
+    int status = mxmlSaveFile(xml, writer->stream, MXML_NO_CALLBACK);
+    if (status < 0)
+    {
+        return "Error writing XML document";
+    }
+    status = fflush(writer->stream);
+    mxmlDelete(xml);
+    return status == 0 ? NULL : "Error flushing stream";
+}
+
+// Push new complex element on stack
+
+static const char *
+xmlStartComplex(XMLWriter *writer, const InfosetBase *base)
+{
+    mxml_node_t *complex = NULL;
+    if (!stack_is_full(&writer->stack))
+    {
+        mxml_node_t *parent = stack_top(&writer->stack);
+        const char * name = get_erd_name(base->erd);
+        const char * xmlns = get_erd_xmlns(base->erd);
+        complex = mxmlNewElement(parent, name);
+        if (xmlns)
+        {
+            const char *ns = get_erd_ns(base->erd);
+            mxmlElementSetAttr(complex, xmlns, ns);
+        }
+        stack_push(&writer->stack, complex);
+    }
+    return complex ? NULL : "Error making new complex element";
+}
+
+// Pop completed complex element off stack
+
+static const char *
+xmlEndComplex(XMLWriter *writer, const InfosetBase *base)
+{
+    mxml_node_t *complex = NULL;
+    if (!stack_is_empty(&writer->stack))
+    {
+        complex = stack_pop(&writer->stack);
+        (void)base;
+    }
+    return complex ? NULL : "Underflowed the XML stack";
+}
+
+// Write 32-bit integer value as element
+
+static const char *
+xmlInt32Elem(XMLWriter *writer, const ERD *erd, const int32_t *location)
+{
+    mxml_node_t *parent = stack_top(&writer->stack);
+    const char * name = get_erd_name(erd);
+    const char * xmlns = get_erd_xmlns(erd);
+    mxml_node_t *simple = mxmlNewElement(parent, name);
+    int32_t      value = *location;
+    mxml_node_t *text = mxmlNewOpaquef(simple, "%i", value);
+    if (xmlns)
+    {
+        const char *ns = get_erd_ns(erd);
+        mxmlElementSetAttr(simple, xmlns, ns);
+    }
+    return (simple && text) ? NULL : "Error making new int32 simple element";
+}
+
+// Initialize a struct with our visitor event handler methods
+
+const VisitEventHandler xmlWriterMethods = {
+    (VisitStartDocument)&xmlStartDocument, (VisitEndDocument)&xmlEndDocument,
+    (VisitStartComplex)&xmlStartComplex,   (VisitEndComplex)&xmlEndComplex,
+    (VisitInt32Elem)&xmlInt32Elem,
+};
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/main/resources/c/xml_writer.h
similarity index 62%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/main/resources/c/xml_writer.h
index f0bc051..45d7a45 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/main/resources/c/xml_writer.h
@@ -15,20 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+#ifndef XML_WRITER_H
+#define XML_WRITER_H
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+#include "infoset.h" // for VisitEventHandler
+#include "stack.h"   // for stack_t
+#include <stdio.h>   // for FILE
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+// XMLWriter - infoset visitor with methods to output XML
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
-  }
+typedef struct XMLWriter
+{
+    const VisitEventHandler handler;
+    FILE *                  stream;
+    stack_t                 stack;
+} XMLWriter;
 
-  private def documentElement = enclosedElement
+// XMLWriter methods to pass to walkInfoset method
 
-}
+extern const VisitEventHandler xmlWriterMethods;
+
+#endif // XML_WRITER_H
diff --git a/daffodil-runtime2/src/main/resources/examples/ex_int32.c b/daffodil-runtime2/src/main/resources/examples/ex_int32.c
new file mode 100644
index 0000000..d2b9217
--- /dev/null
+++ b/daffodil-runtime2/src/main/resources/examples/ex_int32.c
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ex_int32.h" // for generated code structs
+#include <endian.h>   // for be32toh, htobe32
+#include <stddef.h>   // for ptrdiff_t
+#include <stdio.h>    // for NULL, fread, fwrite, size_t, FILE
+
+// Prototypes needed for compilation
+
+static void        c2_initSelf(c2 *instance);
+static const char *c2_parseSelf(c2 *instance, const PState *pstate);
+static const char *c2_unparseSelf(const c2 *instance, const UState *ustate);
+static void        c1_initSelf(c1 *instance);
+static const char *c1_parseSelf(c1 *instance, const PState *pstate);
+static const char *c1_unparseSelf(const c1 *instance, const UState *ustate);
+
+// Metadata singletons
+
+static const ERD e1_ERD = {
+    {
+        "ex", // namedQName.prefix
+        "e1", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD e2_ERD = {
+    {
+        "ex", // namedQName.prefix
+        "e2", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const ERD e3_ERD = {
+    {
+        "ex", // namedQName.prefix
+        "e3", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    PRIMITIVE_INT32, // typeCode
+    0,               // numChildren
+    NULL,            // offsets
+    NULL,            // childrenERDs
+    NULL,            // initSelf
+    NULL,            // parseSelf
+    NULL,            // unparseSelf
+};
+
+static const c2 c2_compute_ERD_offsets;
+
+static const ptrdiff_t c2_offsets[2] = {
+    (char *)&c2_compute_ERD_offsets.e2 - (char *)&c2_compute_ERD_offsets,
+    (char *)&c2_compute_ERD_offsets.e3 - (char *)&c2_compute_ERD_offsets};
+
+static const ERD *c2_childrenERDs[2] = {&e2_ERD, &e3_ERD};
+
+static const ERD c2_ERD = {
+    {
+        "ex", // namedQName.prefix
+        "c2", // namedQName.local
+        NULL, // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    2,                               // numChildren
+    c2_offsets,                      // offsets
+    c2_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&c2_initSelf,       // initSelf
+    (ERDParseSelf)&c2_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&c2_unparseSelf, // unparseSelf
+};
+
+static const c1 c1_compute_ERD_offsets;
+
+static const ptrdiff_t c1_offsets[2] = {
+    (char *)&c1_compute_ERD_offsets.e1 - (char *)&c1_compute_ERD_offsets,
+    (char *)&c1_compute_ERD_offsets.c2 - (char *)&c1_compute_ERD_offsets};
+
+static const ERD *c1_childrenERDs[2] = {&e1_ERD, &c2_ERD};
+
+static const ERD c1_ERD = {
+    {
+        "ex",                 // namedQName.prefix
+        "c1",                 // namedQName.local
+        "http://example.com", // namedQName.ns
+    },
+    COMPLEX,                         // typeCode
+    2,                               // numChildren
+    c1_offsets,                      // offsets
+    c1_childrenERDs,                 // childrenERDs
+    (ERDInitSelf)&c1_initSelf,       // initSelf
+    (ERDParseSelf)&c1_parseSelf,     // parseSelf
+    (ERDUnparseSelf)&c1_unparseSelf, // unparseSelf
+};
+
+// Return a root element to be used for parsing or unparsing
+
+InfosetBase *
+rootElement()
+{
+    static c1    instance;
+    InfosetBase *root = &instance._base;
+    c1_ERD.initSelf(root);
+    return root;
+}
+
+// Methods to initialize, parse, and unparse infoset nodes
+
+static void
+c2_initSelf(c2 *instance)
+{
+    instance->e2 = 0xCDCDCDCD;
+    instance->e3 = 0xCDCDCDCD;
+    instance->_base.erd = &c2_ERD;
+}
+
+static const char *
+c2_parseSelf(c2 *instance, const PState *pstate)
+{
+    const char *error_msg = NULL;
+    if (!error_msg)
+    {
+        char   buffer[4];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->e2 = be32toh(*((uint32_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        char   buffer[4];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->e3 = be32toh(*((uint32_t *)(&buffer)));
+    }
+    return error_msg;
+}
+
+static const char *
+c2_unparseSelf(const c2 *instance, const UState *ustate)
+{
+    const char *error_msg = NULL;
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[4];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htobe32(instance->e2);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[4];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htobe32(instance->e3);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    return error_msg;
+}
+
+static void
+c1_initSelf(c1 *instance)
+{
+    instance->e1 = 0xCDCDCDCD;
+    c2_initSelf(&instance->c2);
+    instance->_base.erd = &c1_ERD;
+}
+
+static const char *
+c1_parseSelf(c1 *instance, const PState *pstate)
+{
+    const char *error_msg = NULL;
+    if (!error_msg)
+    {
+        char   buffer[4];
+        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(pstate->stream);
+        }
+        instance->e1 = be32toh(*((uint32_t *)(&buffer)));
+    }
+    if (!error_msg)
+    {
+        error_msg = c2_parseSelf(&instance->c2, pstate);
+    }
+    return error_msg;
+}
+
+static const char *
+c1_unparseSelf(const c1 *instance, const UState *ustate)
+{
+    const char *error_msg = NULL;
+    if (!error_msg)
+    {
+        union
+        {
+            char     c_val[4];
+            uint32_t i_val;
+        } buffer;
+        buffer.i_val = htobe32(instance->e1);
+        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+        if (count < sizeof(buffer))
+        {
+            error_msg = eof_or_error_msg(ustate->stream);
+        }
+    }
+    if (!error_msg)
+    {
+        error_msg = c2_unparseSelf(&instance->c2, ustate);
+    }
+    return error_msg;
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/main/resources/examples/ex_int32.h
similarity index 62%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/main/resources/examples/ex_int32.h
index f0bc051..affd8b4 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/main/resources/examples/ex_int32.h
@@ -15,20 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+#ifndef GENERATED_CODE_H
+#define GENERATED_CODE_H
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+#include "infoset.h" // for InfosetBase
+#include <stdint.h>  // for int32_t
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+// Define some infoset structures
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
-  }
+typedef struct c2
+{
+    InfosetBase _base;
+    int32_t     e2;
+    int32_t     e3;
+} c2;
 
-  private def documentElement = enclosedElement
+typedef struct c1
+{
+    InfosetBase _base;
+    int32_t     e1;
+    c2          c2;
+} c1;
 
-}
+#endif // GENERATED_CODE_H
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
new file mode 100644
index 0000000..6dcc19d
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/CodeGenerator.scala
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import java.io.File
+import java.nio.file.FileSystems
+import java.nio.file.Files
+import java.nio.file.Paths
+import java.util.Collections
+
+import org.apache.daffodil.api.DFDL
+import org.apache.daffodil.api.Diagnostic
+import org.apache.daffodil.dsom.Root
+import org.apache.daffodil.dsom.SchemaDefinitionError
+import org.apache.daffodil.runtime2.generators.CodeGeneratorState
+import org.apache.daffodil.util.Misc
+import org.apache.daffodil.xml.RefQName
+
+/**
+ * Generates and compiles C source files from a DFDL schema encapsulated in a [[Root]].
+ * Implements the [[DFDL.CodeGenerator]] trait to allow it to be called by Daffodil code.
+ * @param root Provides the DFDL schema for code generation
+ */
+class CodeGenerator(root: Root) extends DFDL.CodeGenerator {
+  // Used by compileCode and pickCompiler methods
+  private lazy val isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows")
+  // Used by WithDiagnostics methods
+  private var diagnostics: Seq[Diagnostic] = Nil
+  private var errorStatus: Boolean = false
+
+  // Writes C source files into a "c" subdirectory of the given output directory.
+  // Removes the "c" subdirectory if it existed before.
+  override def generateCode(rootNS: Option[RefQName], outputDirArg: String): os.Path = {
+    // Get the paths of the output directory and its code subdirectory
+    val outputDir = os.Path(Paths.get(outputDirArg).toAbsolutePath)
+    val codeDir = outputDir/"c"
+
+    // Ensure our output directory exists while our code subdirectory does not
+    os.makeDir.all(outputDir)
+    os.remove.all(codeDir)
+
+    // Copy our resource directory and all its C source files to our code subdirectory
+    val resourceUri = Misc.getRequiredResource("/c")
+    val fileSystem = if (resourceUri.getScheme == "jar") {
+      val env: java.util.Map[String, String] = Collections.emptyMap()
+      FileSystems.newFileSystem(resourceUri, env)
+    } else {
+      null
+    }
+    try {
+      val resourceDir = os.Path(if (fileSystem != null) fileSystem.getPath("/c") else Paths.get(resourceUri))
+      os.copy(resourceDir, codeDir)
+    }
+    finally
+      if (fileSystem != null) fileSystem.close()
+
+    // Generate C code from the DFDL schema
+    val rootElementName = rootNS.getOrElse(root.refQName).local
+    val codeGeneratorState = new CodeGeneratorState()
+    Runtime2CodeGenerator.generateCode(root.document, codeGeneratorState)
+    val codeHeaderText = codeGeneratorState.generateCodeHeader
+    val codeFileText = codeGeneratorState.generateCodeFile(rootElementName)
+
+    // Write the generated C code into our code subdirectory
+    val generatedCodeHeader = codeDir/"generated_code.h"
+    val generatedCodeFile = codeDir/"generated_code.c"
+    os.write(generatedCodeHeader, codeHeaderText)
+    os.write(generatedCodeFile, codeFileText)
+
+    // Return our output directory in case caller wants to call compileCode next
+    outputDir
+  }
+
+  // Compiles any C source files inside a "c" subdirectory of the given output directory.
+  // Returns the path of the newly created executable to use in TDML tests or something else.
+  override def compileCode(outputDir: os.Path): os.Path = {
+    // Get the paths of the code subdirectory and the executable we will build
+    val codeDir = outputDir/"c"
+    val exe = if (isWindows) codeDir/"daffodil.exe" else codeDir/"daffodil"
+
+    try {
+      // Assemble the compiler's command line arguments
+      val compiler = pickCompiler
+      val files = os.list(codeDir).filter(_.ext == "c")
+      val libs = Seq("-lmxml", if (isWindows) "-largp" else "-lpthread")
+
+      // Call the compiler if it was found.  We run the compiler in the output directory,
+      // not in the "c" subdirectory, in order to let the compiler (which might be "zig cc")
+      // cache/reuse previously built files (which might be in a "zig_cache" subdirectory).
+      // We can't let "zig_cache" be put into "c" because we always remove and re-generate
+      // everything in "c" from scratch.
+      if (compiler.nonEmpty) {
+        val result = os.proc(compiler, "-I", codeDir, files, libs, "-o", exe).call(cwd = outputDir, stderr = os.Pipe)
+
+        // Report any compiler output as a warning
+        if (result.out.text.nonEmpty || result.err.text.nonEmpty) {
+          warning("Unexpected compiler output on stdout: %s on stderr: %s", result.out.text, result.err.text)
+        }
+      }
+    } catch {
+      // Report any subprocess termination error as an error
+      case e: os.SubprocessException =>
+        error("Error compiling generated code: %s wd: %s", Misc.getSomeMessage(e).get, outputDir.toString)
+    }
+
+    // Report any failure to build the executable as an error
+    if (!os.exists(exe)) error("No executable was built: %s", exe.toString)
+    exe
+  }
+
+  /**
+   * Searches for any available C compiler on the system.  Tries to find the
+   * compiler given by `CC` if `CC` exists in the environment, then tries to
+   * find any compiler from the following list:
+   *
+   *   - zig cc
+   *   - gcc
+   *   - clang
+   *   - cc
+   *
+   * Returns the first compiler found as a sequence of strings in case the
+   * compiler is a program with a subcommand argument.  Returns the empty
+   * sequence if no compiler could be found in the user's PATH.
+   */
+  lazy val pickCompiler: Seq[String] = {
+    val ccEnv = System.getenv("CC")
+    val compilers = Seq(ccEnv, "zig cc", "gcc", "clang", "cc")
+    val path = System.getenv("PATH").split(File.pathSeparatorChar)
+    def inPath(compiler: String): Boolean = {
+      (compiler != null) && {
+        val exec = compiler.takeWhile(_ != ' ')
+        val exec2 = exec + ".exe"
+        path.exists(dir => Files.isExecutable(Paths.get(dir, exec))
+          || (isWindows && Files.isExecutable(Paths.get(dir, exec2))))
+      }
+    }
+    val compiler = compilers.find(inPath)
+    if (compiler.isDefined)
+      compiler.get.split(' ').toSeq
+    else
+      Seq.empty[String]
+  }
+
+  /**
+   * Adds a warning message to the diagnostics
+   */
+  def warning(formatString: String, args: Any*): Unit = {
+    val sde = new SchemaDefinitionError(None, None, formatString, args: _*)
+    diagnostics :+= sde
+  }
+
+  /**
+   * Adds an error message to the diagnostics and sets isError true
+   */
+  def error(formatString: String, args: Any*): Unit = {
+    val sde = new SchemaDefinitionError(None, None, formatString, args: _*)
+    diagnostics :+= sde
+    errorStatus = true
+  }
+
+  // Implements the WithDiagnostics methods
+  override def getDiagnostics: Seq[Diagnostic] = diagnostics
+  override def isError: Boolean = errorStatus
+}
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
new file mode 100644
index 0000000..fbf704f
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2CodeGenerator.scala
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import org.apache.daffodil.grammar.Gram
+import org.apache.daffodil.grammar.Prod
+import org.apache.daffodil.grammar.RootGrammarMixin
+import org.apache.daffodil.grammar.SeqComp
+import org.apache.daffodil.grammar.primitives.BinaryIntegerKnownLength
+import org.apache.daffodil.grammar.primitives.CaptureContentLengthEnd
+import org.apache.daffodil.grammar.primitives.CaptureContentLengthStart
+import org.apache.daffodil.grammar.primitives.CaptureValueLengthEnd
+import org.apache.daffodil.grammar.primitives.CaptureValueLengthStart
+import org.apache.daffodil.grammar.primitives.ElementCombinator
+import org.apache.daffodil.grammar.primitives.ElementParseAndUnspecifiedLength
+import org.apache.daffodil.grammar.primitives.OrderedSequence
+import org.apache.daffodil.grammar.primitives.ScalarOrderedSequenceChild
+import org.apache.daffodil.grammar.primitives.SpecifiedLengthImplicit
+import org.apache.daffodil.runtime2.generators.BinaryIntegerKnownLengthCodeGenerator
+import org.apache.daffodil.runtime2.generators.CodeGeneratorState
+import org.apache.daffodil.runtime2.generators.ElementParseAndUnspecifiedLengthCodeGenerator
+import org.apache.daffodil.runtime2.generators.OrderedSequenceCodeGenerator
+import org.apache.daffodil.runtime2.generators.SeqCompCodeGenerator
+import org.apache.daffodil.util.Misc
+
+import scala.annotation.tailrec
+
+object Runtime2CodeGenerator
+  extends BinaryIntegerKnownLengthCodeGenerator
+    with ElementParseAndUnspecifiedLengthCodeGenerator
+    with OrderedSequenceCodeGenerator
+    with SeqCompCodeGenerator {
+
+  @tailrec
+  def generateCode(gram: Gram, state: CodeGeneratorState): Unit =
+    gram match {
+      case g: RootGrammarMixin => Runtime2CodeGenerator.generateCode(g.documentElement, state)
+      case g: Prod if (g.guard) => Runtime2CodeGenerator.generateCode(g.gram, state)
+      case g: ElementCombinator => Runtime2CodeGenerator.generateCode(g.subComb, state)
+      case g: SpecifiedLengthImplicit => Runtime2CodeGenerator.generateCode(g.eGram, state)
+      case g: ScalarOrderedSequenceChild => Runtime2CodeGenerator.generateCode(g.term.termContentBody, state)
+      case g: SeqComp => seqCompGenerateCode(g, state)
+      case g: OrderedSequence => orderedSequenceGenerateCode(g, state)
+      case g: ElementParseAndUnspecifiedLength => elementParseAndUnspecifiedLengthGenerateCode(g, state)
+      case g: BinaryIntegerKnownLength => binaryIntegerKnownLengthGenerateCode(g, state)
+      case _: CaptureContentLengthStart => // not generating code here
+      case _: CaptureContentLengthEnd => // not generating code here
+      case _: CaptureValueLengthStart => //not generating code here
+      case _: CaptureValueLengthEnd => // not generating code here
+      case _ => gram.SDE("Code generation not supported for: %s", Misc.getNameFromClass(gram))
+    }
+}
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala
new file mode 100644
index 0000000..7dd8f68
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/Runtime2DataProcessor.scala
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import java.io.File
+import java.io.InputStream
+import java.io.OutputStream
+
+import org.apache.daffodil.api.DFDL
+import org.apache.daffodil.api.DaffodilTunables
+import org.apache.daffodil.api.DataLocation
+import org.apache.daffodil.api.ValidationMode
+import org.apache.daffodil.externalvars.Binding
+import org.apache.daffodil.processors.Failure
+import org.apache.daffodil.processors.ProcessorResult
+import org.apache.daffodil.processors.Success
+import org.apache.daffodil.processors.VariableMap
+import org.apache.daffodil.processors.WithDiagnosticsImpl
+import org.apache.daffodil.processors.parsers.ParseError
+import org.apache.daffodil.processors.unparsers.UnparseError
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.util.Maybe.Nope
+
+/**
+ * Effectively a scala proxy object that does its work via the underlying C-code.
+ * Will need to consider how to use features of underlying C-code to get infoset,
+ * walk infoset, generate XML for use by TDML tests.
+ */
+class Runtime2DataProcessor(executableFile: os.Path) extends DFDL.DataProcessorBase {
+
+  override def withValidationMode(mode: ValidationMode.Type): DFDL.DataProcessor = ???
+
+  override def withTunable(name: String, value: String): DFDL.DataProcessor = ???
+
+  override def withTunables(tunables: Map[String, String]): DFDL.DataProcessor = ???
+
+  override def withExternalVariables(extVars: Map[String, String]): DFDL.DataProcessor = ???
+
+  override def withExternalVariables(extVars: File): DFDL.DataProcessor = ???
+
+  override def withExternalVariables(extVars: Seq[Binding]): DFDL.DataProcessor = ???
+
+  override def validationMode: ValidationMode.Type = ???
+
+  override def getTunables(): DaffodilTunables = ???
+
+  override def save(output: DFDL.Output): Unit = ???
+
+  override def variableMap: VariableMap = ???
+
+  override def setValidationMode(mode: ValidationMode.Type): Unit = ???
+
+  override def setExternalVariables(extVars: Map[String, String]): Unit = ???
+
+  override def setExternalVariables(extVars: File): Unit = ???
+
+  override def setExternalVariables(extVars: File, tunable: DaffodilTunables): Unit = ???
+
+  override def setExternalVariables(extVars: Seq[Binding]): Unit = ???
+
+  override def setTunable(tunable: String, value: String): Unit = ???
+
+  override def setTunables(tunables: Map[String, String]): Unit = ???
+
+  /**
+   * Returns an object which contains the result, and/or diagnostic information.
+   */
+  def parse(input: InputStream): ParseResult = {
+    val tempDir = os.temp.dir()
+    val infile = tempDir/"infile"
+    val outfile = tempDir/"outfile"
+    try {
+      os.write(infile, input)
+      val result = os.proc(executableFile, "parse", "-I", "xml", "-o", outfile, infile).call(cwd = tempDir, stderr = os.Pipe)
+      if (result.out.text.isEmpty && result.err.text.isEmpty) {
+        val parseResult = new ParseResult(outfile, Success)
+        parseResult
+      } else {
+        val msg = s"Unexpected daffodil output on stdout: ${result.out.text} on stderr: ${result.err.text}"
+        val parseError = new ParseError(Nope, Nope, Nope, Maybe(msg))
+        val parseResult = new ParseResult(outfile, Failure(parseError))
+        parseResult.addDiagnostic(parseError)
+        parseResult
+      }
+    } catch {
+      case e: os.SubprocessException =>
+        val parseError = if (e.result.out.text.isEmpty && e.result.err.text.isEmpty) {
+          new ParseError(Nope, Nope, Maybe(e), Nope)
+        } else {
+          val msg = s"${e.getMessage} with stdout: ${e.result.out.text} and stderr: ${e.result.err.text}"
+          new ParseError(Nope, Nope, Nope, Maybe(msg))
+        }
+        val parseResult = new ParseResult(outfile, Failure(parseError))
+        parseResult.addDiagnostic(parseError)
+        parseResult
+    }
+  }
+
+  /**
+   * Unparses (that is, serializes) data to the output, returns an object which contains any diagnostics.
+   */
+  def unparse(input: InputStream, output: OutputStream): UnparseResult = {
+    val tempDir = os.temp.dir()
+    val infile = tempDir/"infile"
+    val outfile = tempDir/"outfile"
+    try {
+      os.write(infile, input)
+      val result = os.proc(executableFile, "unparse", "-I", "xml", "-o", outfile, infile).call(cwd = tempDir, stderr = os.Pipe)
+      val finalBitPos0b = os.size(outfile) * 8 // File sizes are bytes, so must multiply to get final position in bits
+      os.read.stream(outfile).writeBytesTo(output)
+      if (result.out.text.isEmpty && result.err.text.isEmpty) {
+        val unparseResult = new UnparseResult(finalBitPos0b, Success)
+        unparseResult
+      } else {
+        val msg = s"Unexpected daffodil output on stdout: ${result.out.text} on stderr: ${result.err.text}"
+        val unparseError = new UnparseError(Nope, Nope, Nope, Maybe(msg))
+        val unparseResult = new UnparseResult(finalBitPos0b, Failure(unparseError))
+        unparseResult.addDiagnostic(unparseError)
+        unparseResult
+      }
+    } catch {
+      case e: os.SubprocessException =>
+        val unparseError = if (e.result.out.text.isEmpty && e.result.err.text.isEmpty) {
+          new UnparseError(Nope, Nope, Maybe(e), Nope)
+        } else {
+          val msg = s"${e.getMessage} with stdout: ${e.result.out.text} and stderr: ${e.result.err.text}"
+          new UnparseError(Nope, Nope, Nope, Maybe(msg))
+        }
+        val finalBitPos0b = 0L
+        val unparseResult = new UnparseResult(finalBitPos0b, Failure(unparseError))
+        unparseResult.addDiagnostic(unparseError)
+        unparseResult
+    }
+  }
+}
+
+object Runtime2DataLocation {
+  class Runtime2DataLocation(_isAtEnd: Boolean,
+                             _bitPos1b: Long,
+                             _bytePos1b: Long) extends DataLocation {
+    override def isAtEnd: Boolean = _isAtEnd
+    override def bitPos1b: Long = _bitPos1b
+    override def bytePos1b: Long = _bytePos1b
+  }
+
+  def apply(isAtEnd: Boolean = true,
+            bitPos1b: Long = 0L,
+            bytePos1b: Long = 0L): DataLocation = {
+    new Runtime2DataLocation(isAtEnd, bitPos1b, bytePos1b)
+  }
+}
+
+final class ParseResult(outfile: os.Path,
+                        override val processorStatus: ProcessorResult,
+                        loc: DataLocation = Runtime2DataLocation())
+  extends DFDL.ParseResult
+    with DFDL.State
+    with WithDiagnosticsImpl {
+
+  override def resultState: DFDL.State = this
+
+  override def validationStatus: Boolean = processorStatus.isSuccess
+
+  override def currentLocation: DataLocation = loc
+
+  def infosetAsXML : scala.xml.Elem = {
+    val xml = scala.xml.XML.loadFile(outfile.toIO)
+    xml
+  }
+}
+
+final class UnparseResult(val finalBitPos0b: Long,
+                          override val processorStatus: ProcessorResult,
+                          loc: DataLocation = Runtime2DataLocation())
+  extends DFDL.UnparseResult
+    with DFDL.State
+    with WithDiagnosticsImpl {
+  /**
+   * Data is 'scannable' if it consists entirely of textual data, and that data
+   * is all in the same encoding.
+   */
+  override def isScannable: Boolean = false // Safest answer since we don't know for sure
+
+  override def encodingName: String = ??? // We don't need encoding unless isScannable is true
+
+  override def validationStatus: Boolean = processorStatus.isSuccess
+
+  override def currentLocation: DataLocation = loc
+
+  override def resultState: DFDL.State = this
+}
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
new file mode 100644
index 0000000..e1c399d
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/BinaryIntegerKnownLengthCodeGenerator.scala
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2.generators
+
+import org.apache.daffodil.grammar.primitives.BinaryIntegerKnownLength
+import org.apache.daffodil.schema.annotation.props.gen.{ BitOrder, ByteOrder }
+
+trait BinaryIntegerKnownLengthCodeGenerator {
+
+  def binaryIntegerKnownLengthGenerateCode(g: BinaryIntegerKnownLength, cgState: CodeGeneratorState): Unit = {
+    val e = g.e
+    val fieldName = e.namedQName.local
+    val lengthInBits: Long = {
+      e.schemaDefinitionUnless(e.elementLengthInBitsEv.isConstant, "Runtime dfdl:length expressions not supported.")
+      val len = e.elementLengthInBitsEv.constValue.get
+      len
+    }
+
+    val byteOrder: ByteOrder = {
+      e.schemaDefinitionUnless(e.byteOrderEv.isConstant, "Runtime dfdl:byteOrder expressions not supported.")
+      val bo = e.byteOrderEv.constValue
+      bo
+    }
+    // For the time being this is a very limited back end.
+    // So there are numerous restrictions to enforce.
+    e.schemaDefinitionUnless(lengthInBits <= 64, "Length must be 64 bits or less, but was: %s", lengthInBits)
+    if (lengthInBits == 64 && !g.signed)
+      e.SDE("Integers of 64 bits length must be signed.")
+
+    // This insures we can use regular java.io library calls.
+    if (e.alignmentValueInBits.intValue() % 8 != 0)
+      e.SDE("Only alignment to 8-bit (1 byte) boundaries is supported.")
+
+    // The restrictions below are ones we want to eventually lift.
+    if (lengthInBits != 32)
+      e.SDE("Lengths other than 32 bits are not supported.")
+
+    if (byteOrder ne ByteOrder.BigEndian)
+      e.SDE("Only dfdl:byteOrder 'bigEndian' is supported.")
+
+    if (e.bitOrder ne BitOrder.MostSignificantBitFirst)
+      e.SDE("Only dfdl:bitOrder 'mostSignificantBitFirst' is supported.")
+
+    if (!g.signed)
+      e.SDE("Only signed integers are supported.")
+
+    val initStatement = s"    instance->$fieldName = 0xCDCDCDCD;"
+    val parseStatement =
+      s"""    if (!error_msg)
+         |    {
+         |        char   buffer[4];
+         |        size_t count = fread(&buffer, 1, sizeof(buffer), pstate->stream);
+         |        if (count < sizeof(buffer))
+         |        {
+         |            error_msg = eof_or_error_msg(pstate->stream);
+         |        }
+         |        instance->$fieldName = be32toh(*((uint32_t *)(&buffer)));
+         |    }""".stripMargin
+    val unparseStatement =
+      s"""    if (!error_msg)
+         |    {
+         |        union
+         |        {
+         |            char     c_val[4];
+         |            uint32_t i_val;
+         |        } buffer;
+         |        buffer.i_val = htobe32(instance->$fieldName);
+         |        size_t count = fwrite(buffer.c_val, 1, sizeof(buffer), ustate->stream);
+         |        if (count < sizeof(buffer))
+         |        {
+         |            error_msg = eof_or_error_msg(ustate->stream);
+         |        }
+         |    }""".stripMargin
+    cgState.addSimpleTypeStatements(initStatement, parseStatement, unparseStatement)
+  }
+}
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
new file mode 100644
index 0000000..bf97636
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/CodeGeneratorState.scala
@@ -0,0 +1,280 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2.generators
+
+import org.apache.daffodil.dpath.NodeInfo
+import org.apache.daffodil.dpath.NodeInfo.PrimType
+import org.apache.daffodil.dsom.ElementBase
+import org.apache.daffodil.exceptions.ThrowsSDE
+
+import scala.collection.mutable
+
+/**
+ * Builds up the state of generated code.
+ */
+class CodeGeneratorState {
+  private val structs = mutable.Stack[ComplexCGState]()
+  private val prototypes = mutable.ArrayBuffer[String]()
+  private val erds = mutable.ArrayBuffer[String]()
+  private val finalStructs = mutable.ArrayBuffer[String]()
+  private val finalImplementation = mutable.ArrayBuffer[String]()
+
+  def addImplementation(context: ElementBase): Unit = {
+    val C = context.namedQName.local
+    val initStatements = structs.top.initStatements.mkString("\n")
+    val parserStatements = structs.top.parserStatements.mkString("\n")
+    val unparserStatements = structs.top.unparserStatements.mkString("\n")
+    val prototypeFunctions =
+      s"""static void        ${C}_initSelf($C *instance);
+         |static const char *${C}_parseSelf($C *instance, const PState *pstate);
+         |static const char *${C}_unparseSelf(const $C *instance, const UState *ustate);""".stripMargin
+    prototypes += prototypeFunctions
+    val functions =
+      s"""static void
+         |${C}_initSelf($C *instance)
+         |{
+         |$initStatements
+         |}
+         |
+         |static const char *
+         |${C}_parseSelf($C *instance, const PState *pstate)
+         |{
+         |    const char *error_msg = NULL;
+         |$parserStatements
+         |    return error_msg;
+         |}
+         |
+         |static const char *
+         |${C}_unparseSelf(const $C *instance, const UState *ustate)
+         |{
+         |    const char *error_msg = NULL;
+         |$unparserStatements
+         |    return error_msg;
+         |}
+         |""".stripMargin
+    finalImplementation += functions
+  }
+
+  private def defineQNameInit(context: ElementBase): String = {
+    val prefix = context.namedQName.prefix.map(p => s""""$p"""").getOrElse("NULL")
+    val local = context.namedQName.local
+    val nsUri = context.namedQName.namespace.toStringOrNullIfNoNS
+    // Optimize away ns declaration if possible, although this approach may not be entirely correct
+    val parentNsUri = context.enclosingElements.headOption.map(_.namedQName.namespace.toStringOrNullIfNoNS).getOrElse("no-ns")
+    val ns = if (nsUri == null || nsUri == parentNsUri) "NULL" else s""""$nsUri""""
+    val qnameInit =
+      s"""    {
+         |        $prefix, // namedQName.prefix
+         |        "$local", // namedQName.local
+         |        $ns, // namedQName.ns
+         |    },""".stripMargin
+    qnameInit
+  }
+
+  def addComplexTypeERD(context: ElementBase): Unit = {
+    val C = context.namedQName.local
+    val count = structs.top.declarations.length
+    val offsetComputations = structs.top.offsetComputations.mkString(",\n")
+    val erdComputations = structs.top.erdComputations.mkString(",\n")
+    val qnameInit = defineQNameInit(context)
+    val complexERD =
+      s"""static const $C ${C}_compute_ERD_offsets;
+         |
+         |static const ptrdiff_t ${C}_offsets[$count] = {
+         |$offsetComputations
+         |};
+         |
+         |static const ERD *${C}_childrenERDs[$count] = {
+         |$erdComputations
+         |};
+         |
+         |static const ERD ${C}_ERD = {
+         |$qnameInit
+         |    COMPLEX,                         // typeCode
+         |    $count,                               // numChildren
+         |    ${C}_offsets,                      // offsets
+         |    ${C}_childrenERDs,                 // childrenERDs
+         |    (ERDInitSelf)&${C}_initSelf,       // initSelf
+         |    (ERDParseSelf)&${C}_parseSelf,     // parseSelf
+         |    (ERDUnparseSelf)&${C}_unparseSelf, // unparseSelf
+         |};
+         |""".stripMargin
+    erds += complexERD
+  }
+
+  def addStruct(context: ElementBase): Unit = {
+    val C = context.namedQName.local
+    val declarations = structs.top.declarations.mkString("\n")
+    val struct =
+      s"""typedef struct $C
+         |{
+         |    InfosetBase _base;
+         |$declarations
+         |} $C;
+         |""".stripMargin
+    finalStructs += struct
+    val initStatement = s"    instance->_base.erd = &${C}_ERD;"
+    structs.top.initStatements += initStatement
+  }
+
+  def addSimpleTypeStatements(initStatement: String, parseStatement: String, unparseStatement: String): Unit = {
+    structs.top.initStatements += initStatement
+    structs.top.parserStatements += parseStatement
+    structs.top.unparserStatements += unparseStatement
+  }
+
+  def addComplexTypeStatements(child: ElementBase): Unit = {
+    val C = child.namedQName.local
+    val e = child.name
+    val initStatement = s"    ${C}_initSelf(&instance->$e);"
+    val parseStatement =
+      s"""    if (!error_msg)
+         |    {
+         |        error_msg = ${C}_parseSelf(&instance->$e, pstate);
+         |    }""".stripMargin
+    val unparseStatement =
+      s"""    if (!error_msg)
+         |    {
+         |        error_msg = ${C}_unparseSelf(&instance->$e, ustate);
+         |    }""".stripMargin
+    structs.top.initStatements += initStatement
+    structs.top.parserStatements += parseStatement
+    structs.top.unparserStatements += unparseStatement
+  }
+
+  def pushComplexElement(context: ElementBase): Unit = {
+    val C = context.namedQName.local
+    structs.push(new ComplexCGState(C))
+  }
+
+  def popComplexElement(context: ElementBase): Unit = {
+    structs.pop()
+  }
+
+  def addSimpleTypeERD(context: ElementBase): Unit = {
+    val e = context.namedQName.local
+    val qnameInit = defineQNameInit(context)
+    val typeCode = context.optPrimType.get match {
+      case PrimType.Int => "PRIMITIVE_INT32"
+      case PrimType.String => "PRIMITIVE_STRING"
+      case p: PrimType => context.SDE("PrimType %s not supported yet.", p.toString)
+    }
+    val erd =
+      s"""static const ERD ${e}_ERD = {
+         |$qnameInit
+         |    $typeCode, // typeCode
+         |    0,               // numChildren
+         |    NULL,            // offsets
+         |    NULL,            // childrenERDs
+         |    NULL,            // initSelf
+         |    NULL,            // parseSelf
+         |    NULL,            // unparseSelf
+         |};
+         |""".stripMargin
+    erds += erd
+    addComputations(context)
+  }
+
+  def addComputations(child: ElementBase): Unit = {
+    val C = structs.top.C
+    val e = child.namedQName.local
+    val offsetComputation = s"    (char *)&${C}_compute_ERD_offsets.$e - (char *)&${C}_compute_ERD_offsets"
+    val erdComputation = s"    &${e}_ERD"
+    structs.top.offsetComputations += offsetComputation
+    structs.top.erdComputations += erdComputation
+  }
+
+  def addFieldDeclaration(context: ThrowsSDE, child: ElementBase): Unit = {
+    val definition = if (child.isSimpleType) {
+      import NodeInfo.PrimType
+      child.optPrimType.get match {
+        case PrimType.Long => "int64_t    "
+        case PrimType.Int => "int32_t    "
+        case x => context.SDE("Unsupported primitive type: " + x)
+      }
+    } else {
+      child.namedQName.local + "         "
+    }
+    structs.top.declarations += s"    $definition ${child.name};"
+  }
+
+  def generateCodeHeader: String = {
+    val structs = finalStructs.mkString("\n")
+    val header =
+      s"""#ifndef GENERATED_CODE_H
+         |#define GENERATED_CODE_H
+         |
+         |#include "infoset.h" // for InfosetBase
+         |#include <stdint.h>  // for int32_t
+
+         |// Define some infoset structures
+         |
+         |$structs
+         |#endif // GENERATED_CODE_H
+         |""".stripMargin
+    header
+  }
+
+  def generateCodeFile(rootElementName: String): String = {
+    val prototypes = this.prototypes.mkString("\n")
+    val erds = this.erds.mkString("\n")
+    val finalImplementation = this.finalImplementation.mkString("\n")
+    val code =
+      s"""#include "generated_code.h" // for generated code structs
+         |#include <endian.h>         // for be32toh, htobe32
+         |#include <stddef.h>         // for ptrdiff_t
+         |#include <stdio.h>          // for NULL, fread, fwrite, size_t, FILE
+         |
+         |// Prototypes needed for compilation
+         |
+         |$prototypes
+         |
+         |// Metadata singletons
+         |
+         |$erds
+         |// Return a root element to be used for parsing or unparsing
+         |
+         |InfosetBase *
+         |rootElement()
+         |{
+         |    static $rootElementName    instance;
+         |    InfosetBase *root = &instance._base;
+         |    ${rootElementName}_ERD.initSelf(root);
+         |    return root;
+         |}
+         |
+         |// Methods to initialize, parse, and unparse infoset nodes
+         |
+         |$finalImplementation
+         |""".stripMargin
+    code
+  }
+}
+
+/**
+ * Accumulates strings of generated C code for nested elements inside
+ * complex elements.
+ */
+class ComplexCGState(val C: String) {
+  val declarations = mutable.ArrayBuffer[String]()
+  val offsetComputations = mutable.ArrayBuffer[String]()
+  val erdComputations = mutable.ArrayBuffer[String]()
+  val initStatements = mutable.ArrayBuffer[String]()
+  val parserStatements = mutable.ArrayBuffer[String]()
+  val unparserStatements = mutable.ArrayBuffer[String]()
+}
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
new file mode 100644
index 0000000..d13be31
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/ElementParseAndUnspecifiedLengthCodeGenerator.scala
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2.generators
+
+import org.apache.daffodil.grammar.primitives.ElementParseAndUnspecifiedLength
+import org.apache.daffodil.runtime2.Runtime2CodeGenerator
+
+trait ElementParseAndUnspecifiedLengthCodeGenerator {
+
+  def elementParseAndUnspecifiedLengthGenerateCode(g: ElementParseAndUnspecifiedLength,
+                                                   cgState: CodeGeneratorState): Unit = {
+    val context = g.context
+    val elementContentGram = g.eGram // a Gram isA ParserGenerator
+
+    context.schemaDefinitionWhen(context.inputValueCalcOption.isDefined, "Elements with inputValueCalc are not supported.")
+    context.schemaDefinitionWhen(context.outputValueCalcOption.isDefined, "Elements with outputValueCalc are not supported.")
+    context.schemaDefinitionUnless(g.eBeforeGram.isEmpty, "Statements associated with elements are not supported.")
+    context.schemaDefinitionUnless(g.eAfterGram.isEmpty, "Statements associated with elements are not supported.")
+    context.schemaDefinitionUnless(g.repTypeElementGram.isEmpty, "dfdlx:repType is not supported.")
+
+    if (context.isSimpleType) {
+      cgState.addSimpleTypeERD(context) // ERD static initializer
+      Runtime2CodeGenerator.generateCode(elementContentGram, cgState) // initSelf, parseSelf, unparseSelf
+    } else {
+      cgState.pushComplexElement(context)
+      context.elementChildren.foreach { child =>
+        if (!child.isSimpleType) {
+          cgState.addComplexTypeStatements(child) // recursive calls to parse, unparse, init
+          cgState.addComputations(child) // offset, ERD computations
+        }
+        cgState.addFieldDeclaration(context, child) // struct member for child
+        Runtime2CodeGenerator.generateCode(child.enclosedElement, cgState) // generate children too
+      }
+      cgState.addStruct(context) // struct definition
+      cgState.addImplementation(context) // initSelf, parseSelf, unparseSelf
+      cgState.addComplexTypeERD(context) // ERD static initializer
+      cgState.popComplexElement(context)
+    }
+  }
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/OrderedSequenceCodeGenerator.scala
similarity index 55%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/OrderedSequenceCodeGenerator.scala
index f0bc051..fe1ee33 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/OrderedSequenceCodeGenerator.scala
@@ -15,20 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+package org.apache.daffodil.runtime2.generators
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+import org.apache.daffodil.grammar.primitives.OrderedSequence
+import org.apache.daffodil.runtime2.Runtime2CodeGenerator
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+trait OrderedSequenceCodeGenerator {
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
+  def orderedSequenceGenerateCode(g: OrderedSequence, cgState: CodeGeneratorState): Unit = {
+    //
+    // To lift this draconian restriction, we have to
+    // generate code for each of the children, and combine them into a block
+    //
+    g.schemaDefinitionUnless(g.sequenceChildren.length == 1, "Only a single child of a sequence is supported.")
+    val child1 = g.sequenceChildren(0)
+    Runtime2CodeGenerator.generateCode(child1, cgState)
   }
-
-  private def documentElement = enclosedElement
-
 }
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/SeqCompCodeGenerator.scala
similarity index 63%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/SeqCompCodeGenerator.scala
index f0bc051..2954fdb 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/runtime2/generators/SeqCompCodeGenerator.scala
@@ -15,20 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+package org.apache.daffodil.runtime2.generators
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+import org.apache.daffodil.grammar.SeqComp
+import org.apache.daffodil.runtime2.Runtime2CodeGenerator
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+trait SeqCompCodeGenerator {
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
+  def seqCompGenerateCode(g: SeqComp, state: CodeGeneratorState): Unit = {
+    for (elem <- g.children) {
+      Runtime2CodeGenerator.generateCode(elem, state)
+    }
   }
-
-  private def documentElement = enclosedElement
-
 }
diff --git a/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala b/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
new file mode 100644
index 0000000..97e2e4b
--- /dev/null
+++ b/daffodil-runtime2/src/main/scala/org/apache/daffodil/tdml/processor/runtime2/Runtime2TDMLDFDLProcessor.scala
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.tdml.processor.runtime2
+
+import dev.dirs.ProjectDirectories
+import org.apache.daffodil.api._
+import org.apache.daffodil.compiler.Compiler
+import org.apache.daffodil.externalvars.Binding
+import org.apache.daffodil.runtime2.ParseResult
+import org.apache.daffodil.runtime2.Runtime2DataProcessor
+import org.apache.daffodil.runtime2.UnparseResult
+import org.apache.daffodil.tdml.processor._
+import org.apache.daffodil.xml.QName
+import org.apache.daffodil.xml.XMLUtils
+
+import scala.xml.Node
+
+final class TDMLDFDLProcessorFactory private(
+  private var compiler: Compiler,
+  private var checkAllTopLevel: Boolean,
+  validateDFDLSchemasArg: Boolean)
+  extends AbstractTDMLDFDLProcessorFactory {
+
+  override def validateDFDLSchemas = validateDFDLSchemasArg
+
+  override type R = TDMLDFDLProcessorFactory
+
+  override def implementationName = "daffodil-runtime2"
+
+  def this() = this(compiler = Compiler(validateDFDLSchemas = true),
+    checkAllTopLevel = false,
+    validateDFDLSchemasArg = true)
+
+  private def copy(
+    compiler: Compiler = compiler,
+    checkAllTopLevel: Boolean = checkAllTopLevel,
+    validateDFDLSchemas: Boolean = validateDFDLSchemas) =
+    new TDMLDFDLProcessorFactory(compiler, checkAllTopLevel, validateDFDLSchemas)
+
+  /**
+   * Deprecated methods must be implemented. Some are just stubs though now.
+   */
+  @deprecated("Use withValidateDFDLSchemas.", "2.6.0")
+  override def setValidateDFDLSchemas(bool: Boolean): Unit = {
+    compiler = compiler.withValidateDFDLSchemas(bool)
+  }
+
+  override def withValidateDFDLSchemas(bool: Boolean): TDMLDFDLProcessorFactory = {
+    copy(compiler = compiler.withValidateDFDLSchemas(bool))
+  }
+
+  @deprecated("Use withCheckAllTopLevel.", "2.6.0")
+  override def setCheckAllTopLevel(checkAllTopLevel: Boolean): Unit = {
+    compiler = compiler.withCheckAllTopLevel(checkAllTopLevel)
+  }
+
+  override def withCheckAllTopLevel(checkAllTopLevel: Boolean): TDMLDFDLProcessorFactory = {
+    copy(compiler = compiler.withCheckAllTopLevel(checkAllTopLevel))
+  }
+
+  @deprecated("Use withTunables.", "2.6.0")
+  override def setTunables(tunables: Map[String, String]): Unit =
+    compiler = compiler.withTunables(tunables)
+
+  override def withTunables(tunables: Map[String, String]): TDMLDFDLProcessorFactory =
+    copy(compiler = compiler.withTunables(tunables))
+
+  @deprecated("Use DaffodilTDMLDFDLProcessor.setExternalDFDLVariables.", "2.6.0")
+  override def setExternalDFDLVariables(externalVarBindings: Seq[Binding]): Unit =
+    compiler = compiler.withExternalDFDLVariablesImpl(externalVarBindings)
+
+  override def withExternalDFDLVariables(externalVarBindings: Seq[Binding]): TDMLDFDLProcessorFactory =
+    copy(compiler = compiler.withExternalDFDLVariablesImpl(externalVarBindings))
+
+  @deprecated("Use arguments to getProcessor()", "2.6.0")
+  override def setDistinguishedRootNode(name: String, namespace: String): Unit =
+    compiler = compiler.withDistinguishedRootNode(name, namespace)
+
+  // Return result is a TDML.CompileResult - so it's the result
+  // of compiling the schema for the test.
+  override def getProcessor(
+    schemaSource: DaffodilSchemaSource,
+    useSerializedProcessor: Boolean,
+    optRootName: Option[String] = None,
+    optRootNamespace: Option[String] = None): TDML.CompileResult = {
+
+    // Compile the DFDL schema into a ProcessorFactory
+    val pf = compiler.compileSource(schemaSource, optRootName, optRootNamespace)
+    val res = if (pf.isError) {
+      Left(pf.getDiagnostics) // DFDL schema compilation diagnostics
+    } else {
+      // Create a CodeGenerator from the DFDL schema for the C language
+      val generator = pf.forLanguage("c")
+
+      // Generate the C source code in our cache directory
+      val rootNS = QName.refQNameFromExtendedSyntax(optRootName.getOrElse("")).toOption
+      val directories = ProjectDirectories.from("org", "Apache Software Foundation", "Daffodil")
+      val outputDir = generator.generateCode(rootNS, directories.cacheDir)
+
+      // Compile the generated code into an executable
+      val executable = generator.compileCode(outputDir)
+
+      // Summarize the result of compiling the schema for the test
+      val compileResult = if (generator.isError) {
+        Left(generator.getDiagnostics) // C code compilation diagnostics
+      } else {
+        // Create a processor for running the test using the executable
+        val processor = new Runtime2TDMLDFDLProcessor(executable)
+        Right((generator.getDiagnostics, processor))
+      }
+      compileResult
+    }
+    res
+  }
+
+}
+
+/**
+ * Delegates all execution, error gathering, error access to the [[Runtime2DataProcessor]].
+ * The responsibility of this class is just for TDML matching up. That is dealing with TDML
+ * XML Infosets, feeding to the unparser, creating XML from the result created by the
+ * [[Runtime2DataProcessor]]. All the "real work" is done by [[Runtime2DataProcessor]].
+ */
+class Runtime2TDMLDFDLProcessor(executable: os.Path) extends TDMLDFDLProcessor {
+
+  override type R = Runtime2TDMLDFDLProcessor
+
+  private val dataProcessor = new Runtime2DataProcessor(executable)
+  private var anyErrors: Boolean = false
+  private var diagnostics: Seq[Diagnostic] = Nil
+
+  @deprecated("Use withDebugging.", "2.6.0")
+  override def setDebugging(b: Boolean) = ???
+  override def withDebugging(b: Boolean): Runtime2TDMLDFDLProcessor = this
+
+  @deprecated("Use withTracing.", "2.6.0")
+  override def setTracing(bool: Boolean): Unit = ???
+  override def withTracing(bool: Boolean): Runtime2TDMLDFDLProcessor = this
+
+  @deprecated("Use withDebugger.", "2.6.0")
+  override def setDebugger(db: AnyRef): Unit = ???
+  override def withDebugger(db: AnyRef): Runtime2TDMLDFDLProcessor = this
+
+  @deprecated("Use withValidationMode.", "2.6.0")
+  override def setValidationMode(validationMode: ValidationMode.Type): Unit = ???
+  override def withValidationMode(validationMode: ValidationMode.Type): Runtime2TDMLDFDLProcessor = this
+
+  @deprecated("Use withExternalDFDLVariables.", "2.6.0")
+  override def setExternalDFDLVariables(externalVarBindings: Seq[Binding]): Unit = ???
+  override def withExternalDFDLVariables(externalVarBindings: Seq[Binding]): Runtime2TDMLDFDLProcessor = this
+
+  // Save any errors from running the C code here to be returned later
+  override def isError: Boolean = anyErrors
+  override def getDiagnostics: Seq[Diagnostic] = diagnostics
+
+  // Run the C code, collect and save the infoset with any errors and
+  // diagnostics, and return a [[TDMLParseResult]] summarizing the result.
+  // The C code will run in a subprocess, parse the input stream, write
+  // an XML infoset on its standard output, and write any error messages
+  // on its standard output (all done in [[Runtime2DataProcessor.parse]]).
+  override def parse(is: java.io.InputStream, lengthLimitInBits: Long): TDMLParseResult = {
+    // TODO: pass lengthLimitInBits to the C program to tell it how big the data is
+    val pr = dataProcessor.parse(is)
+    anyErrors = pr.isError
+    diagnostics = pr.getDiagnostics
+    new Runtime2TDMLParseResult(pr)
+  }
+
+  // Run the C code, collect and save the unparsed data with any errors and
+  // diagnostics, and return a [[TDMLUnparseResult]] summarizing the result.
+  // The C code will run in a subprocess, unparse the input stream, write
+  // the unparsed data on its standard output, and write any error messages
+  // on its standard output (all done in [[Runtime2DataProcessor.unparse]]).
+  override def unparse(infosetXML: scala.xml.Node, outStream: java.io.OutputStream): TDMLUnparseResult = {
+    val tempDir = null
+    val tempInputFile = XMLUtils.convertNodeToTempFile(infosetXML, tempDir)
+    val inStream = os.read.inputStream(os.Path(tempInputFile))
+    val upr = dataProcessor.unparse(inStream, outStream)
+    anyErrors = upr.isError
+    diagnostics = upr.getDiagnostics
+    new Runtime2TDMLUnparseResult(upr)
+  }
+
+  def unparse(parseResult: TDMLParseResult, outStream: java.io.OutputStream): TDMLUnparseResult = {
+    unparse(parseResult.getResult, outStream)
+  }
+}
+
+final class Runtime2TDMLParseResult(pr: ParseResult) extends TDMLParseResult {
+  override def addDiagnostic(failure: Diagnostic): Unit = pr.addDiagnostic(failure)
+
+  override def getResult: Node = pr.infosetAsXML
+
+  override def currentLocation: DataLocation = pr.currentLocation
+
+  override def isValidationError: Boolean = pr.isValidationError
+
+  override def isProcessingError: Boolean = pr.isProcessingError
+
+  override def getDiagnostics: Seq[Diagnostic] = pr.getDiagnostics
+}
+
+final class Runtime2TDMLUnparseResult(upr: UnparseResult) extends TDMLUnparseResult {
+  override def bitPos0b: Long = upr.finalBitPos0b
+
+  override def finalBitPos0b: Long = upr.finalBitPos0b
+
+  override def isScannable: Boolean = upr.isScannable
+
+  override def encodingName: String = upr.encodingName
+
+  override def isValidationError: Boolean = upr.isValidationError
+
+  override def isProcessingError: Boolean = upr.isProcessingError
+
+  override def getDiagnostics: Seq[Diagnostic] = upr.getDiagnostics
+}
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
new file mode 100644
index 0000000..81cade0
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.dfdl.xsd
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xs:schema elementFormDefault="qualified"
+           targetNamespace="http://example.com"
+           xmlns="http://example.com"
+           xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+           xmlns:ex="http://example.com"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>
+
+    <xs:annotation>
+        <xs:appinfo source="http://www.ogf.org/dfdl/">
+            <dfdl:format ref="GeneralFormat" representation="binary"/>
+        </xs:appinfo>
+    </xs:annotation>
+
+    <xs:element name="ex_int32">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="e1" type="xs:int"/>
+                <xs:element name="c2">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:element name="e2" type="xs:int"/>
+                            <xs:element name="e3" type="xs:int"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+
+</xs:schema>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
new file mode 100644
index 0000000..7a5d08b
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/TestRuntime2.tdml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+<tdml:testSuite
+  defaultConfig="config-runtime2"
+  defaultImplementations="daffodil daffodil-runtime2"
+  defaultRoundTrip="onePass"
+  description="TDML tests for runtime2"
+  suiteName="TestRuntime2"
+  xmlns:daf="urn:ogf:dfdl:2013:imp:daffodil.apache.org:2018:ext"
+  xmlns:dfdl="http://www.ogf.org/dfdl/dfdl-1.0/"
+  xmlns:ex="http://example.com"
+  xmlns:tdml="http://www.ibm.com/xmlns/dfdl/testData"
+  xmlns="http://example.com">
+
+  <tdml:defineConfig name="config-runtime1">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:defineConfig name="config-runtime2">
+    <daf:tunables>
+      <daf:tdmlImplementation>daffodil-runtime2</daf:tdmlImplementation>
+    </daf:tunables>
+  </tdml:defineConfig>
+
+  <tdml:parserTestCase
+    description="Parse binary int32 integers"
+    model="TestRuntime2.dfdl.xsd"
+    name="parse_int32">
+    <tdml:document>
+      <tdml:documentPart type="file">parse_int32</tdml:documentPart>
+    </tdml:document>
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">unparse_int32</tdml:dfdlInfoset>
+    </tdml:infoset>
+  </tdml:parserTestCase>
+
+  <tdml:unparserTestCase
+    description="Unparse binary int32 numbers"
+    model="TestRuntime2.dfdl.xsd"
+    name="unparse_int32">
+    <tdml:infoset>
+      <tdml:dfdlInfoset type="file">unparse_int32</tdml:dfdlInfoset>
+    </tdml:infoset>
+    <tdml:document>
+      <tdml:documentPart type="file">parse_int32</tdml:documentPart>
+    </tdml:document>
+  </tdml:unparserTestCase>
+
+</tdml:testSuite>
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32 b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32
new file mode 100644
index 0000000..fce373f
Binary files /dev/null and b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32 differ
diff --git a/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32 b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32
new file mode 100644
index 0000000..ea15640
--- /dev/null
+++ b/daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/unparse_int32
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<ex:ex_int32 xmlns:ex="http://example.com">
+  <ex:e1>1</ex:e1>
+  <ex:c2>
+    <ex:e2>2</ex:e2>
+    <ex:e3>3</ex:e3>
+  </ex:c2>
+</ex:ex_int32>
diff --git a/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
new file mode 100644
index 0000000..19d5682
--- /dev/null
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestCodeGenerator.scala
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.daffodil.runtime2
+
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.nio.channels.Channels
+
+import org.apache.daffodil.Implicits.intercept
+import org.apache.daffodil.compiler.Compiler
+import org.apache.daffodil.util.Misc
+import org.apache.daffodil.util.SchemaUtils
+import org.apache.daffodil.util.TestUtils
+import org.junit.Assert.assertArrayEquals
+import org.junit.Test
+
+/**
+ * Checks that we can create a [[CodeGenerator]] and call its methods.
+ * The value of this test is to debug the call path from [[Compiler]]
+ * to [[CodeGenerator]] for one very simple DFDL schema.  Running TDML
+ * tests with daffodil-runtime2 is a more effective way to test the
+ * functionality of CodeGenerator's generated code for as many DFDL
+ * schemas as you could want.
+ */
+class TestCodeGenerator {
+  // Define a simple DFDL test schema for debugging our code path
+  private val testSchema = SchemaUtils.dfdlTestSchema(
+      <xs:include schemaLocation="org/apache/daffodil/xsd/DFDLGeneralFormat.dfdl.xsd"/>,
+      <dfdl:format representation="binary" ref="GeneralFormat"/>,
+    <xs:element name="e1">
+      <xs:complexType>
+        <xs:sequence>
+          <xs:element name="x" type="xs:int"/>
+        </xs:sequence>
+      </xs:complexType>
+    </xs:element>)
+
+  @Test def test_forLanguageC_success(): Unit = {
+    // Create a ProcessorFactory from the test schema
+    val pf = Compiler().compileNode(testSchema)
+    assert(!pf.isError, pf.getDiagnostics.map(_.getMessage()).mkString("\n"))
+
+    // Create a CodeGenerator from the ProcessorFactory for a supported language
+    val cg = pf.forLanguage("c")
+    assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
+  }
+
+  @Test def test_forLanguage_error(): Unit = {
+    // Create a ProcessorFactory from the test schema
+    val pf = Compiler().compileNode(testSchema)
+    assert(!pf.isError, pf.getDiagnostics.map(_.getMessage()).mkString("\n"))
+
+    // Create a CodeGenerator from the ProcessorFactory for an unsupported language
+    val e = intercept[Exception] {
+      pf.forLanguage("vhld")
+    }
+    assert(e.getMessage.contains("source language vhld is not supported"))
+  }
+
+  @Test def test_generateCode_success(): Unit = {
+    // Create a ProcessorFactory and CodeGenerator from the test schema
+    val pf = Compiler().compileNode(testSchema)
+    val cg = pf.forLanguage("c")
+
+    // Generate code from the test schema successfully
+    val outputDir = cg.generateCode(None, "./generateCode_tmp")
+    assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
+    assert(os.exists(outputDir))
+    assert(os.exists(outputDir/"c"/"generated_code.c"))
+
+    // Remove the generated code
+    os.remove.all(outputDir)
+  }
+
+  @Test def test_compileCode_success(): Unit = {
+    // Create a CodeGenerator and generate code from the test schema
+    val pf = Compiler().compileNode(testSchema)
+    val cg = pf.forLanguage("c")
+    val outputDir = cg.generateCode(None, "./compileCode_tmp")
+
+    // Compile the generated code into an executable successfully
+    val executable = cg.compileCode(outputDir)
+    assert(!cg.isError, cg.getDiagnostics.map(_.getMessage()).mkString("\n"))
+    assert(os.exists(executable))
+
+    // Remove the generated code
+    os.remove.all(outputDir)
+  }
+
+  @Test def test_parse_success(): Unit = {
+    // Compile the test schema into a C executable
+    val pf = Compiler().compileNode(testSchema)
+    val cg = pf.forLanguage("c")
+    val outputDir = cg.generateCode(None, "./parse_tmp")
+    val executable = cg.compileCode(outputDir)
+
+    // Create a Runtime2DataProcessor and parse a binary int32 number successfully
+    val dp = new Runtime2DataProcessor(executable)
+    val b = Misc.hex2Bytes("00000005")
+    val input = new ByteArrayInputStream(b)
+    val pr = dp.parse(input)
+    assert(!pr.isError && pf.getDiagnostics.isEmpty, pr.getDiagnostics.map(_.getMessage()).mkString("\n"))
+    val expected = <e1><x>5</x></e1>
+    TestUtils.assertEqualsXMLElements(expected, pr.infosetAsXML)
+
+    // Remove the generated code
+    os.remove.all(outputDir)
+  }
+
+  @Test def test_unparse_success(): Unit = {
+    // Compile the test schema into a C executable
+    val pf = Compiler().compileNode(testSchema)
+    val cg = pf.forLanguage("c")
+    val outputDir = cg.generateCode(None, "./unparse_tmp")
+    val executable = cg.compileCode(outputDir)
+
+    // Create a Runtime2DataProcessor and unparse a binary int32 number successfully
+    val dp = new Runtime2DataProcessor(executable)
+    val input = Channels.newInputStream(Misc.stringToReadableByteChannel("<e1><x>5</x></e1>"))
+    val output = new ByteArrayOutputStream()
+    val pr = dp.unparse(input, output)
+    assert(!pr.isError && pf.getDiagnostics.isEmpty, pr.getDiagnostics.map(_.getMessage()).mkString("\n"))
+    val expected = Misc.hex2Bytes("00000005")
+    assertArrayEquals(expected, output.toByteArray)
+
+    // Remove the generated code
+    os.remove.all(outputDir)
+  }
+}
diff --git a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
similarity index 61%
copy from daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
copy to daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
index f0bc051..9bada7c 100644
--- a/daffodil-core/src/main/scala/org/apache/daffodil/grammar/ElementDeclGrammarMixin.scala
+++ b/daffodil-runtime2/src/test/scala/org/apache/daffodil/runtime2/TestRuntime2.scala
@@ -15,20 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.daffodil.grammar
+package org.apache.daffodil.runtime2
 
-import org.apache.daffodil.grammar.primitives.UnicodeByteOrderMark
-import org.apache.daffodil.dsom.Root
+import org.junit.Test
+import org.apache.daffodil.tdml.Runner
+import org.junit.AfterClass
 
-trait RootGrammarMixin
-  extends LocalElementGrammarMixin // can be repeating if not root
-  { self: Root =>
+object TestRuntime2 {
+  val testDir = "/org/apache/daffodil/runtime2/"
+  val runner = Runner(testDir, "TestRuntime2.tdml")
 
-  final lazy val document = prod("document") {
-    schemaDefinitionUnless(isScalar, "The document element cannot be an array.")
-    UnicodeByteOrderMark(this) ~ documentElement
-  }
+  @AfterClass def shutDown(): Unit = { runner.reset }
+}
 
-  private def documentElement = enclosedElement
+class TestRuntime2 {
+  import TestRuntime2._
 
+  @Test def test_parse_int32(): Unit = { runner.runOneTest("parse_int32") }
+  @Test def test_unparse_int32(): Unit = { runner.runOneTest("unparse_int32") }
 }
diff --git a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
index 0ac8fa6..a337045 100644
--- a/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
+++ b/daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tdml/TDMLRunner.scala
@@ -477,7 +477,12 @@ abstract class TestCase(testCaseXML: NodeSeq, val parent: DFDLTestSuite)
   lazy val tdmlDFDLProcessorFactory: AbstractTDMLDFDLProcessorFactory = {
     import scala.language.existentials
 
-    val className = "org.apache.daffodil.tdml.processor.TDMLDFDLProcessorFactory"
+    // Our TDMLDFDLProcessorFactory implementation is a tunable choice with three values.
+    val className = tunableObj.tdmlImplementation match {
+      case "daffodil" => "org.apache.daffodil.tdml.processor.TDMLDFDLProcessorFactory"
+      case "daffodil-runtime2" => "org.apache.daffodil.tdml.processor.runtime2.TDMLDFDLProcessorFactory"
+      case "ibm" => "org.apache.daffodil.tdml.processor.ibm.TDMLDFDLProcessorFactory"
+    }
 
     //
     // If you haven't seen it before. Check out this Try(...) idiom.
@@ -1334,7 +1339,7 @@ case class UnparserTestCase(ptc: NodeSeq, parentArg: DFDLTestSuite)
     if (testDataLength >= 0) {
       val fullBytesNeeded = (testDataLength + 7) / 8
       if (testData.length != fullBytesNeeded) {
-        throw TDMLException("Unparse result data was was %d bytes, but the result length (%d bits) requires %d bytes.".format(
+        throw TDMLException("Unparse result data was %d bytes, but the result length (%d bits) requires %d bytes.".format(
           testData.length, testDataLength, fullBytesNeeded), implString)
       }
     }
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 8a87c60..61bb2bc 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -29,7 +29,9 @@ object Dependencies {
     "xml-resolver" % "xml-resolver" % "1.2",
     "commons-io" % "commons-io" % "2.8.0",
     "jline" % "jline" % "2.14.6",
-    "com.typesafe" % "config" % "1.4.1"
+    "com.typesafe" % "config" % "1.4.1",
+    "com.lihaoyi" %% "os-lib" % "0.7.1", // for generating C source files
+    "dev.dirs" % "directories" % "21" // for caching compiled C files
   )
 
   lazy val infoset = Seq(
@@ -37,7 +39,7 @@ object Dependencies {
     "com.fasterxml.woodstox" % "woodstox-core" % "6.2.4",
     "com.fasterxml.jackson.core" % "jackson-core" % "2.12.2"
   )
-   
+
   lazy val cli = Seq( 
     "org.fusesource.jansi" % "jansi" % "1.18",
     "org.rogach" %% "scallop" % "4.0.2",
diff --git a/project/Rat.scala b/project/Rat.scala
index 67e67c8..f9742a1 100644
--- a/project/Rat.scala
+++ b/project/Rat.scala
@@ -116,6 +116,7 @@ object Rat {
     file("daffodil-sapi/src/test/resources/test/sapi/myData16.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myData19.dat"),
     file("daffodil-sapi/src/test/resources/test/sapi/myDataBroken.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/parse_int32"),
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.bin"),
     file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
     file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 5c96e37..b8cee2a 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+addSbtPlugin("com.github.tnakamot" % "sbt-cc" % "0.0.3")
+
 addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.1")
 
 addSbtPlugin("org.musigma" % "sbt-rat" % "0.7.0")
diff --git a/sonar-project.properties b/sonar-project.properties
index c4e0de3..6e2c1c9 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -16,9 +16,10 @@
 sonar.organization=apache
 sonar.projectKey=apache-daffodil
 
-sonar.modules=daffodil-cli,daffodil-core,daffodil-io,daffodil-japi,daffodil-lib,daffodil-macro-lib,daffodil-propgen,daffodil-runtime1,daffodil-runtime1-unparser,daffodil-sapi,daffodil-tdml-lib,daffodil-tdml-processor,daffodil-test,daffodil-test-ibm1,daffodil-udf
+sonar.modules=daffodil-cli,daffodil-core,daffodil-io,daffodil-japi,daffodil-lib,daffodil-macro-lib,daffodil-propgen,daffodil-runtime1,daffodil-runtime1-unparser,daffodil-runtime2,daffodil-sapi,daffodil-tdml-lib,daffodil-tdml-processor,daffodil-test,daffodil-test-ibm1,daffodil-udf
 sonar.sources=src/main
 sonar.tests=src/it,src/test
+
 # TODO DAFFODIL-1747 Scala/Java APIs currently contain a lot of duplication
 #  by their nature. Best to exclude them. This will want to be removed when
 #  the ticket above is fixed