diff --git a/repos/os/run/rom_filter.run b/repos/os/run/rom_filter.run index 2d25e48879..a8b2d5cbef 100644 --- a/repos/os/run/rom_filter.run +++ b/repos/os/run/rom_filter.run @@ -53,7 +53,12 @@ append config { - + +
+ + +
+
@@ -70,22 +75,23 @@ append config { + + + + + + + + + - + - + - - - - - - - - - + @@ -130,10 +136,10 @@ compare_output_to { [init -> rom_logger] ROM 'generated': [init -> rom_logger] [init -> rom_logger] ROM 'generated': -[init -> rom_logger] -[init -> rom_logger] ROM 'generated': -[init -> rom_logger] -[init -> rom_logger] ROM 'generated': [init -> rom_logger] +[init -> rom_logger] ROM 'generated': +[init -> rom_logger] +[init -> rom_logger] ROM 'generated': +[init -> rom_logger] } diff --git a/repos/os/src/server/rom_filter/README b/repos/os/src/server/rom_filter/README index 07fbe10aa3..db4d559657 100644 --- a/repos/os/src/server/rom_filter/README +++ b/repos/os/src/server/rom_filter/README @@ -10,12 +10,17 @@ Configuration The configuration consists of two parts. The first part is the declaration of input values that are taken into the account. The input values are obtained -from ROM modules that contain XML-formatted data. Each input value is -represented by an '' node with a unique 'name' attribute. The 'rom' -attribute specifies the ROM module to take the input from. If not specified, -the 'name' is used as the ROM name. The type of the top-level XML node can be -specified via the 'node' attribute. If not present, the top-level XML node is -expected to correspond to the 'name' attribute. +from ROM modules that contain XML-formatted data. + +Each input value is represented by an '' node with a unique 'name' +attribute. The 'rom' attribute specifies the ROM module to take the input +from. If not specified, the 'name' is used as the ROM name. The type of the +top-level XML node can be specified via the 'node' attribute. If not present, +the top-level XML node is expected to correspond to the 'name' attribute. +The '' node may contain a hierarchy of '' nodes that +denote a path within the XML input. If specified, the optional attributes +'attribute' and 'value' constrain the selection of the input depending of the +presence and the value of the specified attribute. The second part of the configuration defines the output via an '' node. The type of the top-level XML node must be specified via the 'node' attribute. diff --git a/repos/os/src/server/rom_filter/input_rom_registry.h b/repos/os/src/server/rom_filter/input_rom_registry.h index a3c89832f3..43eb0cc1d9 100644 --- a/repos/os/src/server/rom_filter/input_rom_registry.h +++ b/repos/os/src/server/rom_filter/input_rom_registry.h @@ -88,6 +88,47 @@ class Rom_filter::Input_rom_registry Genode::Signal_handler _rom_changed_handler = { _env.ep(), *this, &Entry::_handle_rom_changed }; + /** + * Return sub node of 'content' according to the constraints + * given by 'path' + * + * \throw Xml_node::Nonexistent_sub_node + */ + static Xml_node _matching_sub_node(Node_type_name type, + Xml_node const &path, + Xml_node const &content) + { + typedef Input_value Attribute_value; + + Xml_node sub_node = content.sub_node(type.string()); + + Attribute_name const expected_attr = + path.attribute_value("attribute", Attribute_name()); + + Attribute_value const expected_value = + path.attribute_value("value", Attribute_value()); + + for (;; sub_node = sub_node.next(type.string())) { + + /* attribute remains unspecified -> match */ + if (!expected_attr.valid()) + return sub_node; + + /* value remains unspecified -> match */ + if (!expected_value.valid()) + return sub_node; + + Attribute_value const present_value = + sub_node.attribute_value(expected_attr.string(), + Attribute_value()); + + if (present_value == expected_value) + return sub_node; + } + + throw Xml_node::Nonexistent_sub_node(); + } + /** * Query value from XML-structured ROM content * @@ -122,8 +163,12 @@ class Rom_filter::Input_rom_registry Node_type_name const sub_node_type = path.attribute_value("type", Node_type_name("")); - content = content.sub_node(sub_node_type.string()); - path = path.sub_node(); + try { + content = _matching_sub_node(sub_node_type, path, content); + path = path.sub_node(); + } + catch (Xml_node::Nonexistent_sub_node) { + throw Nonexistent_input_value(); } continue; }