I would agree based on your description. In that case, I think you just
need to set the bitOrder property to "leastSignificantBitFirst" and the
fields will parse as you would expect. The Ordinal_Number element will
parse exactly the same as before since it starts and ends on a byte
boundary (bitOrder has no effect if everything is on a byte boundary).
The Zero element will then consume all of the the third byte and the 7
least significant bits of the 4th byte. And the Ordinal_Flag element
will consume the most significant bit of the last byte.

- Steve


On 2/12/19 5:09 PM, Costello, Roger L. wrote:
> Thank you Steve! The fixed="0" works like a charm.
> 
> But I just realized a potential fatal wrinkle in this problem.
> 
> EXE files are in Little Endian format .... oops!
> 
> The EXE specification says that the "most significant bit (bit 31)" is the 
> thing 
> that determines how to interpret the other 31 bits.
> 
> In a 4-byte Little Endian field, the most significant bit (bit 31) is the 
> first 
> bit of the last byte:
> 
> I have been thinking that the most significant bit is the last bit of the 
> last 
> byte, which is wrong.
> 
> So, this is not correct:
> 
> <xs:sequence>
> <xs:elementname="Ordinal_Number"type="unsignedint16"/>
> <xs:elementname="Zero"type="unsignedint15"fixed="0"/>
> <xs:elementname="Ordinal_Flag"type="unsignedint1">
> <xs:annotation>
> <xs:appinfosource="http://www.ogf.org/dfdl/";>
> <dfdl:discriminatortest="{ . eq 1 }"/>
> </xs:appinfo>
> </xs:annotation>
> </xs:element>
> </xs:sequence>
> 
> Do you agree?
> 
> /Roger
> 
> -----Original Message-----
> From: Steve Lawrence <[email protected]>
> Sent: Tuesday, February 12, 2019 7:42 AM
> To: [email protected]; Costello, Roger L. <[email protected]>
> Subject: [EXT] Re: Can bits be cast to string, concatenated, and then cast to 
> an 
> unsigned int?
> 
> I think the reason is because of the discriminator on the Zero element.
> 
> When a discriminator test passes, that tells Daffodil that the surrounding 
> point 
> of uncertainty (PoU) has been resolved and that Daffodil has taken the 
> correct 
> branch. If something later causes that branch to fail, Daffodil will not try 
> any 
> other branches related to that PoU, but will instead continue to backtrack 
> passed the PoU to the next one.
> 
> So in this case we parse the Zero element and it just happens to be all 
> zeros, 
> even though we know we're in the wrong branch. The { . eq 0 } test on the 
> Zero 
> element passes, alerting Daffodil that it has chosen the correct choice 
> branch. 
> Then it parses the Ordinal_Flag element which has a value of 1. This 
> discriminator fails, causing Daffodil to backtrack. But we've already 
> resolved 
> the choice PoU, so we don't try the other branch.
> 
> The reason it works when you swap the order of the choice branches is because 
> it 
> parses the correct choice branch first--the Zero discriminator was never set 
> to 
> tell it not to try this branch.
> 
> So what's the right fix?
> 
> First of all, the discriminator on the Zero element should definitely change. 
> The Zero element having a value of 0 doesn't mean that we've taken the 
> correct 
> branch, which is what the discriminator will say.
> 
> One approach would be to change that dfdl:discriminator to a dfdl:assert, 
> which 
> will not resolve the PoU when the value of Zero is 0, but will cause the same 
> backtracking behavior when it's not 0. This will allow Daffodil to attempt 
> the 
> second branch.
> 
> However, I would argue that that isn't necessarily the right behavior.
> 
> Regardless of the value of Zero, you only want to backtrack and try the 
> second 
> branch when Ordinal_Flag is not zero. That is the thing that determines which 
> choice branch we should take, not whether or not Zero has the correct value 
> or 
> not. So I would argue that the Zero element being 0 should be a validation 
> check, not a runtime parse check.
> 
> Syntactically, it's fine if that value is non-zero, but when someone wants to 
> validate if what was parsed actually looked like an EXE, that being non-zero 
> would raise a flag that something wasn't right. So I would recommend doing 
> something like this:
> 
>    <xs:element name="Zero" type="unsignedint15" fixed="0" />
> 
> Setting the "fixed" attribute will not affect the parse at all, but will 
> cause a 
> validation error if the value wasn't correct.
> 
> - Steve
> 
> On 2/12/19 4:21 AM, Costello, Roger L. wrote:
> 
>  > Thanks Steve - awesome!
> 
>  >
> 
>  > I tried the second approach that you provided. See below. When I run it, I 
> get this error message:
> 
>  >
> 
>  > [error] Parse Error: Failed to populate Lookup_Table_Entry[1]. Cause:
> 
>  > Parse Error: All choice alternatives failed. Reason(s): List(Parse
> 
>  > Error: Alternative failed. Reason(s): List(Parse Error: Assertion
> 
>  > failed: { . eq 1 } failed
> 
>  >
> 
>  > On the other hand, if I switch the order of the sequences in
> 
>  > xs:choice, then I get no error. Why do I get an error with the
> 
>  > sequences in one order but no error in another order?  /Roger
> 
>  >
> 
>  > <xs:element name="Lookup_Table_Entry" dfdl:length="32" 
> dfdl:lengthKind="explicit" dfdl:lengthUnits="bits">
> 
>  >     <xs:annotation>
> 
>  >         <xs:appinfo source="http://www.ogf.org/dfdl/";>
> 
>  >             <dfdl:discriminator test="{
> 
>  >                 fn:not(
> 
>  >                 (fn:exists(./Hint_Name_Table_RVA)) and
> 
>  >                 (./Hint_Name_Table_RVA eq 0) and
> 
>  >                 (./Name_Flag eq 0)
> 
>  >                 )
> 
>  >                 }" />
> 
>  >         </xs:appinfo>
> 
>  >     </xs:annotation>
> 
>  >     <xs:complexType>
> 
>  >         <xs:choice>
> 
>  >             <xs:sequence>
> 
>  >                 <xs:element name="Ordinal_Number" type="unsignedint16" />
> 
>  >                 <xs:element name="Zero" type="unsignedint15">
> 
>  >                     <xs:annotation>
> 
>  >                         <xs:appinfo source="http://www.ogf.org/dfdl/";>
> 
>  >                             <dfdl:discriminator test="{ . eq 0 }" />
> 
>  >                         </xs:appinfo>
> 
>  >                     </xs:annotation>
> 
>  >                 </xs:element>
> 
>  >                 <xs:element name="Ordinal_Flag" type="unsignedint1">
> 
>  >                     <xs:annotation>
> 
>  >                         <xs:appinfo source="http://www.ogf.org/dfdl/";>
> 
>  >                             <dfdl:discriminator test="{ . eq 1 }" />
> 
>  >                         </xs:appinfo>
> 
>  >                     </xs:annotation>
> 
>  >                 </xs:element>
> 
>  >             </xs:sequence>
> 
>  >             <xs:sequence>
> 
>  >                 <xs:element name="Hint_Name_Table_RVA" 
> type="unsignedint31" />
> 
>  >                 <xs:element name="Name_Flag" type="unsignedint1">
> 
>  >                     <xs:annotation>
> 
>  >                         <xs:appinfo source="http://www.ogf.org/dfdl/";>
> 
>  >                             <dfdl:discriminator test="{ . eq 0 }" />
> 
>  >                         </xs:appinfo>
> 
>  >                     </xs:annotation>
> 
>  >                 </xs:element>
> 
>  >             </xs:sequence>
> 
>  >         </xs:choice>
> 
>  >     </xs:complexType>
> 
>  > </xs:element>
> 
>  >
> 
>  >
> 
>  >
> 
>  > -----Original Message-----
> 
>  > From: Steve Lawrence <[email protected] <mailto:[email protected]>>
> 
>  > Sent: Monday, February 11, 2019 8:10 AM
> 
>  > To: [email protected] <mailto:[email protected]>; 
> Costello, 
> Roger L. <[email protected] <mailto:[email protected]>>
> 
>  > Subject: [EXT] Re: Can bits be cast to string, concatenated, and then cast 
> to 
> an unsigned int?
> 
>  >
> 
>  > Concating bit values will not work because there are no constructor 
> functions 
> that accept a bit string. The dfdl:setBits() function can be used, but only 
> for 
> only for bytes (i.e. 8 bits or less). You could always just use math to 
> construct an int, e.g.:
> 
>  >
> 
>  >   ./bit1 * fn:pow(2,31) +
> 
>  >   ./bit2 * fn:pow(2,30) +
> 
>  >   ...
> 
>  >   ./bitN * fn:pow(2,0)
> 
>  >
> 
>  > It would probably be more efficient to expand the fn:pow's to their actual 
> values, but this gives the idea.
> 
>  >
> 
>  > That said, I think an approach that makes for a more descriptive schema 
> that 
> is easier to understand is to use a choice where each branch of the choice 
> parses the 30 bits differently, and a discriminator is used to ensure the 
> correct branch is taken based on the lst bit. Something like:
> 
>  >
> 
>  >   <xs:choice>
> 
>  >     <xs:sequence>
> 
>  >       <xs:element name="OrdinalNumber" dfdl:length="16" ... />
> 
>  >       <xs:element name="Zero" dfdl:length="15 ... />
> 
>  >       <xs:element name="Flag" dfdl:length=1" ... >
> 
>  >         <xs:annotation>
> 
>  >           <xs:appinfo source="http://www.ogf.org/dfdl/";>
> 
>  >             <dfdl:discriminator test="{ . eq 1 }" />
> 
>  >           </xs:appinfo>
> 
>  >         </xs:annotation>
> 
>  >       </xs:element>
> 
>  >     </xs:sequence>
> 
>  >     <xs:sequence>
> 
>  >       <xs:element name="HintNameTableRVA" dfdl:length="31" ... />
> 
>  >       <xs:element name="Flag" dfdl:length=1" ... >
> 
>  >         <xs:annotation>
> 
>  >           <xs:appinfo source="http://www.ogf.org/dfdl/";>
> 
>  >             <dfdl:discriminator test="{ . eq 0 }" />
> 
>  >           </xs:appinfo>
> 
>  >         </xs:annotation>
> 
>  >       </xs:element>
> 
>  >     </xs:sequence>
> 
>  >   </xs:choice>
> 
>  >
> 
>  > This is bit inefficient since it requires parsing the same 32 bits twice 
> if 
> the last bit is a 0, but it's much easier to understand what data looks like.
> 
>  >
> 
>  > - Steve
> 
>  >
> 
>  >
> 
>  > On 2/11/19 6:43 AM, Costello, Roger L. wrote:
> 
>  >> Hello DFDL Community,
> 
>  >>
> 
>  >> My input file contains a 32-bit field (bit 0 to bit 31). Bit 31
> 
>  >> determines how to interpret the other bits: if bit 31 = 1 then bits 0
> 
>  >> to 15 is an unsigned int denoting an ordinal number and the other
> 
>  >> bits must be zero. If bit 30 = 0 then bits 0 to 30 is an unsigned int
> 
>  >> denoting a hint/name table RVA. The following graphic illustrates the 
> structure:
> 
>  >>
> 
>  >> How to express this in DFDL? I figured that I would create a hidden
> 
>  >> group that contains 32 1-bit elements. I would have a choice that
> 
>  >> expresses this: If hidden bit 31 = 1 then choose the ordinal_number
> 
>  >> element, otherwise (hidden bit 31 = 0) choose hint_name_table_RVA element.
> 
>  >>
> 
>  >> The value of ordinal_number is calculated by concatenating hidden bit
> 
>  >> 0 with hidden bit 1, ..., hidden bit 15. Then, cast that to unsigned int.
> 
>  >>
> 
>  >> The value of hint_name_table_RVA is calculated by concatenating
> 
>  >> hidden bit 0 with hidden bit 1, ..., hidden bit 30. Then, cast that to 
> unsigned int.
> 
>  >>
> 
>  >> You can see my schema below. Unfortunately, it fails. What is the
> 
>  >> right way to approach this problem, please?  /Roger
> 
>  >>
> 
>  >> <xs:elementname="Ordinal_Number"type="unsignedint16"dfdl:inputValueCalc="{
> 
>  >>      unsignedint16(
> 
>  >>      fn:concat(./Hidden_Lookup_Table_bit0,
> 
>  >>      ./Hidden_Lookup_Table_bit1,
> 
>  >>      ./Hidden_Lookup_Table_bit2,
> 
>  >>      ./Hidden_Lookup_Table_bit3,
> 
>  >>      ./Hidden_Lookup_Table_bit4,
> 
>  >>      ./Hidden_Lookup_Table_bit5,
> 
>  >>      ./Hidden_Lookup_Table_bit6,
> 
>  >>      ./Hidden_Lookup_Table_bit7,
> 
>  >>      ./Hidden_Lookup_Table_bit8,
> 
>  >>      ./Hidden_Lookup_Table_bit9,
> 
>  >>      ./Hidden_Lookup_Table_bit10,
> 
>  >>      ./Hidden_Lookup_Table_bit11,
> 
>  >>      ./Hidden_Lookup_Table_bit12,
> 
>  >>      ./Hidden_Lookup_Table_bit13,
> 
>  >>      ./Hidden_Lookup_Table_bit14,
> 
>  >>      ./Hidden_Lookup_Table_bit15))
> 
>  >>      }"/>
> 
>  >>
> 
>  >> 
> <xs:elementname="Hint_Name_Table_RVA"type="unsignedint31"dfdl:inputValueCalc="{
> 
>  >>      unsignedint31(
> 
>  >>      fn:concat(./Hidden_Lookup_Table_bit0,
> 
>  >>      ./Hidden_Lookup_Table_bit1,
> 
>  >>      ./Hidden_Lookup_Table_bit2,
> 
>  >>      ./Hidden_Lookup_Table_bit3,
> 
>  >>      ./Hidden_Lookup_Table_bit4,
> 
>  >>      ./Hidden_Lookup_Table_bit5,
> 
>  >>      ./Hidden_Lookup_Table_bit6,
> 
>  >>      ./Hidden_Lookup_Table_bit7,
> 
>  >>      ./Hidden_Lookup_Table_bit8,
> 
>  >>      ./Hidden_Lookup_Table_bit9,
> 
>  >>      ./Hidden_Lookup_Table_bit10,
> 
>  >>      ./Hidden_Lookup_Table_bit11,
> 
>  >>      ./Hidden_Lookup_Table_bit12,
> 
>  >>      ./Hidden_Lookup_Table_bit13,
> 
>  >>      ./Hidden_Lookup_Table_bit14,
> 
>  >>      ./Hidden_Lookup_Table_bit15,
> 
>  >>      ./Hidden_Lookup_Table_bit16,
> 
>  >>      ./Hidden_Lookup_Table_bit17,
> 
>  >>      ./Hidden_Lookup_Table_bit18,
> 
>  >>      ./Hidden_Lookup_Table_bit19,
> 
>  >>      ./Hidden_Lookup_Table_bit20,
> 
>  >>      ./Hidden_Lookup_Table_bit21,
> 
>  >>      ./Hidden_Lookup_Table_bit22,
> 
>  >>      ./Hidden_Lookup_Table_bit23,
> 
>  >>      ./Hidden_Lookup_Table_bit24,
> 
>  >>      ./Hidden_Lookup_Table_bit25,
> 
>  >>      ./Hidden_Lookup_Table_bit26,
> 
>  >>      ./Hidden_Lookup_Table_bit27,
> 
>  >>      ./Hidden_Lookup_Table_bit28,
> 
>  >>      ./Hidden_Lookup_Table_bit29,
> 
>  >>      ./Hidden_Lookup_Table_bit30
> 
>  >>      ))
> 
>  >>      }"/>
> 
>  >>
> 
>  >> <xs:groupname="hidden_Lookup_Table_Group">
> 
>  >> <xs:sequencedfdl:alignmentUnits="bits">
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit7"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit6"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit5"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit4"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit3"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit2"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit1"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit0"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit15"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit14"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit13"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit12"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit11"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit10"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit9"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit8"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit23"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit22"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit21"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit20"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit19"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit18"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit17"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit16"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit31"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit30"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit29"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit28"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit27"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit26"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit25"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> <xs:elementname="Hidden_Lookup_Table_bit24"type="unsignedint1"
> 
>  >>              dfdl:outputValueCalc='{ . }'
> 
>  >> />
> 
>  >> </xs:sequence>
> 
>  >> </xs:group>
> 
>  >>
> 
>  >
> 

Reply via email to