indexing description: "Generate a text representation of the configuration in xml." legal: "See notice at end of class." status: "See notice at end of class." date: "$Date$" revision: "$Revision$" class CONF_PRINT_VISITOR inherit CONF_ITERATOR redefine process_system, process_target, process_assembly, process_library, process_precompile, process_cluster, process_override end CONF_VALIDITY CONF_FILE_CONSTANTS CONF_ACCESS create make feature {NONE} -- Initialization make is -- Create. do end feature -- Access text: STRING -- The text output. feature -- Visit nodes process_system (a_system: CONF_SYSTEM) is -- Visit `a_system'. local l_target: CONF_TARGET do create text.make_from_string (header) append_text_indent ("%N") indent := indent + 1 append_description_tag (a_system.description) Precursor (a_system) indent := indent - 1 append_text_indent ("%N") ensure then indent_back: indent = old indent end process_target (a_target: CONF_TARGET) is -- Visit `a_target'. local l_root: CONF_ROOT l_version: CONF_VERSION l_settings, l_variables: HASH_TABLE [STRING, STRING] l_a_name, l_a_val: ARRAYED_LIST [STRING] l_sort_lst: DS_ARRAYED_LIST [STRING] do current_target := a_target append_text_indent ("%N") indent := indent + 1 append_description_tag (a_target.description) l_root := a_target.internal_root if l_root /= Void then create l_a_name.make (4) create l_a_val.make (4) if l_root.is_all_root then l_a_name.force ("all_classes") l_a_val.force (l_root.is_all_root.out.as_lower) else l_a_name.force ("cluster") l_a_val.force (l_root.cluster_name) l_a_name.force ("class") l_a_val.force (l_root.class_name) l_a_name.force ("feature") l_a_val.force (l_root.feature_name) end append_tag ("root", Void, l_a_name, l_a_val) end l_version := a_target.internal_version if l_version /= Void then create l_a_name.make (8) create l_a_val.make (8) l_a_name.force ("major") l_a_val.force (l_version.major.out) l_a_name.force ("minor") l_a_val.force (l_version.minor.out) l_a_name.force ("release") l_a_val.force (l_version.release.out) l_a_name.force ("build") l_a_val.force (l_version.build.out) l_a_name.force ("company") l_a_val.force (l_version.company) l_a_name.force ("product") l_a_val.force (l_version.product) l_a_name.force ("trademark") l_a_val.force (l_version.trademark) l_a_name.force ("copyright") l_a_val.force (l_version.copyright) append_tag ("version", Void, l_a_name, l_a_val) end append_file_rule (a_target.internal_file_rule) append_options (a_target.internal_options, Void) from l_settings := a_target.internal_settings create l_sort_lst.make_from_array (l_settings.current_keys) l_sort_lst.sort (create {DS_QUICK_SORTER [STRING]}.make (create {KL_COMPARABLE_COMPARATOR [STRING]}.make)) l_sort_lst.start until l_sort_lst.after loop create l_a_name.make (2) l_a_name.force ("name") l_a_name.force ("value") create l_a_val.make (1) l_a_val.force (l_sort_lst.item_for_iteration) l_a_val.force (l_settings.item (l_sort_lst.item_for_iteration)) append_tag ("setting", Void, l_a_name, l_a_val) l_sort_lst.forth end append_mapping (a_target.internal_mapping) append_externals (a_target.internal_external_include, "include") append_externals (a_target.internal_external_object, "object") append_externals (a_target.internal_external_library, "library") append_externals (a_target.internal_external_resource, "resource") append_externals (a_target.internal_external_make, "make") append_actions (a_target.internal_pre_compile_action, "pre") append_actions (a_target.internal_post_compile_action, "post") from l_variables := a_target.internal_variables l_variables.start until l_variables.after loop create l_a_name.make (2) l_a_name.force ("name") l_a_name.force ("value") create l_a_val.make (1) l_a_val.force (l_variables.key_for_iteration) l_a_val.force (l_variables.item_for_iteration) append_tag ("variable", Void, l_a_name, l_a_val) l_variables.forth end if a_target.internal_precompile /= Void then a_target.internal_precompile.process (Current) end process_in_alphabetic_order (a_target.internal_libraries) process_in_alphabetic_order (a_target.internal_assemblies) process_in_alphabetic_order (a_target.internal_clusters) process_in_alphabetic_order (a_target.internal_overrides) indent := indent - 1 append_text_indent ("%N") ensure then indent_back: indent = old indent end process_assembly (an_assembly: CONF_ASSEMBLY) is -- Visit `an_assembly'. local l_str: STRING l_p: STRING do l_p := an_assembly.location.original_path append_pre_group ("assembly", an_assembly) if l_p.is_empty then l_str := an_assembly.assembly_name if l_str /= Void and then not l_str.is_empty then append_text (" assembly_name=%""+escape_xml (l_str)+"%"") end l_str := an_assembly.assembly_version if l_str /= Void and then not l_str.is_empty then append_text (" assembly_version=%""+escape_xml (l_str)+"%"") end l_str := an_assembly.assembly_culture if l_str /= Void and then not l_str.is_empty then append_text (" assembly_culture=%""+escape_xml (l_str)+"%"") end l_str := an_assembly.assembly_public_key_token if l_str /= Void and then not l_str.is_empty then append_text (" assembly_key=%""+escape_xml (l_str)+"%"") end end append_val_group (an_assembly) append_post_group ("assembly") ensure then indent_back: indent = old indent end process_library (a_library: CONF_LIBRARY) is -- Visit `a_library'. do append_pre_group ("library", a_library) append_val_group (a_library) if a_library.visible /= Void then append_visible (a_library.visible) end append_post_group ("library") ensure then indent_back: indent = old indent end process_precompile (a_precompile: CONF_PRECOMPILE) is -- Visit `a_precompile'. do append_pre_group ("precompile", a_precompile) if a_precompile.eifgens_location /= Void then append_text (" eifgens_location=%""+a_precompile.eifgens_location.original_directory+"%"") end append_val_group (a_precompile) append_post_group ("precompile") ensure then indent_back: indent = old indent end process_cluster (a_cluster: CONF_CLUSTER) is -- Visit `a_cluster'. do -- ignore subclusters, except if we are handling one. if a_cluster.parent = Void or current_is_subcluster then current_is_subcluster := False append_pre_group ("cluster", a_cluster) append_attr_cluster (a_cluster) append_val_group (a_cluster) append_val_cluster (a_cluster) append_post_group ("cluster") end ensure then indent_back: indent = old indent end process_override (an_override: CONF_OVERRIDE) is -- Visit `an_override'. local l_overrides: ARRAYED_LIST [CONF_GROUP] do -- ignore subclusters, except if we are handling one. if an_override.parent = Void or current_is_subcluster then current_is_subcluster := False append_pre_group ("override", an_override) append_attr_cluster (an_override) append_val_group (an_override) append_val_cluster (an_override) l_overrides := an_override.override if l_overrides /= Void then from l_overrides.start until l_overrides.after loop append_text_indent ("%N") l_overrides.forth end end append_post_group ("override") end ensure then indent_back: indent = old indent end feature {NONE} -- Implementation indent: INTEGER -- The indentation level. last_count: INTEGER -- A helper counter, that is used to see if something was added. current_target: CONF_TARGET -- The target we are currently processing. current_is_subcluster: BOOLEAN -- Is the current cluster/override a subcluster? process_in_alphabetic_order (a_groups: HASH_TABLE [CONF_GROUP, STRING]) is -- Process `a_groups' in alphabetic order corresponding to their key. require a_groups_not_void: a_groups /= Void local l_sort_lst: DS_ARRAYED_LIST [STRING] do from create l_sort_lst.make_from_array (a_groups.current_keys) l_sort_lst.sort (create {DS_QUICK_SORTER [STRING]}.make (create {KL_COMPARABLE_COMPARATOR [STRING]}.make)) l_sort_lst.start until l_sort_lst.after loop a_groups.item (l_sort_lst.item_for_iteration).process (Current) l_sort_lst.forth end end escape_xml (a_string: STRING): STRING is -- Escape xml entities in `a_string'. do if a_string /= Void then Result := a_string.twin Result.replace_substring_all (Amp_string, amp_entity) Result.replace_substring_all (Lt_string, Lt_entity) Result.replace_substring_all (Gt_string, Gt_entity) Result.replace_substring_all (Quot_string, quot_entity) end ensure result_void_iff_a_string_void: (Result = Void) = (a_string = Void) end append_tag (a_name, a_value: STRING; an_attribute_names, an_attribute_values: ARRAYED_LIST [STRING]) is -- Append a tag with `a_name', `a_value' and `an_attributes' to `text', intendend it with `indent' tabs. require a_name_ok: a_name /= Void and then not a_name.is_empty attributes_same_count: (an_attribute_names = Void and an_attribute_values = Void) or else (an_attribute_names /= Void and an_attribute_values /= Void and then an_attribute_names.count = an_attribute_values.count) local l_val: STRING do append_text_indent ("<"+a_name) if an_attribute_names /= Void and then not an_attribute_names.is_empty then from an_attribute_names.start an_attribute_values.start until an_attribute_names.after loop l_val := an_attribute_values.item if l_val /= Void and then not l_val.is_empty then append_text (" "+an_attribute_names.item) append_text ("=%""+escape_xml (l_val)+"%"") end an_attribute_names.forth an_attribute_values.forth end end if a_value /= Void and not a_value.is_empty then append_text (">"+escape_xml (a_value)+"%N") else append_text ("/>%N") end end append_text_indent (a_text: STRING) is -- Append `a_text' at the current `indent' intendation level. require a_text_ok: a_text /= Void and then not a_text.is_empty local i: INTEGER do from i := 1 until i > indent loop text.append_character ('%T') i := i + 1 end text.append (a_text) end append_text (a_text: STRING) is -- Append `a_text'. require a_text_not_void: a_text /= Void and then not a_text.is_empty do text.append (a_text) end append_description_tag (a_description: STRING) is -- Append `a_description'. do if a_description /= Void and then not a_description.is_empty then append_tag ("description", a_description, Void, Void) end end append_conditionals (a_conditions: ARRAYED_LIST [CONF_CONDITION]; is_assembly: BOOLEAN) is -- Append `a_conditions' ignore platform if it `is_assembly'. local l_condition: CONF_CONDITION l_done: BOOLEAN l_platforms, l_builds: ARRAYED_LIST [INTEGER] l_custs: HASH_TABLE [TUPLE [value: STRING; invert: BOOLEAN], STRING] l_custom: TUPLE [value: STRING; invert: BOOLEAN] l_versions: HASH_TABLE [TUPLE [min: CONF_VERSION; max: CONF_VERSION], STRING] l_name: STRING l_ver: TUPLE [min: CONF_VERSION; max: CONF_VERSION] do if a_conditions /= Void then -- assembly and only the default rule? => don't print it if is_assembly and then a_conditions.count = 1 then l_condition := a_conditions.first l_done := l_condition.build = Void and l_condition.platform = Void and l_condition.multithreaded = Void and l_condition.version.is_empty and l_condition.custom.is_empty end if not l_done then from a_conditions.start until a_conditions.after loop append_text_indent ("%N") indent := indent + 1 l_condition := a_conditions.item if l_condition.platform /= Void then if l_condition.platform.invert then append_text_indent ("%N") end if l_condition.build /= Void then if l_condition.build.invert then append_text_indent ("%N") end if l_condition.multithreaded /= Void then append_text_indent ("%N") end if l_condition.dynamic_runtime /= Void then append_text_indent ("%N") end -- don't print dotnet for assemblies if not is_assembly and then l_condition.dotnet /= Void then append_text_indent ("%N") end from l_versions := l_condition.version l_versions.start until l_versions.after loop l_ver := l_versions.item_for_iteration append_text_indent ("%N") l_versions.forth end from l_custs := l_condition.custom l_custs.start until l_custs.after loop l_custom := l_custs.item_for_iteration if l_custom.invert then l_name := "excluded_value" else l_name := "value" end append_text_indent ("%N") l_custs.forth end indent := indent - 1 append_text_indent ("%N") a_conditions.forth end end end ensure indent_back: indent = old indent end append_mapping (a_mapping: EQUALITY_HASH_TABLE [STRING, STRING]) is -- Append `a_mapping'. do if a_mapping /= Void then from a_mapping.start until a_mapping.after loop append_text_indent ("%N") a_mapping.forth end end end append_externals (an_externals: ARRAYED_LIST [CONF_EXTERNAL]; a_name: STRING) is -- Append `an_externals'. require an_externals_not_void: an_externals /= Void a_name_ok: a_name /= Void and then not a_name.is_empty local l_ext: CONF_EXTERNAL l_desc: STRING do if not an_externals.is_empty then from an_externals.start until an_externals.after loop l_ext := an_externals.item append_text_indent ("%N") indent := indent + 1 last_count := text.count l_desc := l_ext.description if l_desc /= Void and not l_desc.is_empty then append_tag ("description", l_desc, Void, Void) end append_conditionals (l_ext.internal_conditions, False) indent := indent - 1 if text.count = last_count then text.insert_character ('/', last_count-1) else append_text_indent ("%N") end an_externals.forth end end end append_actions (an_actions: ARRAYED_LIST [CONF_ACTION]; a_name: STRING) is -- Append `an_actions'. require an_actions_not_void: an_actions /= Void a_nam_ok: a_name /= Void and then not a_name.is_empty local l_action: CONF_ACTION do from an_actions.start until an_actions.after loop l_action := an_actions.item append_text_indent ("<"+a_name+"_compile_action") if l_action.working_directory /= Void then append_text (" working_directory=%""+escape_xml (l_action.working_directory.original_path)+"%"") end append_text (" command=%""+escape_xml (l_action.command)+"%">%N") indent := indent + 1 append_description_tag (l_action.description) append_conditionals (l_action.internal_conditions, False) indent := indent - 1 append_text_indent ("%N") an_actions.forth end end append_file_rule (a_file_rules: ARRAYED_LIST [CONF_FILE_RULE]) is -- Append `a_file_rule' local l_pattern: LINKED_SET [STRING] l_rule: CONF_FILE_RULE do from a_file_rules.start until a_file_rules.after loop l_rule := a_file_rules.item if not l_rule.is_empty then append_text_indent ("%N") indent := indent + 1 append_description_tag (l_rule.description) l_pattern := l_rule.exclude if l_pattern /= Void then from l_pattern.start until l_pattern.after loop append_tag ("exclude", l_pattern.item, Void, Void) l_pattern.forth end end l_pattern := l_rule.include if l_pattern /= Void then from l_pattern.start until l_pattern.after loop append_tag ("include", l_pattern.item, Void, Void) l_pattern.forth end end append_conditionals (l_rule.internal_conditions, False) indent := indent - 1 append_text_indent ("%N") end a_file_rules.forth end end append_options (an_options: CONF_OPTION; a_class: STRING) is -- Append `an_options', optionally for `a_class'. local l_str: STRING l_debugs, l_warnings: HASH_TABLE [BOOLEAN, STRING] l_assertions: CONF_ASSERTIONS l_a_name, l_a_val: ARRAYED_LIST [STRING] l_sort_lst: DS_ARRAYED_LIST [STRING] do if an_options /= Void and then not an_options.is_empty then if a_class /= Void and then not a_class.is_empty then append_text_indent ("%N") indent := indent + 1 append_description_tag (an_options.description) l_debugs := an_options.debugs if l_debugs /= Void and then not l_debugs.is_empty then create l_sort_lst.make_from_array (l_debugs.current_keys) l_sort_lst.sort (create {DS_QUICK_SORTER [STRING]}.make (create {KL_COMPARABLE_COMPARATOR [STRING]}.make)) from l_sort_lst.start until l_sort_lst.after loop append_text_indent ("%N") l_sort_lst.forth end end l_assertions := an_options.assertions if l_assertions /= Void then create l_a_name.make (5) l_a_name.extend ("precondition") l_a_name.extend ("postcondition") l_a_name.extend ("check") l_a_name.extend ("invariant") l_a_name.extend ("loop") create l_a_val.make (5) l_a_val.extend (l_assertions.is_precondition.out.as_lower) l_a_val.extend (l_assertions.is_postcondition.out.as_lower) l_a_val.extend (l_assertions.is_check.out.as_lower) l_a_val.extend (l_assertions.is_invariant.out.as_lower) l_a_val.extend (l_assertions.is_loop.out.as_lower) append_tag ("assertions", Void, l_a_name, l_a_val) end l_warnings := an_options.warnings if l_warnings /= Void and then not l_warnings.is_empty then create l_sort_lst.make_from_array (l_warnings.current_keys) l_sort_lst.sort (create {DS_QUICK_SORTER [STRING]}.make (create {KL_COMPARABLE_COMPARATOR [STRING]}.make)) from l_sort_lst.start until l_sort_lst.after loop append_text_indent ("%N") l_sort_lst.forth end end indent := indent - 1 if a_class /= Void and then not a_class.is_empty then append_text_indent ("%N") else append_text_indent ("%N") end end end append_visible (a_visible: EQUALITY_HASH_TABLE [TUPLE [class_renamed: STRING; features: EQUALITY_HASH_TABLE [STRING, STRING]], STRING]) is -- Append visible rules. require a_visible_not_void: a_visible /= Void local l_vis_feat: EQUALITY_HASH_TABLE [STRING, STRING] l_class: STRING l_feat, l_feat_rename, l_class_rename: STRING do from a_visible.start until a_visible.after loop l_class := a_visible.key_for_iteration l_class_rename := a_visible.item_for_iteration.class_renamed l_vis_feat := a_visible.item_for_iteration.features if l_vis_feat /= Void then from l_vis_feat.start until l_vis_feat.after loop l_feat := l_vis_feat.key_for_iteration l_feat_rename := l_vis_feat.item_for_iteration if l_feat.is_equal ("*") then l_feat := Void end append_text_indent ("%N") l_vis_feat.forth end else append_text_indent ("%N") end a_visible.forth end end append_pre_group (a_tag: STRING; a_group: CONF_GROUP) is -- Append the things that start the entry for `a_group' require a_group_not_void: a_group /= Void a_tag_ok: a_tag /= Void and then not a_tag.is_empty local l_str: STRING do l_str := a_group.location.original_path if l_str.is_empty then l_str := "none" end append_text_indent ("<"+a_tag+" name=%""+escape_xml (a_group.name)+"%"") append_text (" location=%""+escape_xml (l_str)+"%"") if not a_group.is_library and a_group.internal_read_only then append_text (" readonly=%"true%"") elseif a_group.is_library and a_group.is_readonly_set then append_text (" readonly=%""+a_group.is_readonly.out.as_lower+"%"") end l_str := a_group.name_prefix if l_str /= Void and then not l_str.is_empty then append_text (" prefix=%""+escape_xml (l_str)+"%"") end end append_val_group (a_group: CONF_GROUP) is -- Append the things that come in the value part of `a_group'. require a_group_not_void: a_group /= Void local l_renaming: HASH_TABLE [STRING, STRING] l_c_opt: HASH_TABLE [CONF_OPTION, STRING] do append_text (">%N") indent := indent + 1 last_count := text.count append_description_tag (a_group.description) append_conditionals (a_group.internal_conditions, a_group.is_assembly) append_options (a_group.internal_options, Void) l_renaming := a_group.renaming if l_renaming /= Void then from l_renaming.start until l_renaming.after loop append_text_indent ("%N") l_renaming.forth end end l_c_opt := a_group.internal_class_options if l_c_opt /= Void then from l_c_opt.start until l_c_opt.after loop append_options (l_c_opt.item_for_iteration, l_c_opt.key_for_iteration) l_c_opt.forth end end end append_post_group (a_tag: STRING) is -- Finish the the tag for the group. require a_tag_ok: a_tag /= Void and then not a_tag.is_empty do -- we didn't add anything further => change to a single tag. indent := indent - 1 if text.count = last_count then text.insert_character ('/', last_count-1) else append_text_indent ("%N") end end append_attr_cluster (a_cluster: CONF_CLUSTER) is -- Append the attributes for `a_cluster'. require a_cluster_not_void: a_cluster /= Void do if a_cluster.is_recursive then append_text (" recursive=%"true%"") end end append_val_cluster (a_cluster: CONF_CLUSTER) is -- Append the values for `a_cluster'. require a_cluster_not_void: a_cluster /= Void local l_deps: DS_HASH_SET [CONF_GROUP] l_visible: EQUALITY_HASH_TABLE [TUPLE [STRING, EQUALITY_HASH_TABLE [STRING, STRING]], STRING] l_clusters: HASH_TABLE [CONF_CLUSTER, STRING] l_cluster: CONF_CLUSTER l_name: STRING l_sort_lst: DS_ARRAYED_LIST [STRING] do append_file_rule (a_cluster.internal_file_rule) append_mapping (a_cluster.internal_mapping) l_deps := a_cluster.internal_dependencies if l_deps /= Void then from l_deps.start until l_deps.after loop append_text_indent ("%N") l_deps.forth end end l_visible := a_cluster.visible if l_visible /= Void then append_visible (l_visible) end -- look for subclusters from l_name := a_cluster.name l_clusters := current_target.internal_clusters.twin create l_sort_lst.make_from_array (l_clusters.current_keys) l_sort_lst.sort (create {DS_QUICK_SORTER [STRING]}.make (create {KL_COMPARABLE_COMPARATOR [STRING]}.make)) l_sort_lst.start until l_sort_lst.after loop l_cluster := l_clusters.item (l_sort_lst.item_for_iteration) if l_cluster.parent /= Void and then l_cluster.parent.name.is_equal (l_name) then current_is_subcluster := True l_cluster.process (Current) end l_sort_lst.forth end end indexing copyright: "Copyright (c) 1984-2006, Eiffel Software" license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" licensing_options: "http://www.eiffel.com/licensing" copying: "[ This file is part of Eiffel Software's Eiffel Development Environment. Eiffel Software's Eiffel Development Environment is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License (available at the URL listed under "license" above). Eiffel Software's Eiffel Development Environment is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eiffel Software's Eiffel Development Environment; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ]" source: "[ Eiffel Software 356 Storke Road, Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end