note description: "Objects that describe a directory containing C code to merge into a single file" legal: "See notice at end of class." status: "See notice at end of class." author: "Mark Howard, AxaRosenberg - revision 1.12 by Arnaud PICHERY, ISE" date: "$Date$" revision: "$Revision$" class EIFFEL_F_CODE_DIRECTORY inherit DIRECTORY rename make as directory_make end OPERATING_ENVIRONMENT create make feature {NONE} -- Initialization make (a_path: STRING; extension_type: STRING; a_is_root: BOOLEAN) -- Create new EIFFEL_F_CODE_DIRECTORY. require a_path_not_void: a_path /= Void extension_type_not_void: extension_type /= Void local l_files: ARRAYED_LIST [STRING] l_shortname, l_fname, tag: STRING l_file: RAW_FILE l_directory: EIFFEL_F_CODE_DIRECTORY l_start, l_count: INTEGER finished_file: PLAIN_TEXT_FILE finished_file_name: FILE_NAME do is_root := a_is_root -- Create `l_big_file_name' with a number as a suffix, in order not to -- confuse the C debugger. l_start := a_path.last_index_of (Directory_separator, a_path.count) tag := a_path.substring (l_start + 1, a_path.count) big_file_name_prefix := big_file_prefix + tag directory_make (a_path) object_extension := extension_type.twin -- Check if we modified something in the directory -- True if the file `finished' does not exist. create finished_file_name.make_from_string (a_path) finished_file_name.set_file_name ("finished") create finished_file.make (finished_file_name) has_finished_file := finished_file.exists -- Clean up previous conversion if really needed. if not is_root and then not has_finished_file then l_fname := path_name (big_file_name (False, False, False)) create l_file.make (l_fname) if l_file.exists then l_file.delete end l_fname := path_name (big_file_name (False, False, True)) create l_file.make (l_fname) if l_file.exists then l_file.delete end l_fname := path_name (big_file_name (False, True, False)) create l_file.make (l_fname) if l_file.exists then l_file.delete end l_fname := path_name (big_file_name (False, True, True)) create l_file.make (l_fname) if l_file.exists then l_file.delete end end create x_files.make (100) create xpp_files.make (100) create c_files.make (100) create cpp_files.make (100) create directories.make (100) l_files := linear_representation from l_files.start until l_files.off loop if not l_files.item.is_equal (".") and not l_files.item.is_equal ("..") then l_fname := path_name (l_files.item) create l_file.make (l_fname) if l_file.is_directory and then (l_fname.count < 2 or else not l_fname.substring (l_fname.count -1, l_fname.count).is_equal (once "E1")) then create l_directory.make (l_fname, extension_type, False) directories.extend (l_directory) directories.forth elseif (l_files.item.is_equal ("Makefile.SH")) then create makefile_sh.make (l_fname) else l_shortname := l_files.item l_count := l_shortname.count -- If the name is not greater than 3 and does not contain ".", -- it means that we are not handling with Eiffel generated files -- which have always the following format: "eaxxxx.c". if not l_shortname.is_equal ("edynlib.c") and then not l_shortname.is_equal ("egc_dynlib.c") and then not l_shortname.is_equal ("emain.c") and then l_count > 3 and then l_shortname.substring_index (".", 1) /= 0 then if l_shortname.substring_index (".c",1) = l_count - 1 then c_files.extend (l_shortname) c_files.forth elseif l_shortname.substring_index (".cpp",1) = l_count - 3 then cpp_files.extend (l_shortname) cpp_files.forth elseif l_shortname.substring_index (".x",1) = l_count - 1 then x_files.extend (l_fname) x_files.forth elseif l_shortname.substring_index (".xpp",1) = l_count - 3 then xpp_files.extend (l_fname) xpp_files.forth end end end end l_files.forth end ensure is_root_set: is_root = a_is_root end feature -- Access concat -- Concatene all the x/c files and modify the Makefile. local l_directories: LINEAR [EIFFEL_F_CODE_DIRECTORY] l_has_c_file, l_has_cpp_file, l_has_x_file, l_has_xpp_file: BOOLEAN l_new_objects: STRING do if is_root then -- Do the work an all subdirectories from l_directories := directories.linear_representation l_directories.start until l_directories.off loop l_directories.item.concat l_directories.forth end elseif makefile_sh /= Void then if not c_files.is_empty then l_has_c_file := True if not has_finished_file then fake_concat_files (c_files, big_file_name (False, True, False)) end end if not cpp_files.is_empty then l_has_cpp_file := True if not has_finished_file then fake_concat_files (cpp_files, big_file_name (False, True, True)) end end if not x_files.is_empty then l_has_x_file := True if not has_finished_file then concat_files (x_files, big_file_name (False, False, False)) end end if not xpp_files.is_empty then l_has_xpp_file := True if not has_finished_file then concat_files (xpp_files, big_file_name (False, False, True)) end end makefile_sh.open_read makefile_sh.read_stream (makefile_sh.count) makefile_sh.close if makefile_sh.last_string.substring_index ("OLDOBJECTS", 1) = 0 then l_new_objects := "OBJECTS = " if l_has_c_file then l_new_objects.append (big_file_name (True, True, False)) l_new_objects.append (" ") end if l_has_cpp_file then l_new_objects.append (big_file_name (True, True, True)) l_new_objects.append (" ") end if l_has_x_file then l_new_objects.append (big_file_name (True, False, False)) l_new_objects.append (" ") end if l_has_xpp_file then l_new_objects.append (big_file_name (True, False, True)) end l_new_objects.append ("%N%N" + "OLDOBJECTS = ") makefile_sh.last_string.replace_substring_all ("OBJECTS =", l_new_objects) makefile_sh.open_write makefile_sh.put_string (makefile_sh.last_string) makefile_sh.put_string ("%N") makefile_sh.close end else -- makefile_sh = void io.put_string("WARNING: Directory '") io.put_string(name) io.put_string("'%Nhas not been generated by the ISE Eiffel compiler.%N") end end path_name (a_name: STRING): STRING do Result := name.twin Result.append_character (Directory_separator) Result.append (a_name) end feature -- Access is_root: BOOLEAN -- Is current directory the root of W_code of F_code? object_extension: STRING -- Extension name of the object files, depends on the platform. x_files: ARRAYED_LIST [STRING] -- List of .x files in F_code. c_files: ARRAYED_LIST [STRING] -- List of .c files in W_code. xpp_files: ARRAYED_LIST [STRING] -- List of .xpp files in F_code. cpp_files: ARRAYED_LIST [STRING] -- List of .cpp files in W_code. makefile_sh: PLAIN_TEXT_FILE directories: ARRAYED_LIST [EIFFEL_F_CODE_DIRECTORY] has_finished_file: BOOLEAN -- Does the directory contain `finished'? feature {NONE} -- Access big_file_name_prefix: STRING -- Prefix to `big_file_name'. feature {NONE} -- Constants big_file_prefix: STRING = "big_file_" -- Prefix of the big_file name. buffered_input_string: STRING -- Buffer string filled by reading into a file. once create Result.make (10_000_000) end feature {NONE} -- Implementation big_file_name (is_obj_file, is_c_file, is_cpp_file: BOOLEAN): STRING -- Build big file name associated to current directory with `is_obj_file', -- `is_c_file' and `is_cpp_file' specification. do create Result.make (big_file_name_prefix.count + 8) Result.append (big_file_name_prefix) if is_c_file then if is_cpp_file then if is_obj_file then Result.append ("_cpp." + object_extension) else Result.append ("_cpp.cpp") end else if is_obj_file then Result.append ("_c." + object_extension) else Result.append ("_c.c") end end else if is_cpp_file then if is_obj_file then Result.append ("_xpp." + object_extension) else Result.append ("_xpp.xpp") end else if is_obj_file then Result.append ("_x." + object_extension) else Result.append ("_x.x") end end end ensure big_file_name_not_void: Result /= Void big_file_name_not_empty: not Result.is_empty end fake_concat_files (l_files: ARRAYED_LIST [STRING]; l_output_name: STRING) -- Put all files as includes in one file whose name is specified by `is_c_file' and -- `is_cpp_file'. require l_files_not_void: l_files /= Void l_output_name_not_void: l_output_name /= Void local l_big_file_name: STRING l_big_file: RAW_FILE do if not l_files.is_empty then l_big_file_name := name.twin l_big_file_name.append_character (Directory_separator) l_big_file_name.append (l_output_name) create l_big_file.make_open_write (l_big_file_name) from l_files.start until l_files.off loop l_big_file.put_string ("#include %"") l_big_file.put_string (l_files.item) l_big_file.put_string ("%"%N") l_files.forth end l_big_file.close end end concat_files (l_files: ARRAYED_LIST [STRING]; l_output_name: STRING) -- Concat all files into one file whose name is specified by `is_c_file' and -- `is_cpp_file'. require l_files_not_void: l_files /= Void l_output_name_not_void: l_output_name /= Void local l_big_file_name: STRING input_string: STRING l_big_file: RAW_FILE l_file: C_FILE do if not l_files.is_empty then input_string := buffered_input_string l_big_file_name := name.twin l_big_file_name.append_character (Directory_separator) l_big_file_name.append (l_output_name) create l_big_file.make_open_write (l_big_file_name) create l_file.make ("test") from l_files.start until l_files.off loop l_file.make (l_files.item) l_file.open_read l_file.read_all (input_string) l_big_file.put_string (input_string) l_file.close l_files.forth end l_big_file.close end end invariant big_file_name_prefix_not_void: big_file_name_prefix /= Void note copyright: "Copyright (c) 1984-2012, 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 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class EIFFEL_F_CODE_DIRECTORY