dts: dtlib: Remember the format of assignments

Previously, dtlib just stored the raw 'bytes' value for each property,
along with some markers in Property._markers for phandle and path
references.

Extend Property._markers to also remember where different data blocks
start, so that e.g.

    foo = <1 2 3>, "bar", [00 01];

can be reproduced as written.

Use the new information to reproduce properties as written in
Property.__str__(). This gives good test coverage as well, since the
test suite checks literal __str__() output.

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
Ulf Magnusson 2019-08-09 00:44:33 +02:00 committed by Kumar Gala
commit c9ac5e60e3
2 changed files with 277 additions and 155 deletions

View file

@ -431,14 +431,14 @@ class DT:
tok = self._next_token()
if tok.val == "<":
self._parse_cells(prop, 32)
self._parse_cells(prop, 4)
elif tok.id is _T_BITS:
n_bits = self._expect_num()
if n_bits not in {8, 16, 32, 64}:
self._parse_error("expected 8, 16, 32, or 64")
self._expect_token("<")
self._parse_cells(prop, n_bits)
self._parse_cells(prop, n_bits//8)
elif tok.val == "[":
self._parse_bytes(prop)
@ -450,10 +450,11 @@ class DT:
prop.value += val
elif tok.id is _T_STRING:
prop._add_marker(_TYPE_STRING)
prop.value += self._unescape(tok.val.encode("utf-8")) + b"\0"
elif tok.id is _T_REF:
prop._add_marker(tok.val, _PATH)
prop._add_marker(_REF_PATH, tok.val)
elif tok.id is _T_INCBIN:
self._parse_incbin(prop)
@ -471,20 +472,22 @@ class DT:
continue
self._parse_error("expected ';' or ','")
def _parse_cells(self, prop, bits):
def _parse_cells(self, prop, n_bytes):
# Parses '<...>'
prop._add_marker(_N_BYTES_TO_TYPE[n_bytes])
while True:
tok = self._peek_token()
if tok.id is _T_REF:
self._next_token()
if bits != 32:
if n_bytes != 4:
self._parse_error("phandle references are only allowed in "
"arrays with 32-bit elements")
prop._add_marker(tok.val, _PHANDLE)
prop._add_marker(_REF_PHANDLE, tok.val)
elif tok.id is _T_LABEL:
prop._add_marker(tok.val, _LABEL)
prop._add_marker(_REF_LABEL, tok.val)
self._next_token()
elif self._check_token(">"):
@ -494,25 +497,27 @@ class DT:
# Literal value
num = self._eval_prim()
try:
prop.value += num.to_bytes(bits//8, "big")
prop.value += num.to_bytes(n_bytes, "big")
except OverflowError:
try:
# Try again as a signed number, in case it's negative
prop.value += num.to_bytes(bits//8, "big", signed=True)
prop.value += num.to_bytes(n_bytes, "big", signed=True)
except OverflowError:
self._parse_error("{} does not fit in {} bits"
.format(num, bits))
.format(num, 8*n_bytes))
def _parse_bytes(self, prop):
# Parses '[ ... ]'
prop._add_marker(_TYPE_UINT8)
while True:
tok = self._next_token()
if tok.id is _T_BYTE:
prop.value += tok.val.to_bytes(1, "big")
elif tok.id is _T_LABEL:
prop._add_marker(tok.val, _LABEL)
prop._add_marker(_REF_LABEL, tok.val)
elif tok.val == "]":
return
@ -529,6 +534,8 @@ class DT:
#
# /incbin/ ("filename", <offset>, <size>)
prop._add_marker(_TYPE_UINT8)
self._expect_token("(")
tok = self._next_token()
@ -566,7 +573,7 @@ class DT:
tok = self._peek_token()
if tok.id is not _T_LABEL:
return
prop._add_marker(tok.val, _LABEL)
prop._add_marker(_REF_LABEL, tok.val)
self._next_token()
def _node_prop(self, node, name):
@ -590,6 +597,7 @@ class DT:
phandle_prop = node.props["phandle"]
else:
phandle_prop = Property(node, "phandle")
phandle_prop._add_marker(_TYPE_UINT32) # For displaying
phandle_prop.value = b'\0\0\0\0'
if phandle_prop.value == b'\0\0\0\0':
@ -955,8 +963,8 @@ class DT:
is_self_referential = False
for marker in phandle._markers:
_, ref, marker_type = marker
if marker_type == _PHANDLE:
_, marker_type, ref = marker
if marker_type is _REF_PHANDLE:
# The phandle's value is itself a phandle reference
if self._ref2node(ref) is node:
# Alright to set a node's phandle equal to its own
@ -1001,17 +1009,26 @@ class DT:
prev_pos = 0
res = b""
for pos, ref, ref_type in prop._markers:
# Add data before the marker
for marker in prop._markers:
pos, marker_type, ref = marker
# Add data before the marker, reading from the unpatched
# property value
res += prop.value[prev_pos:pos]
if ref_type is _LABEL:
# Fix the marker offset so that it's correct for the
# patched property value, for later (not used in this
# function). The offset might change due to path
# references, which expand to something like "/foo/bar".
marker[0] = len(res)
if marker_type is _REF_LABEL:
# This is a temporary format so that we can catch
# duplicate references. prop.offset_labels is changed
# to a dictionary that maps labels to offsets in
# _register_labels().
_append_no_dup(prop.offset_labels, (ref, len(res)))
else:
elif marker_type in (_REF_PATH, _REF_PHANDLE):
# Path or phandle reference
try:
ref_node = self._ref2node(ref)
@ -1021,16 +1038,17 @@ class DT:
# For /omit-if-no-ref/
ref_node._is_referenced = True
if ref_type is _PATH:
if marker_type is _REF_PATH:
res += ref_node.path.encode("utf-8") + b'\0'
else: # ref_type is PHANDLE
else: # marker_type is PHANDLE
res += self._node_phandle(ref_node)
# Skip over the dummy phandle placeholder
pos += 4
prev_pos = pos
# Add data after the last marker
# Store the final fixed-up value. Add the data after the last
# marker.
prop.value = res + prop.value[prev_pos:]
def _register_aliases(self):
@ -1370,10 +1388,10 @@ class Property:
self.offset_labels = []
# A list of (offset, label, type) tuples (sorted by offset), giving the
# locations of references within the value. 'type' is either _PATH, for
# a node path reference, _PHANDLE, for a phandle reference, or _LABEL,
# for a label on/within data. Node paths and phandles need to be
# patched in after parsing.
# locations of references within the value. 'type' is either _REF_PATH,
# for a node path reference, _REF_PHANDLE, for a phandle reference, or
# _REF_LABEL, for a label on/within data. Node paths and phandles need
# to be patched in after parsing.
self._markers = []
def to_num(self, length=4, signed=False):
@ -1460,26 +1478,57 @@ class Property:
def __str__(self):
s = "".join(label + ": " for label in self.labels) + self.name
if not self.value:
return s + ";"
s += " = ["
s += " ="
offset_labels = [(offset, label)
for label, offset in self.offset_labels.items()]
for i, (pos, marker_type, ref) in enumerate(self._markers):
if i < len(self._markers) - 1:
next_marker = self._markers[i + 1]
else:
next_marker = None
label_offset = offset = 0
for label_offset, label in offset_labels:
s += "".join(" {:02X}".format(byte)
for byte in self.value[offset:label_offset]) \
+ " " + label + ":"
offset = label_offset
# End of current marker
end = next_marker[0] if next_marker else len(self.value)
for byte in self.value[label_offset:]:
s += " {:02X}".format(byte)
if marker_type in (_TYPE_STRING, _REF_PATH):
# end - 1 to strip off the null terminator
s += ' "{}"'.format(_decode_and_escape(
self.value[pos:end - 1]))
if end != len(self.value):
s += ","
else:
# Raw data (<>/[])
if marker_type is _REF_LABEL:
s += " {}:".format(ref)
elif marker_type is not _REF_PHANDLE:
# marker_type is _TYPE_UINT_*
elm_size = _TYPE_TO_N_BYTES[marker_type]
s += _N_BYTES_TO_START_STR[elm_size]
while pos != end:
num = int.from_bytes(self.value[pos:pos + elm_size],
"big")
if elm_size == 1:
s += " {:02X}".format(num)
else:
s += " " + hex(num)
pos += elm_size
if pos != 0 and \
(not next_marker or
next_marker[1] not in (_REF_PHANDLE, _REF_LABEL)):
s += _N_BYTES_TO_END_STR[elm_size]
if pos != len(self.value):
s += ","
return s + ";"
return s + " ];"
def __repr__(self):
return "<Property '{}' at '{}' in '{}'>" \
@ -1489,17 +1538,20 @@ class Property:
# Internal functions
#
def _add_marker(self, ref, marker_type):
def _add_marker(self, marker_type, data=None):
# Helper for registering markers in the value that are processed after
# parsing. See _fixup_props().
# parsing. See _fixup_props(). 'marker_type' identifies the type of
# marker, and 'data' has any optional data associated with the marker.
# len(self.value) gives the current offset. This function is called
# while the value is built.
self._markers.append((len(self.value), ref, marker_type))
# while the value is built. We use a list instead of a tuple to be able
# to fix up offsets later (they might increase if the value includes
# path references, e.g. 'foo = &bar, <3>;', which are expanded later).
self._markers.append([len(self.value), marker_type, data])
# For phandle references, add a dummy value with the same length as a
# phandle. This is handy for the length check in _register_phandles().
if marker_type is _PHANDLE:
if marker_type is _REF_PHANDLE:
self.value += b"\0\0\0\0"
def _err_with_context(self, e):
@ -1599,6 +1651,32 @@ def _append_no_dup(lst, elm):
lst.append(elm)
def _decode_and_escape(b):
# Decodes the 'bytes' array 'b' as UTF-8 and backslash-escapes special
# characters
# Hacky but robust way to avoid double-escaping any '\' spit out by
# 'backslashreplace' bytes.translate() can't map to more than a single
# byte, but str.translate() can map to more than one character, so it's
# nice here. There's probably a nicer way to do this.
return b.decode("utf-8", "surrogateescape") \
.translate(_escape_table) \
.encode("utf-8", "surrogateescape") \
.decode("utf-8", "backslashreplace")
_escape_table = str.maketrans({
"\\": "\\\\",
'"': '\\"',
"\a": "\\a",
"\b": "\\b",
"\t": "\\t",
"\n": "\\n",
"\v": "\\v",
"\f": "\\f",
"\r": "\\r"})
class DTError(Exception):
"Exception raised for Device Tree-related errors"
@ -1684,7 +1762,43 @@ def _init_tokens():
_init_tokens()
# Types of markers in property values (for references and in-value labels)
_PATH = 0
_PHANDLE = 1
_LABEL = 2
# Markers in property values
# References
_REF_PATH = 0 # &foo
_REF_PHANDLE = 1 # <&foo>
_REF_LABEL = 2 # foo: <1 2 3>
# Start of data blocks of specific type
_TYPE_UINT8 = 3 # [00 01 02] (and also used for /incbin/)
_TYPE_UINT16 = 4 # /bits/ 16 <1 2 3>
_TYPE_UINT32 = 5 # <1 2 3>
_TYPE_UINT64 = 6 # /bits/ 64 <1 2 3>
_TYPE_STRING = 7 # "foo"
_TYPE_TO_N_BYTES = {
_TYPE_UINT8: 1,
_TYPE_UINT16: 2,
_TYPE_UINT32: 4,
_TYPE_UINT64: 8,
}
_N_BYTES_TO_TYPE = {
1: _TYPE_UINT8,
2: _TYPE_UINT16,
4: _TYPE_UINT32,
8: _TYPE_UINT64,
}
_N_BYTES_TO_START_STR = {
1: " [",
2: " /bits/ 16 <",
4: " <",
8: " /bits/ 64 <",
}
_N_BYTES_TO_END_STR = {
1: " ]",
2: " >",
4: " >",
8: " >",
}

View file

@ -77,15 +77,17 @@ def run():
/dts-v1/;
/ {
a = < >;
b = < 10 20 >;
c = < 0U 1L 2UL 3LL 4ULL >;
d = < 0x10 0x20 >;
e = < 010 020 >;
f = /bits/ 8 < 0x10 0x20 (-1) >;
g = /bits/ 16 < 0x10 0x20 (-1) >;
h = /bits/ 32 < 0x10 0x20 (-1) >;
i = /bits/ 64 < 0x10 0x20 (-1) >;
a;
b = < >;
c = [ ];
d = < 10 20 >;
e = < 0U 1L 2UL 3LL 4ULL >;
f = < 0x10 0x20 >;
g = < 010 020 >;
h = /bits/ 8 < 0x10 0x20 (-1) >;
i = /bits/ 16 < 0x10 0x20 (-1) >;
j = /bits/ 32 < 0x10 0x20 (-1) >;
k = /bits/ 64 < 0x10 0x20 (-1) >;
};
""",
"""
@ -93,14 +95,16 @@ def run():
/ {
a;
b = [ 00 00 00 0A 00 00 00 14 ];
c = [ 00 00 00 00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 04 ];
d = [ 00 00 00 10 00 00 00 20 ];
e = [ 00 00 00 08 00 00 00 10 ];
f = [ 10 20 FF ];
g = [ 00 10 00 20 FF FF ];
h = [ 00 00 00 10 00 00 00 20 FF FF FF FF ];
i = [ 00 00 00 00 00 00 00 10 00 00 00 00 00 00 00 20 FF FF FF FF FF FF FF FF ];
b;
c;
d = < 0xa 0x14 >;
e = < 0x0 0x1 0x2 0x3 0x4 >;
f = < 0x10 0x20 >;
g = < 0x8 0x10 >;
h = [ 10 20 FF ];
i = /bits/ 16 < 0x10 0x20 0xffff >;
j = < 0x10 0x20 0xffffffff >;
k = /bits/ 64 < 0x10 0x20 0xffffffffffffffff >;
};
""")
@ -173,16 +177,16 @@ def run():
/ {
a = "";
b = "ABC";
c = "\\\"\xAB\377\a\b\t\n\v\f\r";
c = "\\\"\xab\377\a\b\t\n\v\f\r";
};
""",
"""
r"""
/dts-v1/;
/ {
a = [ 00 ];
b = [ 41 42 43 00 ];
c = [ 5C 22 AB FF 07 08 09 0A 0B 0C 0D 00 ];
a = "";
b = "ABC";
c = "\\\"\xab\xff\a\b\t\n\v\f\r";
};
""")
@ -377,7 +381,7 @@ l3: &l1 {
a;
l1: b;
l2: l3: c;
l4: l5: l6: d = [ 00 00 00 00 ];
l4: l5: l6: d = < 0x0 >;
};
""")
@ -405,9 +409,8 @@ l3: &l1 {
/dts-v1/;
/ {
a = l01: l02: < l03: l04: &node l05: l06: 2 l07: l08: > l09: l10:,
l11: l12: [ l13: l14: 03 l15: l16: 04 l17: l18: ] l19: l20:,
l21: l22: "A";
a = l01: l02: < l03: &node l04: l05: 2 l06: >,
l07: l08: [ l09: 03 l10: l11: 04 l12: l13: ] l14:, "A";
b = < 0 > l23: l24:;
@ -419,20 +422,21 @@ l3: &l1 {
/dts-v1/;
/ {
a = [ l01: l02: l03: l04: 00 00 00 01 l05: l06: 00 00 00 02 l07: l08: l09: l10: l11: l12: l13: l14: 03 l15: l16: 04 l17: l18: l19: l20: l21: l22: 41 00 ];
b = [ 00 00 00 00 l23: l24: ];
a = l01: l02: < l03: 0x1 l04: l05: 0x2 l06: l07: l08: >, [ l09: 03 l10: l11: 04 l12: l13: l14: ], "A";
b = < 0x0 l23: l24: >;
node: node {
phandle = [ 00 00 00 01 ];
phandle = < 0x1 >;
};
};
""")
verify_label2offset("l01", "a", 0)
verify_label2offset("l04", "a", 0)
verify_label2offset("l02", "a", 0)
verify_label2offset("l04", "a", 4)
verify_label2offset("l05", "a", 4)
verify_label2offset("l14", "a", 8)
verify_label2offset("l15", "a", 9)
verify_label2offset("l22", "a", 10)
verify_label2offset("l06", "a", 8)
verify_label2offset("l09", "a", 8)
verify_label2offset("l10", "a", 9)
verify_label2offset("l23", "b", 4)
verify_label2offset("l24", "b", 4)
@ -487,10 +491,12 @@ l3: &l1 {
/ {
a = &label;
b = &{/abc};
b = [ 01 ], &label;
c = [ 01 ], &label, <2>;
d = &{/abc};
label: abc {
c = &label;
d = &{/abc};
e = &label;
f = &{/abc};
};
};
""",
@ -498,11 +504,13 @@ l3: &l1 {
/dts-v1/;
/ {
a = [ 2F 61 62 63 00 ];
b = [ 2F 61 62 63 00 ];
a = "/abc";
b = [ 01 ], "/abc";
c = [ 01 ], "/abc", < 0x2 >;
d = "/abc";
label: abc {
c = [ 2F 61 62 63 00 ];
d = [ 2F 61 62 63 00 ];
e = "/abc";
f = "/abc";
};
};
""")
@ -563,21 +571,21 @@ l3: &l1 {
/dts-v1/;
/ {
x = [ 00 00 00 02 00 00 00 04 00 00 00 FF ];
x = < 0x2 0x4 0xff >;
dummy1 {
phandle = [ 00 00 00 01 ];
phandle = < 0x1 >;
};
dummy2 {
phandle = [ 00 00 00 03 ];
phandle = < 0x3 >;
};
a: a {
phandle = [ 00 00 00 02 ];
phandle = < 0x2 >;
};
b {
phandle = [ 00 00 00 04 ];
phandle = < 0x4 >;
};
c: c {
phandle = [ 00 00 00 FF ];
phandle = < 0xff >;
};
};
""")
@ -606,13 +614,13 @@ l3: &l1 {
/ {
dummy {
phandle = [ 00 00 00 01 ];
phandle = < 0x1 >;
};
a {
foo: phandle = [ 00 00 00 02 ];
foo: phandle = < 0x2 >;
};
label: b {
bar: phandle = [ 00 00 00 03 ];
bar: phandle = < 0x3 >;
};
};
""")
@ -757,9 +765,9 @@ l3: &l1 {
/dts-v1/;
/ {
x = [ FF FF 2F 61 62 63 00 00 00 00 FF 00 00 00 01 00 00 00 FF 00 00 00 01 2F 61 62 63 00 FF FF 61 62 63 00 ];
x = [ FF FF ], "/abc", < 0xff 0x1 0xff 0x1 >, "/abc", [ FF FF ], "abc";
abc: abc {
phandle = [ 00 00 00 01 ];
phandle = < 0x1 >;
};
};
""")
@ -789,7 +797,7 @@ l3: &l1 {
/dts-v1/;
/ {
keep = [ 00 00 00 01 ];
keep = < 0x1 >;
sub: sub {
};
};
@ -828,7 +836,7 @@ l3: &l1 {
/ {
sub1 {
x = [ 00 00 00 01 ];
x = < 0x1 >;
};
};
""")
@ -904,8 +912,8 @@ y /include/ "via-include-path-1"
/dts-v1/;
/ {
x = [ 00 00 00 01 ];
y = [ 00 00 00 02 ];
x = < 0x1 >;
y = < 0x2 >;
};
""",
include_path=(".tmp", ".tmp2",))
@ -999,9 +1007,9 @@ y /include/ "via-include-path-1"
/dts-v1/;
/ {
x = [ 00 00 00 01 2F 72 65 66 65 72 65 6E 63 65 64 32 00 ];
x = < 0x1 >, "/referenced2";
referenced {
phandle = [ 00 00 00 01 ];
phandle = < 0x1 >;
};
referenced2: referenced2 {
};
@ -1114,51 +1122,51 @@ y /include/ "via-include-path-1"
/dts-v1/;
/ {
ter1 = [ 00 00 00 03 ];
ter2 = [ 00 00 00 02 ];
ter3 = [ 00 00 00 01 ];
ter4 = [ 00 00 00 01 ];
or1 = [ 00 00 00 00 ];
or2 = [ 00 00 00 01 ];
or3 = [ 00 00 00 01 ];
or4 = [ 00 00 00 01 ];
and1 = [ 00 00 00 00 ];
and2 = [ 00 00 00 00 ];
and3 = [ 00 00 00 00 ];
and4 = [ 00 00 00 01 ];
bitor = [ 00 00 00 03 ];
bitxor = [ 00 00 00 05 ];
bitand = [ 00 00 00 02 ];
eq1 = [ 00 00 00 00 ];
eq2 = [ 00 00 00 01 ];
neq1 = [ 00 00 00 01 ];
neq2 = [ 00 00 00 00 ];
lt1 = [ 00 00 00 01 ];
lt2 = [ 00 00 00 00 ];
lt3 = [ 00 00 00 00 ];
lteq1 = [ 00 00 00 01 ];
lteq2 = [ 00 00 00 01 ];
lteq3 = [ 00 00 00 00 ];
gt1 = [ 00 00 00 00 ];
gt2 = [ 00 00 00 00 ];
gt3 = [ 00 00 00 01 ];
gteq1 = [ 00 00 00 00 ];
gteq2 = [ 00 00 00 01 ];
gteq3 = [ 00 00 00 01 ];
lshift = [ 00 00 00 10 ];
rshift = [ 00 00 00 02 ];
add = [ 00 00 00 07 ];
sub = [ 00 00 00 03 ];
mul = [ 00 00 00 0C ];
div = [ 00 00 00 03 ];
mod = [ 00 00 00 02 ];
unary_minus = [ FF FF FF FD ];
bitnot = [ FF FF FF FE ];
not0 = [ 00 00 00 00 ];
not1 = [ 00 00 00 01 ];
not2 = [ 00 00 00 00 ];
not3 = [ 00 00 00 00 ];
nest = [ FF FF FF FE ];
ter1 = < 0x3 >;
ter2 = < 0x2 >;
ter3 = < 0x1 >;
ter4 = < 0x1 >;
or1 = < 0x0 >;
or2 = < 0x1 >;
or3 = < 0x1 >;
or4 = < 0x1 >;
and1 = < 0x0 >;
and2 = < 0x0 >;
and3 = < 0x0 >;
and4 = < 0x1 >;
bitor = < 0x3 >;
bitxor = < 0x5 >;
bitand = < 0x2 >;
eq1 = < 0x0 >;
eq2 = < 0x1 >;
neq1 = < 0x1 >;
neq2 = < 0x0 >;
lt1 = < 0x1 >;
lt2 = < 0x0 >;
lt3 = < 0x0 >;
lteq1 = < 0x1 >;
lteq2 = < 0x1 >;
lteq3 = < 0x0 >;
gt1 = < 0x0 >;
gt2 = < 0x0 >;
gt3 = < 0x1 >;
gteq1 = < 0x0 >;
gteq2 = < 0x1 >;
gteq3 = < 0x1 >;
lshift = < 0x10 >;
rshift = < 0x2 >;
add = < 0x7 >;
sub = < 0x3 >;
mul = < 0xc >;
div = < 0x3 >;
mod = < 0x2 >;
unary_minus = < 0xfffffffd >;
bitnot = < 0xfffffffe >;
not0 = < 0x0 >;
not1 = < 0x1 >;
not2 = < 0x0 >;
not3 = < 0x0 >;
nest = < 0xfffffffe >;
};
""")
@ -1197,7 +1205,7 @@ foo
/dts-v1/;
/ {
x = [ 00 00 00 01 ];
x = < 0x1 >;
};
""")
@ -1788,7 +1796,7 @@ r"b'\xff\x00' is not valid UTF-8 (for property 'a' on /aliases)")
/dts-v1/;
/ {
x = [ 00 00 00 01 ];
x = < 0x1 >;
foo: foo {
};
};
@ -1812,8 +1820,8 @@ r"b'\xff\x00' is not valid UTF-8 (for property 'a' on /aliases)")
/ {
label: foo {
x = [ 2F 66 6F 6F 00 2F 66 6F 6F 00 00 00 00 01 ];
phandle = [ 00 00 00 01 ];
x = "/foo", "/foo", < 0x1 >;
phandle = < 0x1 >;
};
};
""")
@ -1899,7 +1907,7 @@ l1: l2: /memreserve/ 0x0000000000000002 0x0000000000000004;
/dts-v1/;
/ {
aA0,._+*#?- = [ 2F 61 41 30 2C 2E 5F 2B 2A 23 3F 40 2D 00 2F 61 41 30 2C 2E 5F 2B 2A 23 3F 40 2D 00 ];
aA0,._+*#?- = "/aA0,._+*#?@-", "/aA0,._+*#?@-";
+ = [ 00 ];
* = [ 02 ];
- = [ 01 ];
@ -1950,7 +1958,7 @@ l1: l2: /memreserve/ 0x0000000000000002 0x0000000000000004;
/ {
l1: l2: foo {
l3: l4: bar {
l5: x = [ l6: l7: 01 l8: 02 l9: 03 61 00 ];
l5: x = l6: [ l7: 01 l8: 02 l9: ], [ 03 ], "a";
};
};
};