Lines Matching +full:child +full:- +full:prop
2 # SPDX-License-Identifier: BSD-3-Clause
10 The top-level entry point of the library is the DT class. DT.__init__() takes a
30 "Exception raised for devicetree-related errors"
34 Represents a node in the devicetree ('node-name { ... };').
62 stored in big-endian format.
113 def name(self) -> str:
117 # Converted to a property to discourage renaming -- that has to be done
122 def unit_addr(self) -> str:
129 def path(self) -> str:
144 def node_iter(self) -> Iterable['Node']:
159 def _get_prop(self, name: str) -> 'Property':
163 prop = self.props.get(name)
164 if not prop:
165 prop = Property(self, name)
166 self.props[name] = prop
167 return prop
169 def _del(self) -> None:
188 for prop in self.props.values():
189 s += "\t" + str(prop) + "\n"
191 for child in self.nodes.values():
192 s += textwrap.indent(child.__str__(), "\t") + "\n"
245 big-endian format, and strings are null-terminated. Putting multiple
246 comma-separated values in an assignment (e.g., 'x = < 1 >, "foo"') will
257 ----------------------------+------------------------
329 def type(self) -> Type:
370 def to_num(self, signed=False) -> int:
391 def to_nums(self, signed=False) -> List[int]:
413 def to_bytes(self) -> bytes:
431 def to_string(self) -> str:
441 not valid UTF-8.
450 ret = self.value.decode("utf-8")[:-1] # Strip null
454 "is not valid UTF-8")
458 def to_strings(self) -> List[str]:
467 Also raises DTError if any of the strings are not valid UTF-8.
476 ret = self.value.decode("utf-8").split("\0")[:-1]
480 "is not valid UTF-8")
484 def to_node(self) -> Node:
501 def to_nodes(self) -> List[Node]:
529 def to_path(self) -> Node:
548 path = self.value.decode("utf-8")[:-1]
552 "is not valid UTF-8")
558 f"{self.node.dt.filename} points to the non-existent node "
571 if i < len(self._markers) - 1:
580 # end - 1 to strip off the null terminator
581 s += f' "{_decode_and_escape(self.value[pos:end - 1])}"'
719 (e.g., 'x = label_1: < 1 label2: 2 >;') to a (prop, offset) tuple, where
720 'prop' is a Property instance and 'offset' the byte offset (0 for label_1
780 def root(self) -> Node:
785 # treat self._root as a non-None value until it's initialized
789 def get_node(self, path: str) -> Node:
794 For example, both dt.get_node("/foo/bar") and dt.get_node("bar-alias")
797 /dts-v1/;
808 bar-alias = &bar-label;
813 dt.get_node("bar-alias/baz") returns the 'baz' node.
821 _err(f"no alias '{alias}' found -- did you forget the leading "
826 def has_node(self, path: str) -> bool:
883 def node_iter(self) -> Iterable[Node]:
901 s = "/dts-v1/;\n\n"
956 prop.name: Property(node_copy, prop.name)
957 for prop in node.props.values()
960 prop = node.props[prop_name]
961 prop_copy.value = prop.value
962 prop_copy.labels = prop.labels[:]
963 prop_copy.offset_labels = prop.offset_labels.copy()
964 prop_copy._label_offset_lst = prop._label_offset_lst[:]
965 prop_copy._markers = [marker[:] for marker in prop._markers]
996 for label, prop in self.label2prop.items():
997 node_copy = path2node_copy[prop.node.path]
998 prop_copy = node_copy.props[prop.name]
1004 prop, offset = prop_offset
1005 node_copy = path2node_copy[prop.node.path]
1006 prop_copy = node_copy.props[prop.name]
1026 with open(filename, encoding="utf-8") as f:
1048 # Parses /dts-v1/ (expected) and /plugin/ (unsupported) at the start of
1049 # files. There may be multiple /dts-v1/ at the start of a file.
1057 # /plugin/ always comes after /dts-v1/
1062 self._parse_error("expected '/dts-v1/;' at start of file")
1065 # Parses /memreserve/, which appears after /dts-v1/
1085 # Top-level parsing loop
1134 # Parses the '{ ... };' part of 'node-name { ... };'.
1136 # We need to track which child nodes were defined in this set
1151 child = node.nodes.get(tok.val)
1152 if child:
1153 if child.name in current_child_names:
1154 self._parse_error(f'{child.path}: duplicate node name')
1156 child = Node(name=tok.val, parent=node, dt=self)
1160 _append_no_dup(child.labels, label)
1163 child._omit_if_no_ref = True
1165 node.nodes[child.name] = child
1166 self._parse_node(child)
1173 "/omit-if-no-ref/ can only be used on nodes")
1175 prop = node._get_prop(tok.val)
1178 self._parse_assignment(prop)
1184 _append_no_dup(prop.labels, label)
1209 # _parse_node() helpers for parsing labels and /omit-if-no-ref/s before
1210 # nodes and properties. Returns a (<label list>, <omit-if-no-ref bool>)
1229 def _parse_assignment(self, prop): argument
1230 # Parses the right-hand side of property assignment
1232 # prop:
1235 # Remove any old value, path/phandle references, and in-value labels,
1237 prop.value = b""
1238 prop._markers = []
1242 self._parse_value_labels(prop)
1247 self._parse_cells(prop, 4)
1254 self._parse_cells(prop, n_bits//8)
1257 self._parse_bytes(prop)
1260 prop._add_marker(_MarkerType.STRING)
1261 prop.value += self._unescape(tok.val.encode("utf-8")) + b"\0"
1264 prop._add_marker(_MarkerType.PATH, tok.val)
1267 self._parse_incbin(prop)
1273 self._parse_value_labels(prop)
1282 def _parse_cells(self, prop, n_bytes): argument
1285 prop._add_marker(_N_BYTES_TO_TYPE[n_bytes])
1293 "arrays with 32-bit elements")
1294 prop._add_marker(_MarkerType.PHANDLE, tok.val)
1297 prop._add_marker(_MarkerType.LABEL, tok.val)
1307 prop.value += num.to_bytes(n_bytes, "big")
1311 prop.value += num.to_bytes(n_bytes, "big", signed=True)
1316 def _parse_bytes(self, prop): argument
1319 prop._add_marker(_MarkerType.UINT8)
1324 prop.value += tok.val.to_bytes(1, "big")
1327 prop._add_marker(_MarkerType.LABEL, tok.val)
1333 self._parse_error("expected two-digit byte or ']'")
1335 def _parse_incbin(self, prop): argument
1344 prop._add_marker(_MarkerType.UINT8)
1367 prop.value += f.read()
1370 prop.value += f.read(size)
1374 def _parse_value_labels(self, prop): argument
1376 # comma-separated value
1382 prop._add_marker(_MarkerType.LABEL, tok.val)
1388 # self-referential phandles (which get set to b'\0\0\0\0' initially).
1389 # Self-referential phandles must be rewritten instead of recreated, so
1502 elif self._check_token("-"):
1503 val -= self._eval_mul()
1526 if self._check_token("-"):
1527 return -self._eval_unary()
1562 val = self._unescape(match.group(tok_id).encode("utf-8"))
1621 filename = tok_val[tok_val.find('"') + 1:-1]
1627 self._lineno = int(tok_val.split()[0]) - 1
1628 self.filename = tok_val[tok_val.find('"') + 1:-1]
1672 # returns -1
1673 column = self._tok_i - self._file_contents.rfind("\n", 0,
1687 filename = self._unescape(filename.encode("utf-8"))
1689 filename = filename.decode("utf-8")
1691 self._parse_error("filename is not valid UTF-8")
1693 with self._open(filename, encoding="utf-8") as f:
1702 self._parse_error("recursive /include/:\n" + " ->\n".join(
1736 path = s[1:-1]
1753 # Post-processing
1757 # Registers any manually-inserted phandle properties in
1810 for prop in tuple(node.props.values()):
1816 for marker in prop._markers:
1821 res += prop.value[prev_pos:pos]
1831 # duplicate references. prop._label_offset_lst is changed
1834 _append_no_dup(prop._label_offset_lst, (ref, len(res)))
1840 _err(f"{prop.node.path}: {e}")
1842 # For /omit-if-no-ref/
1846 res += ref_node.path.encode("utf-8") + b'\0'
1854 # Store the final fixed-up value. Add the data after the last
1856 prop.value = res + prop.value[prev_pos:]
1866 alias_re = re.compile("[0-9a-z-]+$")
1870 for prop in aliases.props.values():
1871 if not alias_re.match(prop.name):
1872 _err(f"/aliases: alias property name '{prop.name}' "
1873 "should include only characters from [0-9a-z-]")
1879 alias2node[prop.name] = prop.to_path()
1888 # Removes any unreferenced nodes marked with /omit-if-no-ref/ from the
1909 for prop in node.props.values():
1910 for label in prop.labels:
1911 label2things[label].add(prop)
1912 self.label2prop[label] = prop
1914 for label, offset in prop._label_offset_lst:
1915 label2things[label].add((prop, offset))
1916 self.label2prop_offset[label] = (prop, offset)
1919 prop.offset_labels = dict(prop._label_offset_lst)
1948 # the string level, because the result might not be valid UTF-8 when
1972 # Return <char> as-is for other \<char>
1982 # The C tools support specifying stdin with '-' too
1983 if filename == "-":
2010 signed: bool = False) -> int:
2013 in big-endian format, which is standard in devicetree.
2030 def to_nums(data: bytes, length: int = 4, signed: bool = False) -> List[int]:
2033 are assumed to be in big-endian format, which is standard in devicetree.
2065 # Decodes the 'bytes' array 'b' as UTF-8 and backslash-escapes special
2068 # Hacky but robust way to avoid double-escaping any '\' spit out by
2072 return (b.decode("utf-8", "surrogateescape")
2074 .encode("utf-8", "surrogateescape")
2075 .decode("utf-8", "backslashreplace"))
2096 def _err(msg) -> NoReturn:
2115 _num_re = re.compile(r"(0[xX][0-9a-fA-F]+|[0-9]+)(?:ULL|UL|LL|U|L)?")
2119 _propnodename_re = re.compile(r"\\?([a-zA-Z0-9,._+*#?@-]+)")
2122 _nodename_chars = set(string.ascii_letters + string.digits + ',._+-@')
2128 "==", "!=", "!", "=", ",", ";", "+", "-", "*", "/", "%", "~", "?", ":",
2132 _byte_re = re.compile(r"[0-9a-fA-F]{2}")
2136 _unescape_re = re.compile(br'\\([0-7]{1,3}|x[0-9A-Fa-f]{1,2}|.)')
2150 r'^#(?:line)?[ \t]+([0-9]+[ \t]+"(?:[^\\"]|\\.)*")(?:[ \t]+[0-9]+){0,4}',
2153 _T.DTS_V1: r"(/dts-v1/)",
2157 _T.DEL_PROP: r"(/delete-property/)",
2158 _T.DEL_NODE: r"(/delete-node/)",
2159 _T.OMIT_IF_NO_REF: r"(/omit-if-no-ref/)",
2160 _T.LABEL: r"([a-zA-Z_][a-zA-Z0-9_]*):",
2162 _T.REF: r"&([a-zA-Z_][a-zA-Z0-9_]*|{[a-zA-Z0-9,._+*#?@/-]*})",
2166 # Return a token for end-of-file so that the parsing code can