indexing description: "Eiffel documentation generator." copyright: "Copyright (c) 2005, Julian Tschannen" license: "Eiffel Forum License v2 (see forum.txt)" date: "$Date$" revision: "$Revision$" class EDOC inherit ANY EDOC_SHARED_ACCESS export {NONE} all end KL_SHARED_ARGUMENTS export {NONE} all end KL_SHARED_EXCEPTIONS export {NONE} all end KL_SHARED_FILE_SYSTEM export {NONE} all end KL_SHARED_EXECUTION_ENVIRONMENT export {NONE} all end KL_SHARED_STANDARD_FILES export {NONE} all end create make feature {NONE} -- Initialization make is -- Execute 'edoc'. do Arguments.set_program_name ("edoc") if Arguments.argument_count = 0 then show_usage Error_handler.die (0) end -- Set verbose by default and set silent by option Error_handler.set_verbose (not has_option ('s')) Error_handler.report_message ("%Nedoc in verbose mode") Error_handler.report_message ("-------------------------") -- Select output format -- TODO: when multiple output formats are supported, select appropriate format create {EDOC_HTML_OUTPUT}edoc_output.make -- Load default options file select_default_options_directory load_options_file (file_system.pathname (default_options_directory, edoc_output.default_options_filename)) load_commandline_parameters check_options Error_handler.report_message ("%NParsing input files") if Options.ace_file /= Void then load_ace end if Options.xace_system /= Void then load_xace_system end if Options.xace_library /= Void then load_xace_library (Options.xace_library, True, True) end from Options.mounted_libraries.start until Options.mounted_libraries.after loop load_xace_library (Options.mounted_libraries.item_for_iteration, Options.are_mounted_libraries_included, False) Options.mounted_libraries.forth end if Error_handler.is_verbose then print_options end Context.set_output_generator (edoc_output) Context.generate_universe Context.parse_universe Context.generate_documentation rescue if Error_handler.is_file_output_enabled then Error_handler.print_to_error_log_file ("An unrecoverable error occured", True) end std.output.put_string ("An unrecoverable error occured%N") if not Error_handler.is_verbose then if Error_handler.last_error_message /= Void then std.output.put_string ("Last error is "+Error_handler.last_error_code.out+": "+Error_handler.last_error_message+"%N") else std.output.put_string ("Last error code is: '"+Error_handler.last_error_code.out+"'%N") end end show_usage -- 'die' so no stack trace is shown (which is useless anyway in finalized mode) Error_handler.die (1) end select_default_options_directory is -- Select directory with default options. local a_directory: STRING do Error_handler.report_message ("Searching options directory") -- 1. check environment variable a_directory := Execution_environment.variable_value ("EDOC") if a_directory = Void then Error_handler.report_message ("No environment variable 'EDOC' found. Checking current directory.") else a_directory := file_system.pathname (a_directory, "options") if not file_system.directory_exists (a_directory) then a_directory := Void Error_handler.report_message ("No 'options' directory found in 'EDOC' directory. Checking current directory.") end end if a_directory = Void then -- 2. check working directory a_directory := file_system.pathname (file_system.absolute_pathname (file_system.current_working_directory), "options") if not file_system.directory_exists (a_directory) then Error_handler.report_message ("No 'options' directory found in current directory. Checking Execution command.") -- 3. check execution command a_directory := file_system.pathname (file_system.dirname (file_system.absolute_pathname (Arguments.argument (0))), "options") if not file_system.directory_exists (a_directory) then Error_handler.report_message ("No 'options' directory found in '"+file_system.dirname (file_system.absolute_pathname (Arguments.argument (0)))+"'.") Error_handler.raise_error (Error_handler.Error_no_options_directory_found, Void) end end end create default_options_directory.make_from_string (a_directory) Error_handler.report_message ("Options directory '"+a_directory+"' selected") ensure directory_selected: default_options_directory /= Void directory_exists: file_system.directory_exists (default_options_directory) end load_options_file (a_filename: STRING) is -- Load options file. local an_options_file: EDOC_OPTIONS_FILE do an_options_file := edoc_output.options_file (a_filename) an_options_file.apply_options end load_commandline_parameters is -- Load commandline parameters. local an_option: STRING a_filename: STRING do if (has_option ('v') and Arguments.argument_count > 1) or (not has_option ('v') and Arguments.argument_count > 0) then an_option := Arguments.argument (1) if an_option.is_equal ("-v") then an_option := Arguments.argument (2) end a_filename := Execution_environment.interpreted_string (an_option) if file_system.file_exists (a_filename) then -- Check if xace or options file if file_system.has_extension (a_filename, "xace") then -- Load xace file -- TODO: check if library or system (this is a wild guess here...) if a_filename.has_substring ("library") then Options.set_xace_library (a_filename) else Options.set_xace_system (a_filename) end elseif file_system.has_extension (a_filename, "ace") then -- Load ace file Options.set_ace_file (a_filename) else -- Load options file load_options_file (a_filename) end else a_filename := file_system.pathname (default_options_directory, an_option+".options") if file_system.file_exists (a_filename) then load_options_file (a_filename) end end end end check_options is -- Check essential options if they are valid. local a_directory: KL_DIRECTORY do -- Check input files if Options.ace_file /= Void then if not file_system.file_exists (Options.ace_file) then Error_handler.raise_error (Error_handler.Error_ace_file_not_found, << Options.ace_file >>) end end if Options.xace_system /= Void then if not file_system.file_exists (Options.xace_system) then Error_handler.raise_error (Error_handler.Error_xace_file_not_found, << Options.xace_system >>) end end if Options.xace_library /= Void then if not file_system.file_exists (Options.xace_library) then Error_handler.raise_error (Error_handler.Error_xace_file_not_found, << Options.xace_library >>) end end if Options.ace_file = Void and Options.xace_system = Void and Options.xace_library = Void then Error_handler.raise_error (Error_handler.Error_no_input_file, Void) end from Options.mounted_libraries.start until Options.mounted_libraries.after loop if not file_system.file_exists (Options.mounted_libraries.item_for_iteration) then Error_handler.raise_warning (Error_handler.Error_mounted_xace_not_found, << Options.mounted_libraries.item_for_iteration >>) Options.mounted_libraries.remove_at end Options.mounted_libraries.forth end -- Check output directory create a_directory.make (Options.output_directory) if not a_directory.exists then a_directory.recursive_create_directory end if not a_directory.exists then Error_handler.raise_error (Error_handler.Error_create_output_directory, << Options.output_directory >>) end ensure ace_file_exists: Options.ace_file /= Void implies file_system.file_exists (Options.ace_file) xace_system_exists: Options.xace_system /= Void implies file_system.file_exists (Options.xace_system) xace_library_exists: Options.xace_library /= Void implies file_system.file_exists (Options.xace_library) output_directory_exists: file_system.directory_exists (Options.output_directory) end print_options is -- Print options to commandline do Error_handler.report_message ("%NInput options") if Options.ace_file /= Void then Error_handler.report_message ("Ace file: "+Options.ace_file) end if Options.xace_system /= Void then Error_handler.report_message ("XAce system: "+Options.xace_system) end if Options.xace_library /= Void then Error_handler.report_message ("XAce library: "+Options.xace_library) end from Options.mounted_libraries.start until Options.mounted_libraries.after loop Error_handler.report_message ("Mounted library: "+Options.mounted_libraries.item_for_iteration) Options.mounted_libraries.forth end if not Options.mounted_libraries.is_empty then Error_handler.report_message ("Mounted libraries inlcuded: "+boolean_to_string (Options.are_mounted_libraries_included)) end Error_handler.report_message ("Ignored clusters: "+list_to_string (Options.ignored_clusters)) Error_handler.report_message ("%NOutput options") Error_handler.report_message ("Output directory: "+Options.output_directory) Error_handler.report_message ("Flat output: "+boolean_to_string (Options.is_output_flat)) Error_handler.report_message ("Generate feature list: "+boolean_to_string (Options.is_feature_list_generated)) Error_handler.report_message ("Generate cluster files: "+boolean_to_string (Options.are_cluster_files_generated)) Error_handler.report_message ("Generate index files: "+boolean_to_string (Options.is_index_generated)) Error_handler.report_message ("Generate usage files: "+boolean_to_string (Options.are_usage_files_generated)) Error_handler.report_message ("%NParser options") Error_handler.report_message ("Flatten classes: "+boolean_to_string (Options.are_classes_flat)) Error_handler.report_message ("Ignored indexing tags: "+list_to_string (Options.ignored_indexing_tags)) Error_handler.report_message ("Ignore inherit exported NONE: "+boolean_to_string (Options.is_inherit_export_none_ignored)) Error_handler.report_message ("Ignored inherit classes: "+list_to_string (Options.ignored_inherit_classes)) Error_handler.report_message ("Ignore feature clauses exported to NONE: "+boolean_to_string (Options.is_feature_clause_export_none_ignored)) Error_handler.report_message ("Feature clause order: "+list_to_string (Options.feature_clause_order)) Error_handler.report_message ("Ignored feature clauses: "+list_to_string (Options.ignored_feature_clauses)) -- TODO: As soon as multiple output formats are supported this has to move to the corresponding EDOC_OUTPUT class Error_handler.report_message ("%NHTML options") Error_handler.report_message ("Title: "+Options.title) Error_handler.report_message ("Short title: "+Options.short_title) Error_handler.report_message ("Version: "+Options.version) Error_handler.report_message ("CSS file: "+Options.original_css_file) Error_handler.report_message ("") end load_ace is -- Load ace file. require ace_file_not_void: Options.ace_file /= Void ace_file_exists: file_system.file_exists (Options.ace_file) local lace_parser: ET_LACE_PARSER a_file: KL_TEXT_INPUT_FILE do create a_file.make (Options.ace_file) a_file.open_read if not a_file.is_open_read then Error_handler.raise_error (Error_handler.Error_ace_file_not_readable, << Options.ace_file >>) end create lace_parser.make_standard lace_parser.parse_file (a_file) if Options.title = Void then Options.set_title (Options.ace_file) end if Options.short_title = Void then Options.set_short_title (Options.ace_file) end if lace_parser.last_universe = Void then Error_handler.raise_error (Error_handler.Error_parsing_ace, << Options.ace_file >>) end Error_handler.report_message ("Done. "+lace_parser.last_universe.clusters.count.out+" clusters") Context.add_clusters (lace_parser.last_universe.clusters, True) end load_xace_system is -- Load xace system file. require xace_system_not_void: Options.xace_system /= Void xace_system_exists: file_system.file_exists (Options.xace_system) local xace_error_handler: ET_XACE_DEFAULT_ERROR_HANDLER xace_parser: ET_XACE_SYSTEM_PARSER a_file: KL_TEXT_INPUT_FILE i, nb: INTEGER do create a_file.make (Options.xace_system) a_file.open_read if not a_file.is_open_read then Error_handler.raise_error (Error_handler.Error_xace_file_not_readable, << Options.xace_system >>) end create xace_error_handler.make_standard create xace_parser.make (xace_error_handler) xace_parser.set_shallow (True) xace_parser.parse_file (a_file) if xace_error_handler.has_error then Error_handler.raise_error (Error_handler.Error_parsing_xace, << Options.xace_system >> ) end if Options.title = Void then Options.set_title (xace_parser.last_system.system_name) end if Options.short_title = Void then Options.set_short_title (xace_parser.last_system.system_name) end if xace_parser.last_system.clusters /= Void then Error_handler.report_message ("Done. "+xace_parser.last_system.clusters.count.out+" clusters") Context.add_clusters (xace_parser.last_system.clusters, True) else Error_handler.report_message ("Done. 0 new top-level clusters") end nb := xace_parser.last_system.libraries.libraries.count from i := 1 until i > nb loop Options.mounted_libraries.force_last (Execution_environment.interpreted_string (xace_parser.last_system.libraries.libraries.item (i).pathname)) i := i + 1 end end load_xace_library (a_filename: STRING; add_clusters: BOOLEAN; use_title: BOOLEAN) is -- Load xace library file. require a_filename_not_void: a_filename /= Void a_filename_exists: file_system.file_exists (a_filename) local xace_error_handler: ET_XACE_DEFAULT_ERROR_HANDLER xace_parser: ET_XACE_LIBRARY_PARSER a_file: KL_TEXT_INPUT_FILE do create a_file.make (a_filename) a_file.open_read if not a_file.is_open_read then Error_handler.raise_error (Error_handler.Error_xace_file_not_readable, << a_filename >>) end create xace_error_handler.make_standard create xace_parser.make_with_variables (xace_variables, xace_error_handler) Error_handler.report_message ("Parsing xace library '"+a_filename+"'") xace_parser.parse_file (a_file) if xace_error_handler.has_error then Error_handler.raise_error (Error_handler.Error_parsing_xace, << a_filename >> ) end if use_title then if Options.title = Void then Options.set_title (xace_parser.last_library.name) end if Options.short_title = Void then Options.set_short_title (xace_parser.last_library.name) end end if xace_parser.last_library.clusters /= Void then Error_handler.report_message ("Done. "+xace_parser.last_library.clusters.count.out+" clusters") Context.add_clusters (xace_parser.last_library.clusters, add_clusters) else Error_handler.report_message ("Done. 0 new top-level clusters") end end feature -- Access edoc_output: EDOC_OUTPUT -- Selected output type default_options_directory: STRING -- Directory with default options -- Normally '$EDOC/options' feature {NONE} -- Implementation has_option (a_character: CHARACTER): BOOLEAN is -- Is 'a_charater' in commandline options? local i: INTEGER do from i := 1 until i > Arguments.argument_count or Result loop if Arguments.argument (i).is_equal ("-"+a_character.out) then Result := True end i := i + 1 end end boolean_to_string (a_boolean: BOOLEAN): STRING is -- String of 'a_boolean'. do if a_boolean then Result := "Yes" else Result := "No" end end list_to_string (a_list: DS_LIST [ANY]): STRING is -- String of 'a_list'. do create Result.make (a_list.count*10) from a_list.start until a_list.after loop Result.append_string (a_list.item_for_iteration.out) a_list.forth if not a_list.after then Result.append_string (", ") end end end xace_variables: DS_HASH_TABLE [STRING, STRING] is -- Necessary environment variables for ET_XACE_PARSER local value: STRING once create Result.make_default value := Execution_environment.variable_value ("GOBO_EIFFEL") if value /= Void then Result.put (value, "GOBO_EIFFEL") end value := Execution_environment.variable_value ("GOBO_DOTNET") if value /= Void then Result.put (value, "GOBO_DOTNET") end value := Execution_environment.variable_value ("GOBO_EIFFELBASE") if value /= Void then Result.put (value, "GOBO_EIFFELBASE") end value := Execution_environment.variable_value ("ISE_EIFFEL") if value /= Void then Result.put (value, "ISE_EIFFEL") end end show_usage is -- Show tool usage. do std.output.put_string ("Usage: edoc [-s] {path_to_xace_file/path_to_options_file}%N") std.output.put_string (" -s: Show no output (silent)%N") std.output.put_string (" path_to_xace: Path to valid xace system or library file%N") std.output.put_string (" path_to_options_file: Path to valid EDoc options file%N") end end