[m-rev.] for post-commit review: break up modules.m

Zoltan Somogyi zs at csse.unimelb.edu.au
Mon Jul 21 13:09:13 AEST 2008


I will address any issues post-commit. The main thing that needs checking
is whether I made any mistakes in replacing 'yes's and 'no's when introducing
purpose-specific types. I have done a scan of the diff myself, but a second
one couldn't hurt.

Zoltan.

The file modules.m contains lots of different kinds of functionality.
While much of it belongs together, much of it does not. This diff moves
most of the functionality that does not belong with the rest to several
new modules:

	libs.file_util
	parse_tree.deps_map
	parse_tree.file_names
	parse_tree.module_cmds
	parse_tree.module_imports
	parse_tree.read_module
	parse_tree.write_deps_file

To make them coherent, move some predicates from hlds.passes_aux,
parse_tree.prog_io and parse_tree.prog_out to the new modules, making them
more accessible, reducing the required access from the hlds package to
parse_tree, or from the parse_tree package to libs.

In the same spirit, this diff also moves some simple predicates and functions
dealing with sym_names from prog_util.m to mdbcomp/prim_data.m. This allows
several modules to avoid depending on parse_tree.prog_util.

Rename some of the moved predicates and function symbols where this avoids
ambiguity. (There were several that differed from other predicates or function
symbols only in arity.)

Replace several uses of bools with purpose-specific types. This makes some
of the code significantly easier to read.

This diff moves modules.m from being by far the largest module, to being
only the seventh largest, from 8900+ lines to just 4200+. It also reduces
the number of modules that import parse_tree.modules considerably; most
modules that imported it now import only one or two of the new modules instead.

Despite the size of the diff, there should be no algorithmic changes.

compiler/modules.m:
compiler/passes_aux.m:
compiler/prog_io.m:
compiler/prog_out.m:
	Delete the moved functionality.

compiler/file_util.m:
	New module in the libs package. Its predicates search for files
	and do simple error or progress reporting.

compiler/file_names.m:
	New module in the parse_tree package. It contains predicates for
	converting module names to file names.

compiler/module_cmds.m:
	New module in the parse_tree package. Its predicates handle the
	commands for manipulating interface files of various kinds.

compiler/module_import.m:
	New module in the parse_tree package. It contains the module_imports
	type and its access predicates, and the predicates that compute
	various sorts of direct dependencies (those caused by imports)
	between modules.

compiler/deps_map.m:
	New module in the parse_tree package. It contains the data structure
	for recording indirect dependencies between modules, and the predicates
	for creating it.

compiler/read_module.m:
	New module in the parse_tree package. Its job is reading in modules,
	both human-written and machine-written (such as interface and
	optimization files).

compiler/write_deps_file.m:
	New module in the parse_tree package. Its job is writing out
	makefile fragments.

compiler/libs.m:
compiler/parse_tree.m:
	Include the new modules.

compiler/notes/compiler_design.m:
	Document the new modules.

mdbcomp/prim_data.m:
compiler/prog_util.m:
	Move the predicates that operate on nothing but sym_names from
	prog_util to prim_data.

	Move get_ancestors from modules to prim_data.

compiler/prog_item.m:
	Move stuff that looks for foreign code in a list of items here from
	modules.m.

compiler/source_file_map.m:
	Note why this module needs to be in the parse_tree package.

compiler/add_pred.m:
compiler/add_special_pred.m:
compiler/analysis.file.m:
compiler/analysis.m:
compiler/assertion.m:
compiler/check_typeclass.m:
compiler/compile_target_code.m:
compiler/cse_detection.m:
compiler/det_analysis.m:
compiler/elds_to_erlang.m:
compiler/exception_analysis.m:
compiler/export.m:
compiler/fact_table.m:
compiler/higher_order.m:
compiler/hlds_module.m:
compiler/hlds_pred.m:
compiler/intermod.m:
compiler/llds_out.m:
compiler/make.dependencies.m:
compiler/make.m:
compiler/make.module_dep_file.m:
compiler/make.module_target.m:
compiler/make.program_target.m:
compiler/make.util.m:
compiler/make_hlds_passes.m:
compiler/maybe_mlds_to_gcc.pp:
compiler/mercury_compile.m:
compiler/mlds.m:
compiler/mlds_to_c.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_ilasm.m:
compiler/mlds_to_java.m:
compiler/mmc_analysis.m:
compiler/mode_constraints.m:
compiler/mode_debug.m:
compiler/modes.m:
compiler/module_qual.m:
compiler/optimize.m:
compiler/passes_aux.m:
compiler/proc_gen.m:
compiler/prog_foreign.m:
compiler/prog_io.m:
compiler/prog_io_util.m:
compiler/prog_mutable.m:
compiler/prog_out.m:
compiler/pseudo_type_info.m:
compiler/purity.m:
compiler/recompilation.check.m:
compiler/recompilation.usage.m:
compiler/simplify.m:
compiler/structure_reuse.analysis.m:
compiler/structure_reuse.direct.detect_garbage.m:
compiler/structure_reuse.direct.m:
compiler/structure_sharing.analysis.m:
compiler/tabling_analysis.m:
compiler/term_constr_main.m:
compiler/termination.m:
compiler/trailing_analysis.m:
compiler/trans_opt.m:
compiler/type_util.m:
compiler/typecheck.m:
compiler/typecheck_info.m:
compiler/unify_proc.m:
compiler/unused_args.m:
compiler/unused_imports.m:
compiler/xml_documentation.m:
	Minor changes to conform to the changes above.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/add_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_pred.m,v
retrieving revision 1.33
diff -u -b -r1.33 add_pred.m
--- compiler/add_pred.m	23 Nov 2007 07:34:53 -0000	1.33
+++ compiler/add_pred.m	18 Jul 2008 14:48:57 -0000
@@ -381,7 +381,7 @@
     % will be inferred automatically.
 
     module_info_get_name(!.ModuleInfo, ModuleName0),
-    sym_name_get_module_name(PredName, ModuleName0, ModuleName),
+    sym_name_get_module_name_default(PredName, ModuleName0, ModuleName),
     list.length(Modes, Arity),
     module_info_get_predicate_table(!.ModuleInfo, PredicateTable0),
     (
Index: compiler/add_special_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/add_special_pred.m,v
retrieving revision 1.25
diff -u -b -r1.25 add_special_pred.m
--- compiler/add_special_pred.m	11 Feb 2008 21:25:50 -0000	1.25
+++ compiler/add_special_pred.m	18 Jul 2008 14:48:57 -0000
@@ -74,7 +74,6 @@
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module parse_tree.prog_type.
-:- import_module parse_tree.prog_util.
 
 :- import_module bool.
 :- import_module int.
@@ -370,7 +369,8 @@
     (
         SpecialPredId = spec_pred_init,
         TypeCtor = type_ctor(TypeSymName, _TypeArity),
-        sym_name_get_module_name(TypeSymName, ModuleName, TypeModuleName),
+        sym_name_get_module_name_default(TypeSymName, ModuleName,
+            TypeModuleName),
         PredName = qualified(TypeModuleName, Name)
     ;
         ( SpecialPredId = spec_pred_unify
Index: compiler/analysis.file.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/analysis.file.m,v
retrieving revision 1.6
diff -u -b -r1.6 analysis.file.m
--- compiler/analysis.file.m	6 Jun 2008 02:18:05 -0000	1.6
+++ compiler/analysis.file.m	18 Jul 2008 09:57:11 -0000
@@ -106,7 +106,7 @@
 
 :- import_module libs.compiler_util.
 :- import_module parse_tree.
-:- import_module parse_tree.modules.    % XXX unwanted dependency
+:- import_module parse_tree.module_cmds.        % XXX unwanted dependency
 :- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_out.
 
Index: compiler/analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/analysis.m,v
retrieving revision 1.7
diff -u -b -r1.7 analysis.m
--- compiler/analysis.m	6 Jun 2008 02:18:05 -0000	1.7
+++ compiler/analysis.m	18 Jul 2008 09:56:24 -0000
@@ -316,7 +316,7 @@
 :- import_module libs.
 :- import_module libs.compiler_util.
 :- import_module parse_tree.            % XXX unwanted dependency
-:- import_module parse_tree.modules.    % XXX unwanted dependency
+:- import_module parse_tree.module_cmds.    % XXX unwanted dependency
 
 :- import_module map.
 :- import_module string.
Index: compiler/assertion.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/assertion.m,v
retrieving revision 1.61
diff -u -b -r1.61 assertion.m
--- compiler/assertion.m	27 Feb 2008 07:23:02 -0000	1.61
+++ compiler/assertion.m	18 Jul 2008 14:48:57 -0000
@@ -135,7 +135,8 @@
 :- import_module hlds.goal_util.
 :- import_module hlds.hlds_clauses.
 :- import_module libs.compiler_util.
-:- import_module parse_tree.prog_util.
+:- import_module mdbcomp.
+:- import_module mdbcomp.prim_data.
 
 :- import_module assoc_list.
 :- import_module list.
Index: compiler/check_typeclass.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/check_typeclass.m,v
retrieving revision 1.121
diff -u -b -r1.121 check_typeclass.m
--- compiler/check_typeclass.m	16 Jul 2008 03:30:26 -0000	1.121
+++ compiler/check_typeclass.m	18 Jul 2008 10:00:48 -0000
@@ -118,13 +118,13 @@
 :- import_module hlds.pred_table.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_type_subst.
 :- import_module parse_tree.prog_util.
Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.128
diff -u -b -r1.128 compile_target_code.m
--- compiler/compile_target_code.m	29 Jan 2008 03:40:08 -0000	1.128
+++ compiler/compile_target_code.m	19 Jul 2008 04:49:27 -0000
@@ -16,12 +16,12 @@
 :- module backend_libs.compile_target_code.
 :- interface.
 
-:- import_module parse_tree.
-:- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_io.
-:- import_module parse_tree.modules.
 :- import_module libs.
 :- import_module libs.globals.
+:- import_module libs.file_util.
+:- import_module parse_tree.
+:- import_module parse_tree.module_imports.
+:- import_module parse_tree.prog_data.
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
 
@@ -215,6 +215,9 @@
 :- import_module libs.timestamp.
 :- import_module libs.trace_params.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
+:- import_module parse_tree.write_deps_file.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_out.
 
@@ -225,8 +228,9 @@
 %-----------------------------------------------------------------------------%
 
 il_assemble(ErrorStream, ModuleName, HasMain, Succeeded, !IO) :-
-    module_name_to_file_name(ModuleName, ".il", no, IL_File, !IO),
-    module_name_to_file_name(ModuleName, ".dll", yes, DllFile, !IO),
+    module_name_to_file_name(ModuleName, ".il", do_not_create_dirs, IL_File,
+        !IO),
+    module_name_to_file_name(ModuleName, ".dll", do_create_dirs, DllFile, !IO),
 
     % If the module contains main/2 then we it should be built as an
     % executable. Unfortunately C# code may refer to the dll
@@ -235,7 +239,8 @@
     il_assemble(ErrorStream, IL_File, DllFile, no_main, DllSucceeded, !IO),
     ( 
         HasMain = has_main,
-        module_name_to_file_name(ModuleName, ".exe", yes, ExeFile, !IO),
+        module_name_to_file_name(ModuleName, ".exe", do_create_dirs, ExeFile,
+            !IO),
         il_assemble(ErrorStream, IL_File, ExeFile, HasMain, ExeSucceeded, !IO),
         Succeeded = DllSucceeded `and` ExeSucceeded
     ;
@@ -333,7 +338,8 @@
         Imports ^ int_deps ++ Imports ^ impl_deps ++ ForeignDeps),
     list.map_foldl(
         (pred(Mod::in, Result::out, IO0::di, IO::uo) is det :-
-            module_name_to_file_name(Mod, ".dll", no, FileName, IO0, IO),
+            module_name_to_file_name(Mod, ".dll", do_not_create_dirs,
+                FileName, IO0, IO),
             Result = [Prefix, FileName, " "]
         ), ReferencedDlls, ReferencedDllsList, !IO),
     ReferencedDllsStr = string.append_list(
@@ -351,9 +357,9 @@
 % Any changes there may also require changes here, and vice versa.
 
 compile_c_file(ErrorStream, PIC, ModuleName, Succeeded, !IO) :-
-    module_name_to_file_name(ModuleName, ".c", yes, C_File, !IO),
+    module_name_to_file_name(ModuleName, ".c", do_create_dirs, C_File, !IO),
     maybe_pic_object_file_extension(PIC, ObjExt, !IO),
-    module_name_to_file_name(ModuleName, ObjExt, yes, O_File, !IO),
+    module_name_to_file_name(ModuleName, ObjExt, do_create_dirs, O_File, !IO),
     compile_c_file(ErrorStream, PIC, C_File, O_File, Succeeded, !IO).
 
 compile_c_file(ErrorStream, PIC, C_File, O_File, Succeeded, !IO) :-
@@ -922,9 +928,10 @@
         GCCFLAGS_FOR_ASM = "",
         GCCFLAGS_FOR_PIC = ""
     ),
-    module_name_to_file_name(ModuleName, AsmExt, no, AsmFile, !IO),
+    module_name_to_file_name(ModuleName, AsmExt, do_not_create_dirs, AsmFile,
+        !IO),
     maybe_pic_object_file_extension(PIC, ObjExt, !IO),
-    module_name_to_file_name(ModuleName, ObjExt, yes, ObjFile, !IO),
+    module_name_to_file_name(ModuleName, ObjExt, do_create_dirs, ObjFile, !IO),
 
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Assembling `", !IO),
@@ -1027,12 +1034,13 @@
 
 make_library_init_file_2(ErrorStream, MainModuleName, AllModules, TargetExt,
         MkInit, Succeeded, !IO) :-
-    module_name_to_file_name(MainModuleName, ".init.tmp", yes, TmpInitFileName,
-        !IO),
+    module_name_to_file_name(MainModuleName, ".init.tmp", do_create_dirs,
+        TmpInitFileName, !IO),
     io.open_output(TmpInitFileName, InitFileRes, !IO),
     (
         InitFileRes = ok(InitFileStream),
-        list.map_foldl(module_name_to_file_name_ext(TargetExt, no),
+        list.map_foldl(
+            module_name_to_file_name_ext(TargetExt, do_not_create_dirs),
             AllModules, AllTargetFilesList, !IO),
         join_quoted_string_list(AllTargetFilesList, "", "\n", "",
             TargetFileNames),
@@ -1082,8 +1090,8 @@
         ),
 
         io.close_output(InitFileStream, !IO),
-        module_name_to_file_name(MainModuleName, ".init", yes, InitFileName,
-            !IO),
+        module_name_to_file_name(MainModuleName, ".init", do_create_dirs,
+            InitFileName, !IO),
         update_interface_return_succeeded(InitFileName, Succeeded1, !IO),
         Succeeded2 = Succeeded0 `and` Succeeded1,
         (
@@ -1097,8 +1105,8 @@
                 io.set_output_stream(ErrorStream, OutputStream, !IO),
                 globals.io_set_option(use_subdirs, bool(no), !IO),
                 globals.io_set_option(use_grade_subdirs, bool(no), !IO),
-                module_name_to_file_name(MainModuleName, ".init", no,
-                    UserDirFileName, !IO),
+                module_name_to_file_name(MainModuleName, ".init",
+                    do_not_create_dirs, UserDirFileName, !IO),
                 globals.io_set_option(use_subdirs, bool(yes), !IO),
                 globals.io_set_option(use_grade_subdirs, bool(yes), !IO),
                 % Remove the target of the symlink/copy in case it already
@@ -1128,8 +1136,8 @@
         Succeeded = no
     ).
 
-:- pred module_name_to_file_name_ext(string::in, bool::in, module_name::in, 
-    file_name::out, io::di, io::uo) is det.
+:- pred module_name_to_file_name_ext(string::in, maybe_create_dirs::in,
+    module_name::in, file_name::out, io::di, io::uo) is det.
 
 module_name_to_file_name_ext(Ext, MkDir, ModuleName, FileName, !IO) :-
     module_name_to_file_name(ModuleName, Ext, MkDir, FileName, !IO).
@@ -1268,7 +1276,7 @@
     get_object_code_type(executable, PIC, !IO),
     maybe_pic_object_file_extension(PIC, ObjExt, !IO),
 
-    module_name_to_file_name(ModuleName, "_init" ++ ObjExt, yes,
+    module_name_to_file_name(ModuleName, "_init" ++ ObjExt, do_create_dirs,
         InitObjFileName, !IO),
     CompileCInitFile =
         (pred(InitTargetFileName::in, Res::out, IO0::di, IO::uo) is det :-
@@ -1312,7 +1320,7 @@
         ".erl", StdInitFileNames, StdTraceInitFileNames,
         SourceDebugInitFileNames, ModuleNameOption, MaybeInitTargetFile, !IO),
 
-    module_name_to_file_name(ModuleName, "_init.beam", yes,
+    module_name_to_file_name(ModuleName, "_init.beam", do_create_dirs,
         InitObjFileName, !IO),
     CompileErlangInitFile =
         (pred(InitTargetFileName::in, Res::out, IO0::di, IO::uo) is det :-
@@ -1336,10 +1344,10 @@
     globals.io_get_globals(Globals, !IO),
     compute_grade(Globals, Grade),
 
-    module_name_to_file_name(ModuleName, "_init" ++ TargetExt, yes,
+    module_name_to_file_name(ModuleName, "_init" ++ TargetExt, do_create_dirs,
         InitTargetFileName, !IO),
 
-    list.map_foldl(module_name_to_file_name_ext(TargetExt, no),
+    list.map_foldl(module_name_to_file_name_ext(TargetExt, do_not_create_dirs),
         ModuleNames, TargetFileNameList, !IO),
     join_quoted_string_list(TargetFileNameList, "", "", " ", TargetFileNames),
 
@@ -1583,26 +1591,28 @@
     (
         LinkTargetType = static_library,
         globals.io_lookup_string_option(library_extension, Ext, !IO),
-        module_name_to_lib_file_name("lib", ModuleName, Ext, yes,
+        module_name_to_lib_file_name("lib", ModuleName, Ext, do_create_dirs,
             OutputFileName, !IO)
     ;
         LinkTargetType = shared_library,
         globals.io_lookup_string_option(shared_library_extension, Ext, !IO),
-        module_name_to_lib_file_name("lib", ModuleName, Ext, yes,
+        module_name_to_lib_file_name("lib", ModuleName, Ext, do_create_dirs,
             OutputFileName, !IO)
     ;
         LinkTargetType = java_archive,
         Ext = ".jar",
-        module_name_to_file_name(ModuleName, Ext, yes, OutputFileName, !IO)
+        module_name_to_file_name(ModuleName, Ext, do_create_dirs,
+            OutputFileName, !IO)
     ;
         LinkTargetType = erlang_archive,
         Ext = ".beams",
-        module_name_to_lib_file_name("lib", ModuleName, Ext, yes,
+        module_name_to_lib_file_name("lib", ModuleName, Ext, do_create_dirs,
             OutputFileName, !IO)
     ;
         LinkTargetType = executable,
         globals.io_lookup_string_option(executable_file_extension, Ext, !IO),
-        module_name_to_file_name(ModuleName, Ext, yes, OutputFileName, !IO)
+        module_name_to_file_name(ModuleName, Ext, do_create_dirs,
+            OutputFileName, !IO)
     ).
 
 :- pred link_exe_or_shared_lib(io.output_stream::in,
@@ -2066,15 +2076,16 @@
         globals.io_set_option(use_grade_subdirs, bool(no), !IO),
         ( 
             LinkTargetType = executable,
-            module_name_to_file_name(ModuleName, Ext, no, UserDirFileName, !IO)
+            module_name_to_file_name(ModuleName, Ext, do_not_create_dirs,
+                UserDirFileName, !IO)
         ;
             ( LinkTargetType = static_library
             ; LinkTargetType = shared_library
             ; LinkTargetType = java_archive
             ; LinkTargetType = erlang_archive
             ),
-            module_name_to_lib_file_name("lib", ModuleName, Ext, no,
-                UserDirFileName, !IO)
+            module_name_to_lib_file_name("lib", ModuleName, Ext,
+                do_not_create_dirs, UserDirFileName, !IO)
         ),
         globals.io_set_option(use_subdirs, bool(yes), !IO),
         globals.io_set_option(use_grade_subdirs, bool(yes), !IO),
@@ -2140,8 +2151,8 @@
         globals.io_lookup_string_option(library_extension, LibExt, !IO),
 
         globals.io_set_option(use_grade_subdirs, bool(no), !IO),
-        module_name_to_lib_file_name("lib", LibModuleName, LibExt, no,
-            LibFileName, !IO),
+        module_name_to_lib_file_name("lib", LibModuleName, LibExt,
+            do_not_create_dirs, LibFileName, !IO),
         globals.io_set_option(use_grade_subdirs, bool(UseGradeSubdirs), !IO),
 
         io.input_stream(InputStream, !IO),
@@ -2428,7 +2439,8 @@
 join_module_list([], _Extension, [], !IO).
 join_module_list([Module | Modules], Extension, [FileName | Rest], !IO) :-
     file_name_to_module_name(dir.basename_det(Module), ModuleName),
-    module_name_to_file_name(ModuleName, Extension, no, FileName, !IO),
+    module_name_to_file_name(ModuleName, Extension, do_not_create_dirs,
+        FileName, !IO),
     join_module_list(Modules, Extension, Rest, !IO).
 
 %-----------------------------------------------------------------------------%
@@ -2437,7 +2449,8 @@
     % Pass the main module first.
     list.map_foldl(
         (pred(Module::in, FileName::out, IO0::di, IO::uo) is det :-
-            module_name_to_file_name(Module, ".m", no, FileName, IO0, IO)
+            module_name_to_file_name(Module, ".m", do_not_create_dirs,
+                FileName, IO0, IO)
         ),
         [MainModule | list.delete_all(AllModules, MainModule)],
         ModuleNameStrings, !IO),
Index: compiler/cse_detection.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/cse_detection.m,v
retrieving revision 1.117
diff -u -b -r1.117 cse_detection.m
--- compiler/cse_detection.m	27 Feb 2008 07:23:04 -0000	1.117
+++ compiler/cse_detection.m	18 Jul 2008 10:01:08 -0000
@@ -49,12 +49,12 @@
 :- import_module hlds.quantification.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module parse_tree.
 :- import_module parse_tree.error_util.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type_subst.
 
 :- import_module assoc_list.
Index: compiler/deps_map.m
===================================================================
RCS file: compiler/deps_map.m
diff -N compiler/deps_map.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/deps_map.m	19 Jul 2008 07:54:00 -0000
@@ -0,0 +1,224 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1996-2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: deps_map.m.
+%
+% This module contains the data structure for recording module dependencies
+% and its access predicates.
+%
+%-----------------------------------------------------------------------------%
+
+:- module parse_tree.deps_map.
+:- interface.
+
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_imports.
+
+:- import_module map.
+:- import_module io.
+
+% This is the data structure we use to record the dependencies.
+% We keep a map from module name to information about the module.
+
+:- type have_processed
+    --->    not_yet_processed
+    ;       already_processed.
+
+:- type deps_map == map(module_name, deps).
+:- type deps
+    --->    deps(
+                have_processed,
+                module_imports
+            ).
+
+:- type submodule_kind
+    --->    toplevel
+    ;       nested_submodule
+    ;       separate_submodule.
+
+    % Check if a module is a top-level module, a nested sub-module,
+    % or a separate sub-module.
+    %
+:- func get_submodule_kind(module_name, deps_map) = submodule_kind.
+
+%-----------------------------------------------------------------------------%
+
+:- pred generate_deps_map(module_name::in, maybe_search::in,
+    deps_map::in, deps_map::out, io::di, io::uo) is det.
+
+    % Insert a new entry into the deps_map. If the module already occurred
+    % in the deps_map, then we just replace the old entry (presumed to be
+    % a dummy entry) with the new one.
+    %
+    % This can only occur for sub-modules which have been imported before
+    % their parent module was imported: before reading a module and
+    % inserting it into the deps map, we check if it was already there,
+    % but when we read in the module, we try to insert not just that module
+    % but also all the nested sub-modules inside that module. If a sub-module
+    % was previously imported, then it may already have an entry in the
+    % deps_map. However, unless the sub-module is defined both as a separate
+    % sub-module and also as a nested sub-module, the previous entry will be
+    % a dummy entry that we inserted after trying to read the source file
+    % and failing.
+    %
+    % Note that the case where a module is defined as both a separate
+    % sub-module and also as a nested sub-module is caught in
+    % split_into_submodules.
+    %
+    % XXX This shouldn't need to be exported.
+    %
+:- pred insert_into_deps_map(module_imports::in, deps_map::in, deps_map::out)
+    is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.globals.
+:- import_module parse_tree.error_util.
+:- import_module parse_tree.modules.        % for split_into_submodules;
+                                            % undesirable dependencies
+:- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_io.
+:- import_module parse_tree.read_modules.
+
+:- import_module assoc_list.
+:- import_module bool.
+:- import_module dir.
+:- import_module list.
+:- import_module pair.
+:- import_module set.
+:- import_module svmap.
+:- import_module term.
+
+%-----------------------------------------------------------------------------%
+
+get_submodule_kind(ModuleName, DepsMap) = Kind :-
+    Ancestors = get_ancestors(ModuleName),
+    ( list.last(Ancestors, Parent) ->
+        map.lookup(DepsMap, ModuleName, deps(_, ModuleImports)),
+        map.lookup(DepsMap, Parent, deps(_, ParentImports)),
+        ModuleFileName = ModuleImports ^ source_file_name,
+        ParentFileName = ParentImports ^ source_file_name,
+        ( ModuleFileName = ParentFileName ->
+            Kind = nested_submodule
+        ;
+            Kind = separate_submodule
+        )
+    ;
+        Kind = toplevel
+    ).
+
+%-----------------------------------------------------------------------------%
+
+generate_deps_map(ModuleName, Search, !DepsMap, !IO) :-
+    generate_deps_map_loop(set.make_singleton_set(ModuleName), Search,
+        !DepsMap, !IO).
+
+:- pred generate_deps_map_loop(set(module_name)::in, maybe_search::in,
+    deps_map::in, deps_map::out, io::di, io::uo) is det.
+
+generate_deps_map_loop(!.Modules, Search, !DepsMap, !IO) :-
+    ( set.remove_least(!.Modules, Module, !:Modules) ->
+        generate_deps_map_step(Module, !Modules, Search, !DepsMap, !IO),
+        generate_deps_map_loop(!.Modules, Search, !DepsMap, !IO)
+    ;
+        % If we can't remove the smallest, then the set of modules to be
+        % processed is empty.
+        true
+    ).
+
+:- pred generate_deps_map_step(module_name::in,
+    set(module_name)::in, set(module_name)::out,
+    maybe_search::in, deps_map::in, deps_map::out, io::di, io::uo) is det.
+
+generate_deps_map_step(Module, !Modules, Search, !DepsMap, !IO) :-
+    % Look up the module's dependencies, and determine whether
+    % it has been processed yet.
+    lookup_dependencies(Module, Search, Done, !DepsMap, ModuleImports, !IO),
+
+    % If the module hadn't been processed yet, then add its imports, parents,
+    % and public children to the list of dependencies we need to generate,
+    % and mark it as having been processed.
+    (
+        Done = not_yet_processed,
+        svmap.set(Module, deps(already_processed, ModuleImports), !DepsMap),
+        ForeignImportedModules =
+            list.map(
+                (func(foreign_import_module_info(_, ImportedModule, _))
+                    = ImportedModule),
+                ModuleImports ^ foreign_import_modules),
+        list.condense(
+            [ModuleImports ^ parent_deps,
+            ModuleImports ^ int_deps,
+            ModuleImports ^ impl_deps,
+            ModuleImports ^ public_children, % a.k.a. incl_deps
+            ForeignImportedModules],
+            ModulesToAdd),
+        % We could keep a list of the modules we have already processed
+        % and subtract it from ModulesToAddSet here, but doing that
+        % actually leads to a small slowdown.
+        set.list_to_set(ModulesToAdd, ModulesToAddSet),
+        set.union(ModulesToAddSet, !Modules)
+    ;
+        Done = already_processed
+    ).
+
+    % Look up a module in the dependency map.
+    % If we don't know its dependencies, read the module and
+    % save the dependencies in the dependency map.
+    %
+:- pred lookup_dependencies(module_name::in, maybe_search::in,
+    have_processed::out, deps_map::in, deps_map::out, module_imports::out,
+    io::di, io::uo) is det.
+
+lookup_dependencies(Module, Search, Done, !DepsMap, ModuleImports, !IO) :-
+    ( map.search(!.DepsMap, Module, deps(DonePrime, ModuleImportsPrime)) ->
+        Done = DonePrime,
+        ModuleImports = ModuleImportsPrime
+    ;
+        read_dependencies(Module, Search, ModuleImportsList, !IO),
+        list.foldl(insert_into_deps_map, ModuleImportsList, !DepsMap),
+        map.lookup(!.DepsMap, Module, deps(Done, ModuleImports))
+    ).
+
+insert_into_deps_map(ModuleImports, !DepsMap) :-
+    module_imports_get_module_name(ModuleImports, ModuleName),
+    svmap.set(ModuleName, deps(not_yet_processed, ModuleImports), !DepsMap).
+
+    % Read a module to determine the (direct) dependencies of that module
+    % and any nested sub-modules it contains.
+    %
+:- pred read_dependencies(module_name::in, maybe_search::in,
+    list(module_imports)::out, io::di, io::uo) is det.
+
+read_dependencies(ModuleName, Search, ModuleImportsList, !IO) :-
+    read_module_ignore_errors(ModuleName, ".m",
+        "Getting dependencies for module", Search, do_not_return_timestamp,
+        Items0, Error, FileName0, _, !IO),
+    globals.io_get_globals(Globals, !IO),
+    (
+        Items0 = [],
+        Error = fatal_module_errors
+    ->
+        read_module_ignore_errors(ModuleName, ".int",
+            "Getting dependencies for module interface", Search,
+            do_not_return_timestamp, Items, _Error, FileName, _, !IO),
+        SubModuleList = [ModuleName - Items]
+    ;
+        FileName = FileName0,
+        Items = Items0,
+        split_into_submodules(ModuleName, Items, SubModuleList, [], Specs),
+        write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO)
+    ),
+    assoc_list.keys(SubModuleList, SubModuleNames),
+    list.map(init_dependencies(FileName, ModuleName, SubModuleNames,
+        Error, Globals), SubModuleList, ModuleImportsList).
+
+%-----------------------------------------------------------------------------%
Index: compiler/det_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/det_analysis.m,v
retrieving revision 1.214
diff -u -b -r1.214 det_analysis.m
--- compiler/det_analysis.m	25 Apr 2008 17:22:31 -0000	1.214
+++ compiler/det_analysis.m	18 Jul 2008 10:02:07 -0000
@@ -118,12 +118,12 @@
 :- import_module hlds.hlds_out.
 :- import_module hlds.pred_table.
 :- import_module libs.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.compiler_util.
 :- import_module libs.options.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 
 :- import_module assoc_list.
Index: compiler/elds_to_erlang.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/elds_to_erlang.m,v
retrieving revision 1.32
diff -u -b -r1.32 elds_to_erlang.m
--- compiler/elds_to_erlang.m	23 Nov 2007 07:35:00 -0000	1.32
+++ compiler/elds_to_erlang.m	18 Jul 2008 16:25:08 -0000
@@ -45,12 +45,13 @@
 :- import_module backend_libs.rtti.
 :- import_module hlds.hlds_pred.
 :- import_module hlds.hlds_rtti.
-:- import_module hlds.passes_aux.
 :- import_module hlds.pred_table.
 :- import_module hlds.special_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module mdbcomp.prim_data.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_type.
@@ -72,8 +73,10 @@
 
 output_elds(ModuleInfo, ELDS, !IO) :-
     Name = ELDS ^ elds_name,
-    module_name_to_file_name(Name, ".erl", yes, SourceFileName, !IO),
-    module_name_to_file_name(Name, ".hrl", yes, HeaderFileName, !IO),
+    module_name_to_file_name(Name, ".erl", do_create_dirs, SourceFileName,
+        !IO),
+    module_name_to_file_name(Name, ".hrl", do_create_dirs, HeaderFileName,
+        !IO),
     output_to_file(SourceFileName, output_erl_file(ModuleInfo, ELDS,
         SourceFileName), !IO),
     % Avoid updating the timestamp on the `.hrl' file if it hasn't changed.
Index: compiler/exception_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/exception_analysis.m,v
retrieving revision 1.49
diff -u -b -r1.49 exception_analysis.m
--- compiler/exception_analysis.m	6 Jun 2008 02:18:05 -0000	1.49
+++ compiler/exception_analysis.m	18 Jul 2008 11:00:15 -0000
@@ -131,12 +131,12 @@
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
-:- import_module parse_tree.prog_out.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_type.
 :- import_module transform_hlds.dependency_graph.
 :- import_module transform_hlds.mmc_analysis.
@@ -1183,7 +1183,8 @@
 
 make_optimization_interface(ModuleInfo, !IO) :-
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+        OptFileName, !IO),
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Appending exceptions pragmas to `", !IO),
     maybe_write_string(Verbose, OptFileName, !IO),
Index: compiler/export.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.120
diff -u -b -r1.120 export.m
--- compiler/export.m	11 Feb 2008 21:25:53 -0000	1.120
+++ compiler/export.m	18 Jul 2008 11:00:37 -0000
@@ -96,7 +96,8 @@
 :- import_module hlds.pred_table.
 :- import_module libs.compiler_util.
 :- import_module libs.globals.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_util.
 
@@ -669,12 +670,14 @@
     ForeignExportDecls = foreign_export_decls(ForeignDecls, C_ExportDecls),
     module_info_get_exported_enums(ModuleInfo, ExportedEnums),
     HeaderExt = ".mh",
-    module_name_to_file_name(ModuleName, HeaderExt, yes, FileName, !IO),
+    module_name_to_file_name(ModuleName, HeaderExt, do_create_dirs,
+        FileName, !IO),
     io.open_output(FileName ++ ".tmp", Result, !IO),
     (
         Result = ok(FileStream),
         io.set_output_stream(FileStream, OutputStream, !IO),
-        module_name_to_file_name(ModuleName, ".m", no, SourceFileName, !IO),
+        module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+            SourceFileName, !IO),
         library.version(Version),
         io.write_strings([
             "/*\n",
Index: compiler/fact_table.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/fact_table.m,v
retrieving revision 1.85
diff -u -b -r1.85 fact_table.m
--- compiler/fact_table.m	3 Apr 2008 05:26:43 -0000	1.85
+++ compiler/fact_table.m	18 Jul 2008 11:00:47 -0000
@@ -103,13 +103,15 @@
 :- import_module hlds.code_model.
 :- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module ll_backend.code_util.
 :- import_module ll_backend.llds.
 :- import_module ll_backend.llds_out.
 :- import_module parse_tree.error_util.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_util.
@@ -214,8 +216,8 @@
     (
         SeeResult = ok,
         module_info_get_name(ModuleInfo, ModuleName),
-        fact_table_file_name(ModuleName, FileName, ".c", yes, OutputFileName,
-            !IO),
+        fact_table_file_name(ModuleName, FileName, ".c", do_create_dirs,
+            OutputFileName, !IO),
         open_output_handle_error(yes(Context), OutputFileName, OpenResult,
             !IO),
         (
Index: compiler/file_names.m
===================================================================
RCS file: compiler/file_names.m
diff -N compiler/file_names.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/file_names.m	18 Jul 2008 16:10:00 -0000
@@ -0,0 +1,524 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: file_name.m.
+%
+% This module deals with the connections between module names and files.
+%
+%-----------------------------------------------------------------------------%
+
+:- module parse_tree.file_names.
+:- interface.
+
+:- import_module mdbcomp.prim_data.
+:- import_module libs.file_util.
+
+:- import_module io.
+
+%-----------------------------------------------------------------------------%
+
+    % Succeeds iff the module referred to by the module name is one
+    % of the modules in the standard library.
+    %
+:- pred mercury_std_library_module_name(module_name::in) is semidet.
+
+    % To avoid namespace collisions between Mercury standard modules and
+    % Erlang standard modules, we pretend the Mercury standard modules are in
+    % a "mercury" supermodule.  This function returns ModuleName with the
+    % extra qualifier if it is a standard library module.  Otherwise it
+    % returns it unchanged.
+    %
+:- func erlang_module_name(module_name) = module_name.
+
+%-----------------------------------------------------------------------------%
+
+:- type maybe_create_dirs
+    --->    do_create_dirs
+    ;       do_not_create_dirs.
+
+    % module_name_to_file_name(Module, Extension, Mkdir, FileName):
+    %
+    % Convert a module name and file extension to the corresponding file name.
+    % If `MkDir' is create_dirs, then create any directories needed.
+    %
+    % Currently we use the convention that the module `foo.bar.baz' should be
+    % named `foo.bar.baz.m', and allow other naming conventions with the
+    % `-f' option.
+    %
+    % Note that this predicate is also used to create some "phony" Makefile
+    % targets that do not have corresponding files, e.g. `<foo>.clean'.
+    %
+:- pred module_name_to_file_name(module_name::in, string::in,
+    maybe_create_dirs::in, file_name::out, io::di, io::uo) is det.
+
+    % module_name_to_search_file_name(Module, Extension, FileName):
+    %
+    % As above, but for a file which might be in an installed library,
+    % not the current directory.
+    %
+    % With `--use-grade-subdirs', the current directory's `.mih' files are in
+    % `Mercury/<grade>/<arch>/Mercury/mihs', and those for installed libraries
+    % are in `<prefix>/lib/mercury/lib/<grade>/<arch>/inc/Mercury/mihs'.
+    %
+    % handle_options.m sets up the `--c-include-directory' options so that
+    % the name `<module>.mih' should be used in a context which requires
+    % searching for the `.mih files, for example in a C file.
+    %
+    % module_name_to_file_name would return
+    % `Mercury/<grade>/<arch>/Mercury/mihs/<module>.mihs',
+    % which would be used when writing or removing the `.mih' file.
+    %
+:- pred module_name_to_search_file_name(module_name::in, string::in,
+    file_name::out, io::di, io::uo) is det.
+
+:- type maybe_search
+    --->    do_search
+    ;       do_not_search.
+
+    % module_name_to_lib_file_name(Prefix, Module, Extension, MkDir,
+    %       FileName):
+    %
+    % Like module_name_to_file_name, but also allows a prefix.
+    %
+    % Used for creating library names, e.g. `lib<foo>.$A' and `lib<foo>.so'.
+    %
+:- pred module_name_to_lib_file_name(string::in, module_name::in, string::in,
+    maybe_create_dirs::in, file_name::out, io::di, io::uo) is det.
+
+    % fact_table_file_name(Module, FactTableFileName, Ext, MkDir, FileName):
+    % Returns the filename to use when compiling fact table files.
+    % If 'MkDir' is do_create_dirs, then create any directories needed.
+    %
+:- pred fact_table_file_name(module_name::in, file_name::in, string::in,
+    maybe_create_dirs::in, file_name::out, io::di, io::uo) is det.
+
+    % extra_link_obj_file_name(Module, ExtraLinkObjName,
+    %   Ext, MkDir, FileName):
+    %
+    % Returns the filename to use when compiling extra objects that must be
+    % linked into the executable (currently used only for fact tables).
+    % If `MkDir' is do_create_dirs, make any directories necessary.
+    %
+:- pred extra_link_obj_file_name(module_name::in, file_name::in, string::in,
+    maybe_create_dirs::in, file_name::out, io::di, io::uo) is det.
+
+    % Convert a file name (excluding the trailing `.m') to the corresponding
+    % module name.
+    %
+:- pred file_name_to_module_name(file_name::in, module_name::out) is det.
+
+    % Convert a module name to a file name stem (e.g. foo.bar.baz).
+    %
+:- pred module_name_to_file_name(module_name::in, file_name::out) is det.
+
+    % Convert a module name to something that is suitable
+    % for use as a variable name in makefiles.
+    %
+:- pred module_name_to_make_var_name(module_name::in, string::out) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.globals.
+
+:- import_module libs.compiler_util.
+:- import_module libs.handle_options.
+:- import_module libs.options.
+:- import_module parse_tree.prog_util.
+:- import_module parse_tree.source_file_map.
+
+:- import_module bool.
+:- import_module dir.
+:- import_module library.
+:- import_module list.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+mercury_std_library_module_name(unqualified(Name)) :-
+    mercury_std_library_module(Name).
+mercury_std_library_module_name(qualified(Module, Name)) :-
+    module_name_to_file_name(qualified(Module, Name), ModuleNameStr),
+    mercury_std_library_module(ModuleNameStr).
+mercury_std_library_module_name(qualified(Module, Name)) :-
+    strip_outermost_qualifier(qualified(Module, Name), "mercury", ModuleName),
+    module_name_to_file_name(ModuleName, ModuleNameStr),
+    mercury_std_library_module(ModuleNameStr).
+
+erlang_module_name(ModuleName) = ErlangModuleName :-
+    ( mercury_std_library_module_name(ModuleName) ->
+        ErlangModuleName= add_outermost_qualifier("mercury", ModuleName)
+    ;
+        ErlangModuleName= ModuleName
+    ).
+
+%-----------------------------------------------------------------------------%
+
+module_name_to_file_name(ModuleName, Ext, MkDir, FileName, !IO) :-
+    module_name_to_file_name_general(ModuleName, Ext,
+        do_not_search, MkDir, FileName, !IO).
+
+module_name_to_search_file_name(ModuleName, Ext, FileName, !IO) :-
+    module_name_to_file_name_general(ModuleName, Ext,
+        do_search, do_not_create_dirs, FileName, !IO).
+
+:- pred module_name_to_file_name_general(module_name::in, string::in,
+    maybe_search::in, maybe_create_dirs::in, file_name::out, io::di, io::uo)
+    is det.
+
+module_name_to_file_name_general(ModuleName0, Ext, Search, MkDir, FileName,
+        !IO) :-
+    ( Ext = ".m" ->
+        % Look up the module in the module->file mapping.
+        source_file_map.lookup_module_source_file(ModuleName0, FileName, !IO)
+    ;
+        (
+            ( string.suffix(Ext, ".erl")
+            ; string.suffix(Ext, ".hrl")
+            ; string.suffix(Ext, ".beam")
+            )
+        ->
+            % Erlang uses `.' as a package separator and expects a module
+            % `a.b.c' to be in a file `a/b/c.erl'.  Rather than that, we use
+            % a flat namespace with `__' as module separators.
+            Sep = "__",
+            ModuleName = erlang_module_name(ModuleName0)
+        ;
+            Sep = ".",
+            ModuleName = ModuleName0
+        ),
+        BaseName = sym_name_to_string_sep(ModuleName, Sep) ++ Ext,
+        choose_file_name(ModuleName, BaseName, Ext, Search, MkDir, FileName,
+            !IO)
+    ).
+
+module_name_to_lib_file_name(Prefix, ModuleName, Ext, MkDir, FileName, !IO) :-
+    BaseFileName = sym_name_to_string(ModuleName),
+    string.append_list([Prefix, BaseFileName, Ext], BaseName),
+    choose_file_name(ModuleName, BaseName, Ext, do_not_search, MkDir,
+        FileName, !IO).
+
+fact_table_file_name(ModuleName, FactTableFileName, Ext, MkDir, FileName,
+        !IO) :-
+    extra_link_obj_file_name(ModuleName, FactTableFileName, Ext, MkDir,
+        FileName, !IO).
+
+extra_link_obj_file_name(ModuleName, ExtraLinkObjName, Ext, MkDir, FileName,
+        !IO) :-
+    BaseName = ExtraLinkObjName ++ Ext,
+    choose_file_name(ModuleName, BaseName, Ext, do_not_search, MkDir,
+        FileName, !IO).
+
+:- pred choose_file_name(module_name::in, string::in, string::in,
+    maybe_search::in, maybe_create_dirs::in, file_name::out, io::di, io::uo)
+    is det.
+
+choose_file_name(_ModuleName, BaseName, Ext, Search, MkDir, FileName, !IO) :-
+    globals.io_get_globals(Globals, !IO),
+    globals.lookup_bool_option(Globals, use_subdirs, UseSubdirs),
+    globals.lookup_bool_option(Globals, use_grade_subdirs, UseGradeSubdirs),
+    globals.lookup_string_option(Globals, library_extension, LibExt),
+    globals.lookup_string_option(Globals, shared_library_extension,
+        SharedLibExt),
+    (
+        (
+            UseSubdirs = no
+        ;
+            % If we're searching for (rather than writing) a `.mih' file,
+            % use the plain file name.  This is so that searches for files
+            % in installed libraries will work.  `--c-include-directory' is
+            % set so that searches for files in the current directory will
+            % work.
+            % Similarly for `.hrl' files.  We set `--erlang-include-directory'
+            % for those.
+
+            Search = do_search,
+            ( Ext = ".mih"
+            ; Ext = ".mih.tmp"
+            ; Ext = ".hrl"
+            ; Ext = ".hrl.tmp"
+            )
+        )
+    ->
+        FileName = BaseName
+    ;
+        % The source files, the final executables, library files (including
+        % .init files) output files intended for use by the user, and phony
+        % Mmake targets names go in the current directory
+
+        \+ (
+            UseGradeSubdirs = yes,
+            file_is_arch_or_grade_dependent(Globals, Ext)
+        ),
+        (
+            % Executable files.
+            ( Ext = ""
+            ; Ext = ".exe"
+            ; Ext = ".dll"
+
+            % Library files.
+            ; Ext = ".a"
+            ; Ext = ".$A"
+            ; Ext = ".so"
+            ; Ext = ".dylib"
+            ; Ext = ".$(EXT_FOR_SHARED_LIB)"
+            ; Ext = ".jar"
+            ; Ext = ".beams"
+            ; Ext = ".init"
+
+            % mercury_update_interface requires the `.init.tmp' files to be
+            % in the same directory as the `.init' files.
+            ; Ext = ".init.tmp"
+
+            % output files intended for use by the user (the .h_dump* and
+            % .c_dump* MLDS dumps also fit into this category, but for
+            % efficiency, to keep this as a switch, we deal with them below).
+            ; Ext = ".mh"
+
+            % mercury_update_interface requires the `.mh.tmp' files to be
+            % in the same directory as the `.mh' files.
+            ; Ext = ".mh.tmp"
+            ; Ext = ".err"
+            ; Ext = ".ugly"
+            ; Ext = ".hlds_dump"
+            ; Ext = ".mlds_dump"
+            ; Ext = ".dependency_graph"
+            ; Ext = ".order"
+            % Mmake targets
+            ; Ext = ".clean"
+            ; Ext = ".realclean"
+            ; Ext = ".depend"
+            ; Ext = ".install_ints"
+            ; Ext = ".install_opts"
+            ; Ext = ".install_hdrs"
+            ; Ext = ".install_grade_hdrs"
+            ; Ext = ".check"
+            ; Ext = ".ints"
+            ; Ext = ".int3s"
+            ; Ext = ".ss"
+            ; Ext = ".pic_ss"
+            ; Ext = ".ils"
+            ; Ext = ".javas"
+            ; Ext = ".classes"
+            ; Ext = ".erls"
+            ; Ext = ".beams"
+            ; Ext = ".opts"
+            ; Ext = ".trans_opts"
+            )
+        ;
+            % Output files intended for use by the user.
+
+            ( string.prefix(Ext, ".c_dump")
+            ; string.prefix(Ext, ".mih_dump")
+            )
+        )
+    ->
+        FileName = BaseName
+    ;
+        % We need to handle a few cases specially.
+
+        (
+            ( Ext = ".dir/*.o"
+            ; Ext = ".dir/*.$O"
+            )
+        ->
+            SubDirName = "dirs"
+        ;
+            % .$O, .pic_o and .lpic_o files need to go in the same directory,
+            % so that using .$(EXT_FOR_PIC_OBJECTS) will work.
+            ( Ext = ".o"
+            ; Ext = ".$O"
+            ; Ext = ".lpic_o"
+            ; Ext = ".pic_o"
+            ; Ext = "$(EXT_FOR_PIC_OBJECTS)"
+            ; Ext = "_init.o"
+            ; Ext = "_init.$O"
+            ; Ext = "_init.lpic_o"
+            ; Ext = "_init.pic_o"
+            ; Ext = "_init.$(EXT_FOR_PIC_OBJECTS)"
+            )
+        ->
+            SubDirName = "os"
+        ;
+            % _init.c, _init.s, _init.o etc. files go in the cs, ss, os etc
+            % subdirectories.
+            string.append("_init.", ExtName, Ext)
+        ->
+            string.append(ExtName, "s", SubDirName)
+        ;
+            % .int.tmp, .opt.tmp, etc. files need to go in the ints, opts, etc
+            % subdirectories.
+            string.append(".", ExtName0, Ext),
+            string.remove_suffix(ExtName0, ".tmp", ExtName)
+        ->
+            string.append(ExtName, "s", SubDirName)
+        ;
+            % `.dv' files go in the `deps' subdirectory,
+            % along with the `.dep' files
+            Ext = ".dv"
+        ->
+            SubDirName = "deps"
+        ;
+            % Static and shared libraries go in the `lib' subdirectory.
+            ( Ext = LibExt
+            ; Ext = SharedLibExt
+            )
+        ->
+            SubDirName = "lib"
+        ;
+            % The usual case: `*.foo' files go in the `foos' subdirectory.
+            string.append(".", ExtName, Ext)
+        ->
+            string.append(ExtName, "s", SubDirName)
+        ;
+            Ext = ""
+        ->
+            SubDirName = "bin"
+        ;
+            string.append_list(["unknown extension `", Ext, "'"], ErrorMsg),
+            unexpected(this_file, ErrorMsg)
+        ),
+        make_file_name(SubDirName, Search, MkDir, BaseName, Ext, FileName, !IO)
+    ).
+
+file_name_to_module_name(FileName, ModuleName) :-
+    ModuleName = string_to_sym_name(FileName).
+
+module_name_to_file_name(ModuleName, FileName) :-
+    FileName = sym_name_to_string(ModuleName).
+
+module_name_to_make_var_name(ModuleName, MakeVarName) :-
+    MakeVarName = sym_name_to_string(ModuleName).
+
+:- pred make_file_name(dir_name::in, maybe_search::in, maybe_create_dirs::in,
+    file_name::in, string::in, file_name::out, io::di, io::uo) is det.
+
+make_file_name(SubDirName, Search, MkDir, BaseName, Ext, FileName, !IO) :-
+    globals.io_get_globals(Globals, !IO),
+    globals.lookup_bool_option(Globals, use_grade_subdirs, UseGradeSubdirs),
+    globals.lookup_string_option(Globals, fullarch, FullArch),
+    (
+        UseGradeSubdirs = yes,
+        file_is_arch_or_grade_dependent(Globals, Ext),
+
+        % If we're searching for (rather than writing) the file, just search
+        % in Mercury/<ext>s. This is so that searches for files in installed
+        % libraries work.  `--intermod-directories' is set so this will work.
+
+        \+ (
+            Search = do_search,
+            ( Ext = ".opt"
+            ; Ext = ".trans_opt"
+            ; Ext = ".analysis"
+            ; Ext = ".imdg"
+            ; Ext = ".request"
+            )
+        )
+    ->
+        grade_directory_component(Globals, Grade),
+
+        % The extra "Mercury" is needed so we can use `--intermod-directory
+        % Mercury/<grade>/<fullarch>' and `--c-include
+        % Mercury/<grade>/<fullarch>' to find the local `.opt' and `.mih'
+        % files without messing up the search for the files for installed
+        % libraries.
+        DirComponents = ["Mercury", Grade, FullArch, "Mercury", SubDirName]
+    ;
+        DirComponents = ["Mercury", SubDirName]
+    ),
+    (
+        MkDir = do_create_dirs,
+        DirName = dir.relative_path_name_from_components(DirComponents),
+        make_directory(DirName, _, !IO)
+    ;
+        MkDir = do_not_create_dirs
+    ),
+    Components = DirComponents ++ [BaseName],
+    FileName = dir.relative_path_name_from_components(Components).
+
+:- pred file_is_arch_or_grade_dependent(globals::in, string::in) is semidet.
+
+file_is_arch_or_grade_dependent(_, Ext) :-
+    file_is_arch_or_grade_dependent_2(Ext).
+file_is_arch_or_grade_dependent(Globals, Ext0) :-
+    string.append(Ext, ".tmp", Ext0), % for mercury_update_interface.
+    file_is_arch_or_grade_dependent(Globals, Ext).
+file_is_arch_or_grade_dependent(Globals, Ext) :-
+    globals.lookup_string_option(Globals, executable_file_extension, Ext).
+file_is_arch_or_grade_dependent(Globals, Ext) :-
+    (
+        globals.lookup_string_option(Globals,
+            object_file_extension, ObjExt)
+    ;
+        globals.lookup_string_option(Globals,
+            pic_object_file_extension, ObjExt)
+    ;
+        globals.lookup_string_option(Globals,
+            link_with_pic_object_file_extension, ObjExt)
+    ),
+    ( Ext = ObjExt
+    ; Ext = "_init" ++ ObjExt
+    ).
+file_is_arch_or_grade_dependent(Globals, Ext) :-
+    globals.lookup_string_option(Globals, library_extension, LibExt),
+    Ext = LibExt.
+file_is_arch_or_grade_dependent(Globals, Ext) :-
+    globals.lookup_string_option(Globals, shared_library_extension, Ext).
+
+:- pred file_is_arch_or_grade_dependent_2(string::in) is semidet.
+
+    % The `.used' file isn't grade dependent itself, but it contains
+    % information collected while compiling a grade-dependent `.c', `il',
+    % etc file.
+file_is_arch_or_grade_dependent_2(".used").
+file_is_arch_or_grade_dependent_2(".opt").
+file_is_arch_or_grade_dependent_2(".optdate").
+file_is_arch_or_grade_dependent_2(".trans_opt").
+file_is_arch_or_grade_dependent_2(".trans_opt_date").
+file_is_arch_or_grade_dependent_2(".analysis").
+file_is_arch_or_grade_dependent_2(".analysis_date").
+file_is_arch_or_grade_dependent_2(".imdg").
+file_is_arch_or_grade_dependent_2(".init").
+file_is_arch_or_grade_dependent_2(".request").
+file_is_arch_or_grade_dependent_2(".mih").
+file_is_arch_or_grade_dependent_2(".c").
+file_is_arch_or_grade_dependent_2(".c_date").
+file_is_arch_or_grade_dependent_2(".s").
+file_is_arch_or_grade_dependent_2(".s_date").
+file_is_arch_or_grade_dependent_2(".pic_s").
+file_is_arch_or_grade_dependent_2(".pic_s_date").
+file_is_arch_or_grade_dependent_2(".il").
+file_is_arch_or_grade_dependent_2(".il_date").
+file_is_arch_or_grade_dependent_2(".java").
+file_is_arch_or_grade_dependent_2(".java_date").
+file_is_arch_or_grade_dependent_2(".class").
+file_is_arch_or_grade_dependent_2(".erl").
+file_is_arch_or_grade_dependent_2(".erl_date").
+file_is_arch_or_grade_dependent_2(".beam").
+file_is_arch_or_grade_dependent_2(".beams").
+file_is_arch_or_grade_dependent_2(".hrl").
+file_is_arch_or_grade_dependent_2(".dir").
+file_is_arch_or_grade_dependent_2(".dll").
+file_is_arch_or_grade_dependent_2(".$A").
+file_is_arch_or_grade_dependent_2(".a").
+file_is_arch_or_grade_dependent_2("_init.c").
+file_is_arch_or_grade_dependent_2("_init.$O").
+file_is_arch_or_grade_dependent_2("_init.erl").
+file_is_arch_or_grade_dependent_2("_init.beam").
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "file_names.m".
+
+%-----------------------------------------------------------------------------%
+:- end_module parse_tree.file_names.
+%-----------------------------------------------------------------------------%
Index: compiler/file_util.m
===================================================================
RCS file: compiler/file_util.m
diff -N compiler/file_util.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/file_util.m	19 Jul 2008 03:49:35 -0000
@@ -0,0 +1,233 @@
+%-----------------------------------------------------------------------------e
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------e
+% Copyright (C) 2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: file_util.m.
+%
+% Utility predicates for operating on files that do not require any access
+% to the parse_tree package or anything above it.
+%
+%-----------------------------------------------------------------------------%
+
+:- module libs.file_util.
+:- interface.
+
+:- import_module bool.
+:- import_module io.
+:- import_module list.
+:- import_module maybe.
+
+%-----------------------------------------------------------------------------%
+
+:- type file_name == string.
+:- type dir_name == string.
+
+    % Open a source or interface file, returning `ok(FileInfo)' on success
+    % (where FileInfo is information about the file such as the file name
+    % or the directory in which it was found), or `error(Message)' on failure.
+:- type open_file(FileInfo) == pred(maybe_error(FileInfo), io, io).
+:- inst open_file == (pred(out, di, uo) is det).
+
+    % search_for_file(Dirs, FileName, FoundFileName, !IO):
+    %
+    % Search Dirs for FileName, opening the file if it is found,
+    % and returning the path name of the file that was found.
+    %
+:- pred search_for_file(list(dir_name)::in, file_name::in,
+    maybe_error(file_name)::out, io::di, io::uo) is det.
+
+    % search_for_file_returning_dir(Dirs, FileName, FoundDirName, !IO):
+    %
+    % Search Dirs for FileName, opening the file if it is found, and returning
+    % the name of the directory in which the file was found.
+    %
+:- pred search_for_file_returning_dir(list(dir_name)::in, file_name::in,
+    maybe_error(dir_name)::out, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % Write to a given filename, giving appropriate status messages
+    % and error messages if the file cannot be opened.
+    %
+:- pred output_to_file(string::in, pred(io, io)::in(pred(di, uo) is det),
+    io::di, io::uo) is det.
+
+    % Same as output_to_file/4 above, but allow the writing predicate
+    % to generate something, and if it succeeds, return its result.
+    %
+:- pred output_to_file_return_result(string::in,
+    pred(T, io, io)::in(pred(out, di, uo) is det),
+    maybe(T)::out, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % get_install_name_option(FileName, Option, !IO):
+    %
+    % Get the option string for setting the install-name of the shared library
+    % FileName. This is only used for systems which support the install-name
+    % option for shared libraries (such as Darwin).
+    %
+:- pred get_install_name_option(string::in, string::out, io::di, io::uo)
+    is det.
+
+%-----------------------------------------------------------------------------%
+
+:- pred maybe_report_stats(bool::in, io::di, io::uo) is det.
+:- pred maybe_write_string(bool::in, string::in, io::di, io::uo) is det.
+:- pred maybe_flush_output(bool::in, io::di, io::uo) is det.
+
+:- pred report_error(string::in, io::di, io::uo) is det.
+:- pred report_error_to_stream(io.output_stream::in, string::in,
+    io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.compiler_util.
+:- import_module libs.globals.
+:- import_module libs.handle_options.
+:- import_module libs.options.
+
+:- import_module dir.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+search_for_file(Dirs, FileName, Result, !IO) :-
+    search_for_file_returning_dir(Dirs, FileName, Result0, !IO),
+    (
+        Result0 = ok(Dir),
+        ( dir.this_directory(Dir) ->
+            PathName = FileName
+        ;
+            PathName = dir.make_path_name(Dir, FileName)
+        ),
+        Result = ok(PathName)
+    ;
+        Result0 = error(Message),
+        Result = error(Message)
+    ).
+
+search_for_file_returning_dir(Dirs, FileName, Result, !IO) :-
+    search_for_file_returning_dir_2(Dirs, FileName, MaybeDir, !IO),
+    (
+        MaybeDir = yes(Dir),
+        Result = ok(Dir)
+    ;
+        MaybeDir = no,
+        Msg = "cannot find `" ++ FileName ++ "' in directories " ++
+            string.join_list(", ", Dirs),
+        Result = error(Msg)
+    ).
+
+:- pred search_for_file_returning_dir_2(list(dir_name)::in,
+    file_name::in, maybe(dir_name)::out, io::di, io::uo) is det.
+
+search_for_file_returning_dir_2([], _FileName, no, !IO).
+search_for_file_returning_dir_2([Dir | Dirs], FileName, MaybeDir, !IO) :-
+    ( dir.this_directory(Dir) ->
+        ThisFileName = FileName
+    ;
+        ThisFileName = dir.make_path_name(Dir, FileName)
+    ),
+    io.see(ThisFileName, SeeResult0, !IO),
+    (
+        SeeResult0 = ok,
+        MaybeDir = yes(Dir)
+    ;
+        SeeResult0 = error(_),
+        search_for_file_returning_dir_2(Dirs, FileName, MaybeDir, !IO)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+output_to_file(FileName, Action, !IO) :-
+    NewAction = (pred(0::out, di, uo) is det --> Action),
+    output_to_file_return_result(FileName, NewAction, _Result, !IO).
+
+output_to_file_return_result(FileName, Action, Result, !IO) :-
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    globals.io_lookup_bool_option(statistics, Stats, !IO),
+    maybe_write_string(Verbose, "% Writing to file `", !IO),
+    maybe_write_string(Verbose, FileName, !IO),
+    maybe_write_string(Verbose, "'...\n", !IO),
+    maybe_flush_output(Verbose, !IO),
+    io.open_output(FileName, Res, !IO),
+    (
+        Res = ok(FileStream),
+        io.set_output_stream(FileStream, OutputStream, !IO),
+        Action(ActionResult, !IO),
+        io.set_output_stream(OutputStream, _, !IO),
+        io.close_output(FileStream, !IO),
+        maybe_write_string(Verbose, "% done.\n", !IO),
+        maybe_report_stats(Stats, !IO),
+        Result = yes(ActionResult)
+    ;
+        Res = error(_),
+        maybe_write_string(Verbose, "\n", !IO),
+        string.append_list(["can't open file `", FileName, "' for output."],
+            ErrorMessage),
+        report_error(ErrorMessage, !IO),
+        Result = no
+    ).
+
+%-----------------------------------------------------------------------------%
+
+% Changes to the following predicate may require similar changes to
+% make.program_target.install_library_grade_files/9.
+
+get_install_name_option(OutputFileName, InstallNameOpt, !IO) :-
+    globals.io_get_globals(Globals, !IO),
+    globals.lookup_string_option(Globals, shlib_linker_install_name_flag,
+        InstallNameFlag),
+    globals.lookup_string_option(Globals, shlib_linker_install_name_path,
+        InstallNamePath0),
+    ( InstallNamePath0 = "" ->
+        globals.lookup_string_option(Globals, install_prefix, InstallPrefix),
+        grade_directory_component(Globals, GradeDir),
+        InstallNamePath = InstallPrefix / "lib" / "mercury" / "lib" / GradeDir
+    ;
+        InstallNamePath = InstallNamePath0
+    ),
+    InstallNameOpt = InstallNameFlag ++ InstallNamePath / OutputFileName.
+
+%-----------------------------------------------------------------------------%
+
+maybe_report_stats(yes, !IO) :-
+    io.report_stats(!IO).
+maybe_report_stats(no, !IO).
+
+maybe_write_string(yes, String, !IO) :-
+    io.write_string(String, !IO).
+maybe_write_string(no, _, !IO).
+
+maybe_flush_output(yes, !IO) :-
+    io.flush_output(!IO).
+maybe_flush_output(no, !IO).
+
+report_error(ErrorMessage, !IO) :-
+    io.write_string("Error: ", !IO),
+    io.write_string(ErrorMessage, !IO),
+    io.write_string("\n", !IO),
+    io.set_exit_status(1, !IO).
+
+report_error_to_stream(Stream, ErrorMessage, !IO) :-
+    io.set_output_stream(Stream, OldStream, !IO),
+    report_error(ErrorMessage, !IO),
+    io.set_output_stream(OldStream, _, !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "file_util.m".
+
+%-----------------------------------------------------------------------------%
+:- end_module libs.file_util.
+%-----------------------------------------------------------------------------%
Index: compiler/higher_order.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/higher_order.m,v
retrieving revision 1.177
diff -u -b -r1.177 higher_order.m
--- compiler/higher_order.m	3 Apr 2008 05:26:43 -0000	1.177
+++ compiler/higher_order.m	18 Jul 2008 10:36:00 -0000
@@ -60,6 +60,7 @@
 :- import_module hlds.quantification.
 :- import_module hlds.special_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
Index: compiler/hlds_module.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_module.m,v
retrieving revision 1.159
diff -u -b -r1.159 hlds_module.m
--- compiler/hlds_module.m	5 Jun 2008 06:25:16 -0000	1.159
+++ compiler/hlds_module.m	19 Jul 2008 08:01:55 -0000
@@ -660,6 +660,8 @@
 :- implementation.
 
 :- import_module libs.compiler_util.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_imports.
 :- import_module parse_tree.prog_util.
 
 :- import_module assoc_list.
Index: compiler/hlds_pred.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/hlds_pred.m,v
retrieving revision 1.244
diff -u -b -r1.244 hlds_pred.m
--- compiler/hlds_pred.m	5 Jun 2008 06:25:16 -0000	1.244
+++ compiler/hlds_pred.m	18 Jul 2008 14:48:57 -0000
@@ -1071,7 +1071,7 @@
         ClassProofs, ClassConstraintMap, ClausesInfo, VarNameRemap,
         PredInfo) :-
     PredName = unqualify_name(SymName),
-    sym_name_get_module_name(SymName, ModuleName, PredModuleName),
+    sym_name_get_module_name_default(SymName, ModuleName, PredModuleName),
     type_vars_list(ArgTypes, TVars),
     list.delete_elems(TVars, ExistQVars, HeadTypeParams),
     Attributes = [],
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.232
diff -u -b -r1.232 intermod.m
--- compiler/intermod.m	16 Jul 2008 03:30:27 -0000	1.232
+++ compiler/intermod.m	19 Jul 2008 02:10:52 -0000
@@ -40,7 +40,7 @@
 
 :- import_module hlds.hlds_module.
 :- import_module parse_tree.error_util.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.module_imports.
 :- import_module parse_tree.prog_io.
 
 :- import_module bool.
@@ -107,15 +107,16 @@
 :- import_module hlds.pred_table.
 :- import_module hlds.special_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_item.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
 :- import_module transform_hlds.inlining.
@@ -143,7 +144,8 @@
     globals.io_set_option(line_numbers, bool(no), !IO),
 
     module_info_get_name(!.ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", yes, TmpName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_create_dirs,
+        TmpName, !IO),
     io.open_output(TmpName, Result, !IO),
     (
         Result = error(Err),
Index: compiler/libs.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/libs.m,v
retrieving revision 1.8
diff -u -b -r1.8 libs.m
--- compiler/libs.m	17 Nov 2005 15:57:20 -0000	1.8
+++ compiler/libs.m	18 Jul 2008 09:06:50 -0000
@@ -24,6 +24,7 @@
 % Generic algorithms and data structures that are not quite useful enough
 % to go in the standard library.
 :- include_module atsort.
+:- include_module file_util.
 :- include_module graph_colour.
 :- include_module tree.
 
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.326
diff -u -b -r1.326 llds_out.m
--- compiler/llds_out.m	2 Jun 2008 02:27:27 -0000	1.326
+++ compiler/llds_out.m	18 Jul 2008 16:01:42 -0000
@@ -190,6 +190,7 @@
 :- import_module ll_backend.layout_out.
 :- import_module ll_backend.pragma_c_gen.
 :- import_module ll_backend.rtti_out.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_foreign.
@@ -228,7 +229,7 @@
 
 output_llds(CFile, ComplexityProcs, StackLayoutLabels, !IO) :-
     ModuleName = CFile ^ cfile_modulename,
-    module_name_to_file_name(ModuleName, ".c", yes, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".c", do_create_dirs, FileName, !IO),
     io.open_output(FileName, Result, !IO),
     (
         Result = ok(FileStream),
@@ -287,7 +288,8 @@
         UserInitPredCNames, UserFinalPredCNames),
     library.version(Version),
     io.set_output_stream(FileStream, OutputStream, !IO),
-    module_name_to_file_name(ModuleName, ".m", no, SourceFileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+        SourceFileName, !IO),
     output_c_file_intro_and_grade(SourceFileName, Version, !IO),
     module_gather_env_var_names(Modules, set.init, EnvVarNameSet),
     EnvVarNames = set.to_sorted_list(EnvVarNameSet),
Index: compiler/make.dependencies.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.dependencies.m,v
retrieving revision 1.50
diff -u -b -r1.50 make.dependencies.m
--- compiler/make.dependencies.m	14 Jul 2008 02:09:37 -0000	1.50
+++ compiler/make.dependencies.m	19 Jul 2008 04:58:59 -0000
@@ -168,6 +168,8 @@
 
 :- implementation.
 
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 :- import_module transform_hlds.
 :- import_module transform_hlds.mmc_analysis.
@@ -1220,21 +1222,22 @@
     io.write_string(": dependencies could not be built.\n\t", !IO),
     io.write_list(UnbuiltDependencies, ",\n\t",
         (pred((DepTarget - DepStatus)::in, !.IO::di, !:IO::uo) is det :-
-            write_dependency_file(DepTarget, !IO),
+            make_write_dependency_file(DepTarget, !IO),
             io.write_string(" - ", !IO),
-            write_dependency_status(DepStatus, !IO)
+            make_write_dependency_status(DepStatus, !IO)
         ), !IO),
     io.nl(!IO).
 
-:- pred write_dependency_status(dependency_status::in, io::di, io::uo) is det.
+:- pred make_write_dependency_status(dependency_status::in, io::di, io::uo)
+    is det.
 
-write_dependency_status(deps_status_not_considered, !IO) :-
+make_write_dependency_status(deps_status_not_considered, !IO) :-
     io.write_string("deps_status_not_considered", !IO).
-write_dependency_status(deps_status_being_built, !IO) :-
+make_write_dependency_status(deps_status_being_built, !IO) :-
     io.write_string("deps_status_being_built", !IO).
-write_dependency_status(deps_status_up_to_date, !IO) :-
+make_write_dependency_status(deps_status_up_to_date, !IO) :-
     io.write_string("deps_status_up_to_date", !IO).
-write_dependency_status(deps_status_error, !IO) :-
+make_write_dependency_status(deps_status_error, !IO) :-
     io.write_string("deps_status_error", !IO).
 
 check_dependencies(TargetFileName, MaybeTimestamp, BuildDepsSucceeded,
@@ -1259,7 +1262,7 @@
             DepTimestamps, !Info, !IO),
 
         check_dependency_timestamps(TargetFileName, MaybeTimestamp,
-            BuildDepsSucceeded, DepFiles, write_dependency_file,
+            BuildDepsSucceeded, DepFiles, make_write_dependency_file,
             DepTimestamps, DepsResult, !IO)
     ).
 
@@ -1386,20 +1389,20 @@
                 compare((>), DepTimestamp, Timestamp)
             )
         ), NewerDeps),
-    write_dependency_file_and_timestamp_list(NewerDeps, !IO).
+    make_write_dependency_file_and_timestamp_list(NewerDeps, !IO).
 
-:- pred write_dependency_file_and_timestamp_list(
+:- pred make_write_dependency_file_and_timestamp_list(
     list({T, maybe_error(timestamp)})::in, io::di, io::uo) is det.
 
-write_dependency_file_and_timestamp_list([], !IO).
-write_dependency_file_and_timestamp_list([Head | Tail], !IO) :-
+make_write_dependency_file_and_timestamp_list([], !IO).
+make_write_dependency_file_and_timestamp_list([Head | Tail], !IO) :-
     Head = {DepFile, MaybeTimestamp},
     io.write_char('\t', !IO),
     io.write(DepFile, !IO),
     io.write_char(' ', !IO),
     io.write(MaybeTimestamp, !IO),
     io.nl(!IO),
-    write_dependency_file_and_timestamp_list(Tail, !IO).
+    make_write_dependency_file_and_timestamp_list(Tail, !IO).
 
 dependency_status(dep_file(FileName, _) @ Dep, Status, !Info, !IO) :-
     ( version_hash_table.search(!.Info ^ dependency_status, Dep, Status0) ->
@@ -1440,7 +1443,8 @@
                 % Targets from libraries are always considered to be
                 % up-to-date if they exist.
 
-                get_target_timestamp(yes, Target, MaybeTimestamp, !Info, !IO),
+                get_target_timestamp(do_search, Target, MaybeTimestamp,
+                    !Info, !IO),
                 (
                     MaybeTimestamp = ok(_),
                     Status = deps_status_up_to_date
@@ -1448,7 +1452,7 @@
                     MaybeTimestamp = error(Error),
                     Status = deps_status_error,
                     io.write_string("** Error: file `", !IO),
-                    write_target_file(Target, !IO),
+                    make_write_target_file(Target, !IO),
                     io.write_string("' not found: ", !IO),
                     io.write_string(Error, !IO),
                     io.nl(!IO)
Index: compiler/make.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.m,v
retrieving revision 1.54
diff -u -b -r1.54 make.m
--- compiler/make.m	14 Jul 2008 02:09:37 -0000	1.54
+++ compiler/make.m	19 Jul 2008 02:12:21 -0000
@@ -22,12 +22,12 @@
 :- include_module make.options_file.
 :- include_module make.util.
 
+:- import_module libs.file_util.
 :- import_module make.options_file.
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.
-:- import_module parse_tree.modules.
-:- import_module parse_tree.prog_io.
+:- import_module parse_tree.module_imports.
 
 :- import_module io.
 :- import_module list.
@@ -71,6 +71,7 @@
 :- import_module make.module_target.
 :- import_module make.program_target.
 :- import_module make.util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.error_util.
 :- import_module top_level.                 % XXX unwanted dependency
 :- import_module top_level.mercury_compile. % XXX unwanted dependency
Index: compiler/make.module_dep_file.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.module_dep_file.m,v
retrieving revision 1.34
diff -u -b -r1.34 make.module_dep_file.m
--- compiler/make.module_dep_file.m	16 Jul 2008 03:30:27 -0000	1.34
+++ compiler/make.module_dep_file.m	19 Jul 2008 08:03:05 -0000
@@ -17,7 +17,7 @@
 :- module make.module_dep_file.
 :- interface.
 
-:- import_module parse_tree.modules.
+:- import_module parse_tree.module_imports.
 
 :- import_module io.
 :- import_module maybe.
@@ -40,10 +40,15 @@
 :- implementation.
 
 :- import_module libs.globals.
+:- import_module libs.file_util.
 :- import_module libs.process_util.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
+:- import_module parse_tree.modules.
+:- import_module parse_tree.read_modules.
 :- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_item.
 :- import_module parse_tree.prog_out.
 
@@ -136,12 +141,13 @@
     % leading to an infinite loop. Just using module_name_to_file_name
     % will fail if the module name doesn't match the file name, but
     % that case is handled below.
-    module_name_to_file_name(ModuleName, ".m", no, SourceFileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+        SourceFileName, !IO),
     get_file_timestamp([dir.this_directory], SourceFileName,
         MaybeSourceFileTimestamp, !Info, !IO),
 
     module_name_to_file_name(ModuleName, make_module_dep_file_extension,
-        no, DepFileName, !IO),
+        do_not_create_dirs, DepFileName, !IO),
     globals.io_lookup_accumulating_option(search_directories, SearchDirs, !IO),
     get_file_timestamp(SearchDirs, DepFileName, MaybeDepFileTimestamp,
         !Info, !IO),
@@ -250,7 +256,7 @@
 do_write_module_dep_file(Imports, !IO) :-
     ModuleName = Imports ^ module_name,
     module_name_to_file_name(ModuleName, make_module_dep_file_extension,
-        yes, ProgDepFile, !IO),
+        do_create_dirs, ProgDepFile, !IO),
     io.open_output(ProgDepFile, ProgDepResult, !IO),
     (
         ProgDepResult = ok(ProgDepStream),
@@ -413,7 +419,7 @@
                 ContainsForeignExport = contains_foreign_export
             ;
                 ContainsForeignExportStr = "no_foreign_export",
-                ContainsForeignExport = no_foreign_export
+                ContainsForeignExport = contains_no_foreign_export
             ),
 
             HasMainTerm = term.functor(term.atom(HasMainStr), [], _),
@@ -423,7 +429,7 @@
         ->
             (
                 ForeignLanguages = [],
-                ContainsForeignCode = no_foreign_code
+                ContainsForeignCode = contains_no_foreign_code
             ;
                 ForeignLanguages = [_ | _],
                 ContainsForeignCode = contains_foreign_code(
@@ -512,7 +518,7 @@
 
 read_module_dependencies_remake_msg(ModuleName, Msg, !IO) :-
     module_name_to_file_name(ModuleName, make_module_dep_file_extension,
-        no, ModuleDepsFile, !IO),
+        do_not_create_dirs, ModuleDepsFile, !IO),
     io.write_string("Error reading file `", !IO),
     io.write_string(ModuleDepsFile, !IO),
     io.write_string("', rebuilding: ", !IO),
@@ -527,24 +533,22 @@
             sym_name_and_args(Arg, SymName, [])
         ), Args, SymNames).
 
-    % The module_name given must be the top level module in
-    % the source file. get_module_dependencies ensures this by
-    % making the dependencies for all parent modules of the
-    % requested module first.
+    % The module_name given must be the top level module in the source file.
+    % get_module_dependencies ensures this by making the dependencies
+    % for all parent modules of the requested module first.
+    %
 :- pred make_module_dependencies(module_name::in,
     make_info::in, make_info::out, io::di, io::uo) is det.
 
 make_module_dependencies(ModuleName, !Info, !IO) :-
-    Search = no,
-    ReturnTimestamp = yes,
-
     redirect_output(ModuleName, MaybeErrorStream, !Info, !IO),
     (
         MaybeErrorStream = yes(ErrorStream),
         io.set_output_stream(ErrorStream, OldOutputStream, !IO),
-        read_mod(ModuleName, ".m",
-            "Getting dependencies for module", Search, ReturnTimestamp,
-            Items, Error, SourceFileName, _, !IO),
+        % XXX Why ask for the timestamp if we then ignore it?
+        read_module(ModuleName, ".m", "Getting dependencies for module",
+            do_not_search, do_return_timestamp, Items, Error, SourceFileName,
+            _, !IO),
         ( Error = fatal_module_errors ->
             io.set_output_stream(OldOutputStream, _, !IO),
             io.write_string("** Error: error reading file `", !IO),
@@ -562,8 +566,8 @@
                 !IO),
             unredirect_output(ModuleName, ErrorStream, !Info, !IO),
             globals.io_set_option(output_compile_error_lines, int(Lines), !IO),
-            module_name_to_file_name(ModuleName, ".err", no, ErrFileName,
-                !IO),
+            module_name_to_file_name(ModuleName, ".err", do_not_create_dirs,
+                ErrFileName, !IO),
             io.remove_file(ErrFileName, _, !IO),
             !:Info = !.Info ^ module_dependencies ^ elem(ModuleName) := no
         ;
Index: compiler/make.module_target.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.module_target.m,v
retrieving revision 1.66
diff -u -b -r1.66 make.module_target.m
--- compiler/make.module_target.m	14 Jul 2008 02:09:37 -0000	1.66
+++ compiler/make.module_target.m	19 Jul 2008 05:18:43 -0000
@@ -70,10 +70,12 @@
 :- implementation.
 
 :- import_module analysis.
-:- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
 :- import_module libs.process_util.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_item.
 :- import_module parse_tree.prog_foreign.
 :- import_module transform_hlds.
 :- import_module transform_hlds.mmc_analysis.
@@ -174,12 +176,12 @@
 
                 debug_msg(
                    (pred(!.IO::di, !:IO::uo) is det :-
-                        write_target_file(TargetFile, !IO),
+                        make_write_target_file(TargetFile, !IO),
                         io.write_string(": dependencies:\n", !IO),
                         dependency_file_index_set_to_plain_set(!.Info,
                             DepFiles0, PlainSet),
-                        write_dependency_file_list(to_sorted_list(PlainSet),
-                            !IO)
+                        make_write_dependency_file_list(
+                            to_sorted_list(PlainSet), !IO)
                 ), !IO),
 
                 globals.io_lookup_bool_option(keep_going, KeepGoing, !IO),
@@ -236,7 +238,7 @@
             io.write_string("Error: circular dependency detected " ++
                 "while building\n", !IO),
             io.write_string("  `", !IO),
-            write_dependency_file(Dep, !IO),
+            make_write_dependency_file(Dep, !IO),
             io.write_string("'.\n", !IO),
             io.write_string("  This is due to a forbidden " ++
                 "foreign_import_module cycle.\n", !IO),
@@ -265,7 +267,7 @@
 
     % Check that the target files exist.
 
-    list.map_foldl2(get_target_timestamp(no), TouchedTargetFiles,
+    list.map_foldl2(get_target_timestamp(do_not_search), TouchedTargetFiles,
         TargetTimestamps, !Info, !IO),
     (
         MakeDepsSuccess = no,
@@ -305,7 +307,8 @@
                 MaybeOldestTimestamp = list.foldl(find_oldest_timestamp,
                     TouchedFileTimestamps, MaybeOldestTimestamp0),
 
-                get_file_name(no, TargetFile, TargetFileName, !Info, !IO),
+                get_file_name(do_not_search, TargetFile, TargetFileName,
+                    !Info, !IO),
                 check_dependencies(TargetFileName, MaybeOldestTimestamp,
                     MakeDepsSuccess, DepFilesToMake, DepsResult, !Info, !IO)
             )
@@ -484,7 +487,8 @@
         Succeeded, !IO).
 build_object_code(ModuleName, target_java, _, ErrorStream, _Imports, Succeeded,
         !IO) :-
-    module_name_to_file_name(ModuleName, ".java", yes, JavaFile, !IO),
+    module_name_to_file_name(ModuleName, ".java", do_create_dirs, JavaFile,
+        !IO),
     compile_target_code.compile_java_file(ErrorStream, JavaFile,
         Succeeded, !IO).
 build_object_code(ModuleName, target_il, _, ErrorStream, Imports, Succeeded,
@@ -496,7 +500,8 @@
     sorry(this_file, "NYI mmc --make and target x86_64").
 build_object_code(ModuleName, target_erlang, _, ErrorStream, _Imports,
         Succeeded, !IO) :-
-    module_name_to_file_name(ModuleName, ".erl", yes, ErlangFile, !IO),
+    module_name_to_file_name(ModuleName, ".erl", do_create_dirs, ErlangFile,
+        !IO),
     compile_target_code.compile_erlang_file(ErrorStream, ErlangFile,
         Succeeded, !IO).
 
@@ -555,8 +560,10 @@
         unexpected(this_file, "unsupported foreign language")
     ),
     ObjExt = get_object_extension(Globals, PIC),
-    module_name_to_file_name(ForeignModName, SrcExt, yes, SrcFileName, !IO),
-    module_name_to_file_name(ForeignModName, ObjExt, yes, ObjFileName, !IO),
+    module_name_to_file_name(ForeignModName, SrcExt, do_create_dirs,
+        SrcFileName, !IO),
+    module_name_to_file_name(ForeignModName, ObjExt, do_create_dirs,
+        ObjFileName, !IO),
     ForeignCodeFile = foreign_code_file(Lang, SrcFileName, ObjFileName).
 
 :- pred fact_table_foreign_code_file(module_name::in, pic::in, string::in,
@@ -566,8 +573,10 @@
         !IO) :-
     globals.io_get_globals(Globals, !IO),
     ObjExt = get_object_extension(Globals, PIC),
-    fact_table_file_name(ModuleName, FactTableName, ".c", yes, CFile, !IO),
-    fact_table_file_name(ModuleName, FactTableName, ObjExt, yes, ObjFile, !IO),
+    fact_table_file_name(ModuleName, FactTableName, ".c", do_create_dirs,
+        CFile, !IO),
+    fact_table_file_name(ModuleName, FactTableName, ObjExt, do_create_dirs,
+        ObjFile, !IO),
     ForeignCodeFile = foreign_code_file(lang_c, CFile, ObjFile).
 
 :- func get_object_extension(globals, pic) = string.
@@ -692,7 +701,7 @@
 
     list.foldl(update_target_status(TargetStatus), TouchedTargetFiles, !Info),
 
-    list.map_foldl2(get_file_name(no), TouchedTargetFiles,
+    list.map_foldl2(get_file_name(do_not_search), TouchedTargetFiles,
         TouchedTargetFileNames, !Info, !IO),
 
     some [!Timestamps] (
@@ -965,8 +974,8 @@
             is det :-
         TouchedTargetFile = target_file(TargetModuleName, TargetFileType),
         ( TimestampExt = timestamp_extension(Globals, TargetFileType) ->
-            module_name_to_file_name(TargetModuleName, TimestampExt, no,
-                TimestampFile, !IO),
+            module_name_to_file_name(TargetModuleName, TimestampExt,
+                do_not_create_dirs, TimestampFile, !IO),
             list.cons(TimestampFile, !TimestampFiles)
         ;
             true
@@ -988,14 +997,13 @@
     TargetFile = target_file(ModuleName, _),
     globals.io_get_globals(Globals, !IO),
     ObjExt = get_object_extension(Globals, PIC),
-    fact_table_file_name(ModuleName, FactTableName, ObjExt, yes,
+    fact_table_file_name(ModuleName, FactTableName, ObjExt, do_create_dirs,
         FactTableObjectFile, !IO).
 
 external_foreign_code_files(PIC, Imports, ForeignFiles, !IO) :-
-    %
     % Find externally compiled foreign code files for
     % `:- pragma foreign_proc' declarations.
-    %
+
     maybe_pic_object_file_extension(PIC, ObjExt, !IO),
     globals.io_get_target(CompilationTarget, !IO),
     ModuleName = Imports ^ module_name,
@@ -1006,10 +1014,10 @@
     ->
         module_name_to_file_name(
             foreign_language_module_name(ModuleName, lang_c),
-            ".c", no, CCodeFileName, !IO),
+            ".c", do_not_create_dirs, CCodeFileName, !IO),
         module_name_to_file_name(
             foreign_language_module_name(ModuleName, lang_c),
-            ObjExt, no, ObjFileName, !IO),
+            ObjExt, do_not_create_dirs, ObjFileName, !IO),
         ForeignFiles0 = [foreign_code_file(lang_c, CCodeFileName, ObjFileName)]
     ;
         CompilationTarget = target_il,
@@ -1022,9 +1030,7 @@
         ForeignFiles0 = []
     ),
 
-    %
     % Find externally compiled foreign code files for fact tables.
-    %
     (
         ( CompilationTarget = target_c
         ; CompilationTarget = target_asm
@@ -1033,9 +1039,9 @@
             (pred(FactTableFile::in, FactTableForeignFile::out, di, uo)
                     is det -->
                 fact_table_file_name(ModuleName, FactTableFile,
-                    ".c", no, FactTableCFile),
+                    ".c", do_not_create_dirs, FactTableCFile),
                 fact_table_file_name(ModuleName, FactTableFile,
-                    ObjExt, no, FactTableObjFile),
+                    ObjExt, do_not_create_dirs, FactTableObjFile),
                 { FactTableForeignFile = foreign_code_file(lang_c,
                     FactTableCFile, FactTableObjFile) }
             ), Imports ^ fact_table_deps, FactTableForeignFiles, !IO),
@@ -1058,9 +1064,9 @@
         ForeignModuleName = foreign_language_module_name(ModuleName, Language),
         ForeignExt = foreign_language_file_extension(Language)
     ->
-        module_name_to_file_name(ForeignModuleName, ForeignExt, yes,
+        module_name_to_file_name(ForeignModuleName, ForeignExt, do_create_dirs,
             ForeignFileName, !IO),
-        module_name_to_file_name(ForeignModuleName, ".dll", yes,
+        module_name_to_file_name(ForeignModuleName, ".dll", do_create_dirs,
             ForeignDLLFileName, !IO),
         ForeignFiles = [foreign_code_file(Language, ForeignFileName,
             ForeignDLLFileName)]
Index: compiler/make.program_target.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.program_target.m,v
retrieving revision 1.88
diff -u -b -r1.88 make.program_target.m
--- compiler/make.program_target.m	14 Jul 2008 02:09:37 -0000	1.88
+++ compiler/make.program_target.m	19 Jul 2008 04:52:30 -0000
@@ -40,12 +40,15 @@
 :- implementation.
 
 :- import_module analysis.
-:- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
 :- import_module libs.handle_options.
 :- import_module libs.process_util.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
+:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_io.
+:- import_module parse_tree.prog_item.
 :- import_module parse_tree.prog_out.
 :- import_module transform_hlds.
 :- import_module transform_hlds.mmc_analysis.
@@ -181,10 +184,10 @@
             ObjModules, ForeignObjTargetsList, !Info, !IO),
         ForeignObjTargets = list.condense(ForeignObjTargetsList),
 
-        % Ensure all interface files are present before continuing.  This
-        % prevents a problem when two parallel branches try to generate the
-        % same missing interface file later.
-        %
+        % Ensure all interface files are present before continuing.
+        % This prevents a problem when two parallel branches try to generate
+        % the same missing interface file later.
+
         make_all_interface_files(AllModulesList, IntsSucceeded, !Info, !IO),
         ( IntsSucceeded = no, KeepGoing = no ->
             BuildDepsSucceeded = no
@@ -469,8 +472,7 @@
     ;
         DepsResult = deps_up_to_date,
         MsgTarget = MainModuleName - linked_target(FileType),
-        globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs,
-            !IO),
+        globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
         (
             UseGradeSubdirs = yes,
             post_link_make_symlink_or_copy(ErrorStream,
@@ -534,8 +536,8 @@
         ),
         list.map_foldl(
             (pred(ObjModule::in, ObjToLink::out, !.IO::di, !:IO::uo) is det :-
-                module_name_to_file_name(ObjModule,
-                    ObjExtToUse, no, ObjToLink, !IO)
+                module_name_to_file_name(ObjModule, ObjExtToUse,
+                    do_not_create_dirs, ObjToLink, !IO)
             ), ObjModules, ObjList, !IO),
 
         % LinkObjects may contain `.a' files which must come
@@ -742,7 +744,10 @@
 build_analysis_files(MainModuleName, AllModules, Succeeded0, Succeeded,
         !Info, !IO) :-
     globals.io_lookup_bool_option(keep_going, KeepGoing, !IO),
-    ( Succeeded0 = no, KeepGoing = no ->
+    (
+        Succeeded0 = no,
+        KeepGoing = no
+    ->
         Succeeded = no
     ;
         % Ensure all interface files are present before continuing.  This
@@ -750,7 +755,10 @@
         % same missing interface file later.
         % (Although we can't actually build analysis files in parallel yet.)
         make_all_interface_files(AllModules, Succeeded1, !Info, !IO),
-        ( Succeeded1 = no, KeepGoing = no ->
+        (
+            Succeeded1 = no,
+            KeepGoing = no
+        ->
             Succeeded = no
         ;
             build_analysis_files_1(MainModuleName, AllModules,
@@ -928,14 +936,14 @@
             SharedLibsSupported = no,
             SharedLibsSucceeded = yes
         ),
-        % We can only build the .init file if we have succesfully
-        % built the .c files.
+        % We can only build the .init file if we have succesfully built
+        % the .c files.
         (
             SharedLibsSucceeded = yes,
             % Errors while making the .init file should be very rare.
             io.output_stream(ErrorStream, !IO),
-            make_library_init_file(ErrorStream, MainModuleName,
-                AllModules, Succeeded, !IO)
+            make_library_init_file(ErrorStream, MainModuleName, AllModules,
+                Succeeded, !IO)
         ;
             SharedLibsSucceeded = no,
             Succeeded = no 
@@ -964,8 +972,8 @@
         Succeeded0 = yes,
         % Errors while making the .init file should be very rare.
         io.output_stream(ErrorStream, !IO),
-        make_erlang_library_init_file(ErrorStream, MainModuleName,
-            AllModules, Succeeded, !IO)
+        make_erlang_library_init_file(ErrorStream, MainModuleName, AllModules,
+            Succeeded, !IO)
     ;
         Succeeded0 = no,
         Succeeded = no
@@ -1056,7 +1064,8 @@
             ),
             % XXX Should we test
             % Imports ^ contains_foreign_export = contains_foreign_export?
-            module_name_to_file_name(ModuleName, ".mh", no, FileName, !IO),
+            module_name_to_file_name(ModuleName, ".mh", do_not_create_dirs,
+                FileName, !IO),
             install_file(FileName, LibDir/"inc", HeaderSucceeded1, !IO),
 
             % This is needed so that the file will be found in Mmake's VPATH.
@@ -1066,7 +1075,8 @@
             HeaderSucceeded = HeaderSucceeded1 `and` HeaderSucceeded2
         ;
             Target = target_erlang,
-            module_name_to_file_name(ModuleName, ".hrl", no, FileName, !IO),
+            module_name_to_file_name(ModuleName, ".hrl", do_not_create_dirs,
+                FileName, !IO),
             install_file(FileName, LibDir/"inc", HeaderSucceeded, !IO)
         ;
             ( Target = target_java
@@ -1260,7 +1270,8 @@
 install_grade_init(GradeDir, ModuleName, Succeeded, !IO) :-
     globals.io_lookup_string_option(install_prefix, Prefix, !IO),
     GradeModulesDir = Prefix / "lib" / "mercury" / "modules" / GradeDir,
-    module_name_to_file_name(ModuleName, ".init", no, InitFileName, !IO),
+    module_name_to_file_name(ModuleName, ".init", do_not_create_dirs,
+        InitFileName, !IO),
     install_file(InitFileName, GradeModulesDir, Succeeded, !IO).
 
     % Install the `.opt', `.analysis' and `.mih' files for the current grade.
@@ -1291,8 +1302,7 @@
             install_subdir_file(LinkSucceeded, GradeIncDir, ModuleName, "mih",
                 HeaderSucceeded1, !IO),
 
-            % This is needed so that the file will be
-            % found in Mmake's VPATH.
+            % This is needed so that the file will be found in Mmake's VPATH.
             IntDir = LibDir/"ints",
             install_subdir_file(LinkSucceeded, IntDir, ModuleName, "mih",
                 HeaderSucceeded2, !IO),
@@ -1339,7 +1349,8 @@
 
 install_subdir_file(SubdirLinkSucceeded, InstallDir, ModuleName, Ext,
         Succeeded, !IO) :-
-    module_name_to_file_name(ModuleName, "." ++ Ext, no, FileName, !IO),
+    module_name_to_file_name(ModuleName, "." ++ Ext, do_not_create_dirs,
+        FileName, !IO),
     install_file(FileName, InstallDir, Succeeded1, !IO),
     (
         SubdirLinkSucceeded = no,
@@ -1358,11 +1369,10 @@
     globals.io_lookup_accumulating_option(lib_linkages, LibLinkages, !IO),
     ( list.member(Linkage, LibLinkages) ->
         install_file(FileName, InstallDir, Succeeded0, !IO),
-        %
+
         % We need to update the archive index after we copy a .a file to
         % the installation directory because the linkers on some OSs
         % complain if we don't.
-        % 
         (
             Linkage = "static",
             Succeeded0 = yes
@@ -1370,7 +1380,7 @@
             % Since mmc --make uses --use-subdirs the above FileName will
             % be directory qualified.  We don't care about the build
             % directory here so we strip that qualification off.
-            %
+
             BaseFileName = dir.det_basename(FileName),
             generate_archive_index(BaseFileName, InstallDir, Succeeded, !IO)
         ;
@@ -1549,8 +1559,7 @@
 make_grade_clean(ModuleName, AllModules, !Info, !IO) :-
     verbose_msg(
         (pred(!.IO::di, !:IO::uo) is det :-
-            io.write_string("Cleaning up grade-dependent files for `",
-                !IO),
+            io.write_string("Cleaning up grade-dependent files for `", !IO),
             write_sym_name(ModuleName, !IO),
             io.write_string("'in grade ", !IO),
             globals.io_get_globals(Globals, !IO),
@@ -1593,7 +1602,7 @@
     linked_target_file_name(ModuleName, erlang_archive,
         ThisDirErlangArchiveFileName, !IO),
     % XXX this symlink should not be necessary anymore for `mmc --make'
-    module_name_to_file_name(ModuleName, ".init", no,
+    module_name_to_file_name(ModuleName, ".init", do_not_create_dirs,
         ThisDirInitFileName, !IO),
     globals.io_set_option(use_grade_subdirs, bool(UseGradeSubdirs), !IO),
 
@@ -1657,7 +1666,7 @@
     list.foldl2(
         (pred(FactTableFile::in, !.Info::in, !:Info::out, di, uo) is det -->
             fact_table_file_name(ModuleName, FactTableFile,
-                ".c", no, FactTableCFile),
+                ".c", do_not_create_dirs, FactTableCFile),
             make_remove_file(very_verbose, FactTableCFile, !Info)
         ), FactTableFiles, !Info, !IO),
 
@@ -1791,9 +1800,9 @@
             io.format("Checking that %s is installed in grade `%s'.\n",
                 [s(LibName), s(Grade)], !IO)
         ), !IO),
-    % We check for the presence of a library in a particular grade by
-    % seeing whether its .init file.  This will work because all
-    % libraries have a grade dependent .init file.
+    % We check for the presence of a library in a particular grade by seeing
+    % whether its .init file exists.  This will work because all libraries
+    % have a grade dependent .init file.
     InitFileName = LibName ++ ".init",
     search_for_file(Dirs, InitFileName, SearchResult, !IO),
     (
Index: compiler/make.util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make.util.m,v
retrieving revision 1.59
diff -u -b -r1.59 make.util.m
--- compiler/make.util.m	14 Jul 2008 02:09:37 -0000	1.59
+++ compiler/make.util.m	19 Jul 2008 05:19:55 -0000
@@ -147,20 +147,20 @@
     % get_target_timestamp(Search, TargetFile, Timestamp)
     %
     % Find the timestamp for the given target file.
-    % `Search' should be `yes' if the file could be part of an
+    % `Search' should be `do_search' if the file could be part of an
     % installed library.
     %
-:- pred get_target_timestamp(bool::in, target_file::in,
+:- pred get_target_timestamp(maybe_search::in, target_file::in,
     maybe_error(timestamp)::out, make_info::in, make_info::out,
     io::di, io::uo) is det.
 
     % get_file_name(Search, TargetFile, FileName).
     %
     % Compute a file name for the given target file.
-    % `Search' should be `yes' if the file could be part of an
+    % `Search' should be `do_search' if the file could be part of an
     % installed library.
     %
-:- pred get_file_name(bool::in, target_file::in, file_name::out,
+:- pred get_file_name(maybe_search::in, target_file::in, file_name::out,
     make_info::in, make_info::out, io::di, io::uo) is det.
 
     % Find the timestamp of the first file matching the given
@@ -232,15 +232,18 @@
 %
 
     % Apply the given predicate if `--debug-make' is set.
+    % XXX Do we need this, now that we have trace goals?
     %
 :- pred debug_msg(pred(io, io)::(pred(di, uo) is det), io::di, io::uo) is det.
 
     % Apply the given predicate if `--verbose-make' is set.
+    % XXX Do we need this, now that we have trace goals?
     %
 :- pred verbose_msg(pred(io, io)::(pred(di, uo) is det),
     io::di, io::uo) is det.
 
     % Apply the given predicate if the given boolean option is set to `yes'.
+    % XXX Do we need this, now that we have trace goals?
     %
 :- pred verbose_msg(option::in, pred(io, io)::(pred(di, uo) is det),
     io::di, io::uo) is det.
@@ -249,12 +252,12 @@
     %
 :- pred debug_file_msg(target_file::in, string::in, io::di, io::uo) is det.
 
-:- pred write_dependency_file(dependency_file::in, io::di, io::uo) is det.
+:- pred make_write_dependency_file(dependency_file::in, io::di, io::uo) is det.
 
-:- pred write_dependency_file_list(list(dependency_file)::in, io::di, io::uo)
-    is det.
+:- pred make_write_dependency_file_list(list(dependency_file)::in,
+    io::di, io::uo) is det.
 
-:- pred write_target_file(target_file::in, io::di, io::uo) is det.
+:- pred make_write_target_file(target_file::in, io::di, io::uo) is det.
 
     % Write a message "Making <filename>" if `--verbose-make' is set.
     %
@@ -312,6 +315,7 @@
 :- import_module libs.compiler_util.
 :- import_module libs.handle_options.
 :- import_module libs.process_util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_foreign.
 :- import_module transform_hlds.
 :- import_module transform_hlds.mmc_analysis.
@@ -843,7 +847,8 @@
     io.open_input(TmpErrorFileName, TmpErrorInputRes, !IO),
     (
         TmpErrorInputRes = ok(TmpErrorInputStream),
-        module_name_to_file_name(ModuleName, ".err", yes, ErrorFileName, !IO),
+        module_name_to_file_name(ModuleName, ".err", do_create_dirs,
+            ErrorFileName, !IO),
         ( set.member(ModuleName, !.Info ^ error_file_modules) ->
             io.open_append(ErrorFileName, ErrorFileRes, !IO)
         ;
@@ -855,8 +860,8 @@
                 LinesToWrite, !IO),
             io.output_stream(CurrentOutputStream, !IO),
             io.input_stream_foldl2_io(TmpErrorInputStream,
-                write_error_char(ErrorFileOutputStream, CurrentOutputStream),
-                LinesToWrite, TmpFileInputRes, !IO),
+                make_write_error_char(ErrorFileOutputStream,
+                    CurrentOutputStream), LinesToWrite, TmpFileInputRes, !IO),
             (
                 TmpFileInputRes = ok(_)
             ;
@@ -891,10 +896,10 @@
     ),
     io.remove_file(TmpErrorFileName, _, !IO).
 
-:- pred write_error_char(io.output_stream::in, io.output_stream::in,
+:- pred make_write_error_char(io.output_stream::in, io.output_stream::in,
     char::in, int::in, int::out, io::di, io::uo) is det.
 
-write_error_char(FullOutputStream, PartialOutputStream, Char,
+make_write_error_char(FullOutputStream, PartialOutputStream, Char,
         !LinesRemaining, !IO) :-
     io.write_char(FullOutputStream, Char, !IO),
     ( !.LinesRemaining > 0 ->
@@ -922,20 +927,22 @@
         MaybeTimestamp, !Info, !IO) :-
     globals.io_get_globals(Globals, !IO),
     ( TimestampExt = timestamp_extension(Globals, FileType) ->
-        module_name_to_file_name(ModuleName, TimestampExt, no, FileName, !IO)
+        module_name_to_file_name(ModuleName, TimestampExt, do_not_create_dirs,
+            FileName, !IO)
     ;
-        module_target_to_file_name(ModuleName, FileType, no, FileName, !IO)
+        module_target_to_file_name(ModuleName, FileType, do_not_create_dirs,
+            FileName, !IO)
     ),
 
-    % We should only ever look for timestamp files
-    % in the current directory. Timestamp files are
-    % only used when processing a module, and only
-    % modules in the current directory are processed.
+    % We should only ever look for timestamp files in the current directory.
+    % Timestamp files are only used when processing a module, and only modules
+    % in the current directory are processed.
     SearchDirs = [dir.this_directory],
     get_file_timestamp(SearchDirs, FileName, MaybeTimestamp, !Info, !IO).
 
-get_dependency_timestamp(dep_file(FileName, MaybeOption), MaybeTimestamp,
-        !Info, !IO) :-
+get_dependency_timestamp(DependencyFile, MaybeTimestamp, !Info, !IO) :-
+    (
+        DependencyFile = dep_file(FileName, MaybeOption),
     (
         MaybeOption = yes(Option),
         globals.io_lookup_accumulating_option(Option, SearchDirs, !IO)
@@ -943,9 +950,10 @@
         MaybeOption = no,
         SearchDirs = [dir.this_directory]
     ),
-    get_file_timestamp(SearchDirs, FileName, MaybeTimestamp, !Info, !IO).
-get_dependency_timestamp(dep_target(Target), MaybeTimestamp, !Info, !IO) :-
-    get_target_timestamp(yes, Target, MaybeTimestamp0, !Info, !IO),
+        get_file_timestamp(SearchDirs, FileName, MaybeTimestamp, !Info, !IO)
+    ;
+        DependencyFile = dep_target(Target),
+        get_target_timestamp(do_search, Target, MaybeTimestamp0, !Info, !IO),
     (
         Target = target_file(_, module_target_c_header(header_mih)),
         MaybeTimestamp0 = ok(_)
@@ -958,6 +966,7 @@
         MaybeTimestamp = ok(oldest_timestamp)
     ;
         MaybeTimestamp = MaybeTimestamp0
+        )
     ).
 
 get_target_timestamp(Search, TargetFile, MaybeTimestamp, !Info, !IO) :-
@@ -975,9 +984,9 @@
     % `.analysis_status' file says the `.analysis' file is invalid then we
     % treat it as out of date.
     %
-:- pred get_target_timestamp_analysis_registry(bool::in, target_file::in,
-    file_name::in, maybe_error(timestamp)::out, make_info::in, make_info::out,
-    io::di, io::uo) is det.
+:- pred get_target_timestamp_analysis_registry(maybe_search::in,
+    target_file::in, file_name::in, maybe_error(timestamp)::out,
+    make_info::in, make_info::out, io::di, io::uo) is det.
 
 get_target_timestamp_analysis_registry(Search, TargetFile, FileName,
         MaybeTimestamp, !Info, !IO) :-
@@ -999,18 +1008,18 @@
         )
     ).
 
-:- pred get_target_timestamp_2(bool::in, target_file::in, file_name::in,
-    maybe_error(timestamp)::out, make_info::in, make_info::out,
+:- pred get_target_timestamp_2(maybe_search::in, target_file::in,
+    file_name::in, maybe_error(timestamp)::out, make_info::in, make_info::out,
     io::di, io::uo) is det.
 
 get_target_timestamp_2(Search, TargetFile, FileName, MaybeTimestamp,
         !Info, !IO) :-
     TargetFile = target_file(ModuleName, FileType),
     (
-        Search = yes,
+        Search = do_search,
         get_search_directories(FileType, SearchDirs, !IO)
     ;
-        Search = no,
+        Search = do_not_search,
         SearchDirs = [dir.this_directory]
     ),
     get_file_timestamp(SearchDirs, FileName, MaybeTimestamp0, !Info, !IO),
@@ -1055,7 +1064,8 @@
 
             % Something has gone wrong generating the dependencies,
             % so just take a punt (which probably won't work).
-            module_name_to_file_name(ModuleName, ".m", no, FileName, !IO)
+            module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+                FileName, !IO)
         )
     ;
         globals.io_get_globals(Globals, !IO),
@@ -1063,18 +1073,19 @@
         (
             MaybeExt = yes(Ext),
             (
-                Search = yes,
+                Search = do_search,
                 module_name_to_search_file_name_cache(ModuleName, Ext,
                     FileName, !Info, !IO)
             ;
-                Search = no,
+                Search = do_not_search,
                 % Not common enough to cache.
-                module_name_to_file_name(ModuleName, Ext, no, FileName, !IO)
+                module_name_to_file_name(ModuleName, Ext, do_not_create_dirs,
+                    FileName, !IO)
             )
         ;
             MaybeExt = no,
-            module_target_to_file_name_maybe_search(ModuleName, FileType, no,
-                Search, FileName, !IO)
+            module_target_to_file_name_maybe_search(ModuleName, FileType,
+                do_not_create_dirs, Search, FileName, !IO)
         )
     ).
 
@@ -1157,7 +1168,8 @@
 
 make_remove_target_file(VerboseOption, ModuleName, FileType, !Info, !IO) :-
     globals.io_get_globals(Globals, !IO),
-    module_target_to_file_name(ModuleName, FileType, no, FileName, !IO),
+    module_target_to_file_name(ModuleName, FileType, do_not_create_dirs,
+        FileName, !IO),
     make_remove_file(VerboseOption, FileName, !Info, !IO),
     ( TimestampExt = timestamp_extension(Globals, FileType) ->
         make_remove_file(VerboseOption, ModuleName, TimestampExt, !Info, !IO)
@@ -1166,7 +1178,8 @@
     ).
 
 make_remove_file(VerboseOption, ModuleName, Ext, !Info, !IO) :-
-    module_name_to_file_name(ModuleName, Ext, no, FileName, !IO),
+    module_name_to_file_name(ModuleName, Ext, do_not_create_dirs, FileName,
+        !IO),
     make_remove_file(VerboseOption, FileName, !Info, !IO).
 
 make_remove_file(VerboseOption, FileName, !Info, !IO) :-
@@ -1225,36 +1238,40 @@
 
 linked_target_file_name(ModuleName, executable, FileName, !IO) :-
     globals.io_lookup_string_option(executable_file_extension, Ext, !IO),
-    module_name_to_file_name(ModuleName, Ext, no, FileName, !IO).
+    module_name_to_file_name(ModuleName, Ext,
+        do_not_create_dirs, FileName, !IO).
 linked_target_file_name(ModuleName, static_library, FileName, !IO) :-
     globals.io_lookup_string_option(library_extension, Ext, !IO),
-    module_name_to_lib_file_name("lib", ModuleName, Ext, no, FileName, !IO).
+    module_name_to_lib_file_name("lib", ModuleName, Ext,
+        do_not_create_dirs, FileName, !IO).
 linked_target_file_name(ModuleName, shared_library, FileName, !IO) :-
     globals.io_lookup_string_option(shared_library_extension, Ext, !IO),
-    module_name_to_lib_file_name("lib", ModuleName, Ext, no, FileName, !IO).
+    module_name_to_lib_file_name("lib", ModuleName, Ext,
+        do_not_create_dirs, FileName, !IO).
 linked_target_file_name(ModuleName, java_archive, FileName, !IO) :-
-    module_name_to_file_name(ModuleName, ".jar", no, FileName, !IO).
+    module_name_to_file_name(ModuleName, ".jar",
+        do_not_create_dirs, FileName, !IO).
 linked_target_file_name(ModuleName, erlang_archive, FileName, !IO) :-
-    module_name_to_lib_file_name("lib", ModuleName, ".beams", no, FileName,
-        !IO).
+    module_name_to_lib_file_name("lib", ModuleName, ".beams",
+        do_not_create_dirs, FileName, !IO).
 
 :- pred module_target_to_file_name(module_name::in, module_target_type::in,
-    bool::in, file_name::out, io::di, io::uo) is det.
+    maybe_create_dirs::in, file_name::out, io::di, io::uo) is det.
 
 module_target_to_file_name(ModuleName, TargetType, MkDir, FileName, !IO) :-
-    module_target_to_file_name_maybe_search(ModuleName, TargetType, MkDir, no,
-        FileName, !IO).
+    module_target_to_file_name_maybe_search(ModuleName, TargetType, MkDir,
+        do_not_search, FileName, !IO).
 
 :- pred module_target_to_search_file_name(module_name::in,
     module_target_type::in, file_name::out, io::di, io::uo) is det.
 
 module_target_to_search_file_name(ModuleName, TargetType, FileName, !IO) :-
-    module_target_to_file_name_maybe_search(ModuleName, TargetType, no, yes,
-        FileName, !IO).
+    module_target_to_file_name_maybe_search(ModuleName, TargetType,
+        do_not_create_dirs, do_search, FileName, !IO).
 
 :- pred module_target_to_file_name_maybe_search(module_name::in,
-    module_target_type::in, bool::in, bool::in, file_name::out,
-    io::di, io::uo) is det.
+    module_target_type::in, maybe_create_dirs::in, maybe_search::in,
+    file_name::out, io::di, io::uo) is det.
 
 module_target_to_file_name_maybe_search(ModuleName, TargetType, MkDir, Search,
         FileName, !IO) :-
@@ -1263,10 +1280,10 @@
     (
         MaybeExt = yes(Ext),
         (
-            Search = yes,
+            Search = do_search,
             module_name_to_search_file_name(ModuleName, Ext, FileName, !IO)
         ;
-            Search = no,
+            Search = do_not_search,
             module_name_to_file_name(ModuleName, Ext, MkDir, FileName, !IO)
         )
     ;
@@ -1457,27 +1474,28 @@
 debug_file_msg(TargetFile, Msg, !IO) :-
     debug_msg(
         (pred(!.IO::di, !:IO::uo) is det :-
-            write_target_file(TargetFile, !IO),
+            make_write_target_file(TargetFile, !IO),
             io.write_string(": ", !IO),
             io.write_string(Msg, !IO),
             io.nl(!IO)
         ), !IO).
 
-write_dependency_file(dep_target(TargetFile), !IO) :-
-    write_target_file(TargetFile, !IO).
-write_dependency_file(dep_file(FileName, _), !IO) :-
+make_write_dependency_file(dep_target(TargetFile), !IO) :-
+    make_write_target_file(TargetFile, !IO).
+make_write_dependency_file(dep_file(FileName, _), !IO) :-
     io.write_string(FileName, !IO).
 
-write_dependency_file_list([], !IO).
-write_dependency_file_list([DepFile | DepFiles], !IO) :-
+make_write_dependency_file_list([], !IO).
+make_write_dependency_file_list([DepFile | DepFiles], !IO) :-
     io.write_string("\t", !IO),
-    write_dependency_file(DepFile, !IO),
+    make_write_dependency_file(DepFile, !IO),
     io.nl(!IO),
-    write_dependency_file_list(DepFiles, !IO).
+    make_write_dependency_file_list(DepFiles, !IO).
 
-write_target_file(TargetFile, !IO) :-
+make_write_target_file(TargetFile, !IO) :-
     TargetFile = target_file(ModuleName, FileType),
-    module_target_to_file_name(ModuleName, FileType, no, FileName, !IO),
+    module_target_to_file_name(ModuleName, FileType, do_not_create_dirs,
+        FileName, !IO),
     io.write_string(FileName, !IO).
 
 maybe_make_linked_target_message(TargetFile, !IO) :-
@@ -1497,7 +1515,7 @@
         (pred(!.IO::di, !:IO::uo) is det :-
             io.set_output_stream(OutputStream, OldOutputStream, !IO),
             io.write_string("Making ", !IO),
-            write_target_file(TargetFile, !IO),
+            make_write_target_file(TargetFile, !IO),
             io.nl(!IO),
             io.set_output_stream(OldOutputStream, _, !IO)
         ), !IO).
@@ -1513,7 +1531,7 @@
 
 target_file_error(TargetFile, !IO) :-
     io.write_string("** Error making `", !IO),
-    write_target_file(TargetFile, !IO),
+    make_write_target_file(TargetFile, !IO),
     io.write_string("'.\n", !IO).
 
 file_error(TargetFile, !IO) :-
@@ -1527,7 +1545,7 @@
         Warn = yes,
         ( set.member(Target, !.Info ^ command_line_targets) ->
             io.write_string("** Nothing to be done for `", !IO),
-            write_module_or_linked_target(Target, !IO),
+            make_write_module_or_linked_target(Target, !IO),
             io.write_string("'.\n", !IO)
         ;
             true
@@ -1542,18 +1560,18 @@
     verbose_msg(
         (pred(!.IO::di, !:IO::uo) is det :-
             io.write_string("Made symlink/copy of ", !IO),
-            write_module_or_linked_target(Target, !IO),
+            make_write_module_or_linked_target(Target, !IO),
             io.write_string("\n", !IO)
         ), !IO).
 
-:- pred write_module_or_linked_target(pair(module_name, target_type)::in,
+:- pred make_write_module_or_linked_target(pair(module_name, target_type)::in,
     io::di, io::uo) is det.
 
-write_module_or_linked_target(ModuleName - FileType, !IO) :-
+make_write_module_or_linked_target(ModuleName - FileType, !IO) :-
     (
         FileType = module_target(ModuleTargetType),
         TargetFile = target_file(ModuleName, ModuleTargetType),
-        write_target_file(TargetFile, !IO)
+        make_write_target_file(TargetFile, !IO)
     ;
         FileType = linked_target(LinkedTargetType),
         linked_target_file_name(ModuleName, LinkedTargetType, FileName, !IO),
Index: compiler/make_hlds_passes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/make_hlds_passes.m,v
retrieving revision 1.79
diff -u -b -r1.79 make_hlds_passes.m
--- compiler/make_hlds_passes.m	16 Jul 2008 03:30:27 -0000	1.79
+++ compiler/make_hlds_passes.m	18 Jul 2008 16:12:12 -0000
@@ -114,6 +114,7 @@
 :- import_module hlds.pred_table.
 :- import_module hlds.special_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module parse_tree.prog_data.
Index: compiler/maybe_mlds_to_gcc.pp
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/maybe_mlds_to_gcc.pp,v
retrieving revision 1.11
diff -u -b -r1.11 maybe_mlds_to_gcc.pp
--- compiler/maybe_mlds_to_gcc.pp	23 Feb 2006 09:36:56 -0000	1.11
+++ compiler/maybe_mlds_to_gcc.pp	19 Jul 2008 08:53:54 -0000
@@ -55,7 +55,7 @@
 
 #else
 
-:- import_module parse_tree.prog_out.
+:- import_module libs.file_util.
 :- import_module string.
 
 maybe_mlds_to_gcc__run_gcc_backend(_ModuleName, CallBack, CallBackOutput) -->
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.475
diff -u -b -r1.475 mercury_compile.m
--- compiler/mercury_compile.m	16 Jul 2008 03:30:27 -0000	1.475
+++ compiler/mercury_compile.m	19 Jul 2008 08:04:45 -0000
@@ -37,16 +37,18 @@
 
 :- implementation.
 
-    %
-    % the main compiler passes (mostly in order of execution)
-    %
+    % The main compiler passes (mostly in order of execution).
 
-    % semantic analysis
+    % Semantic analysis.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_out.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_imports.
 :- import_module parse_tree.modules.
+:- import_module parse_tree.read_modules.
 :- import_module parse_tree.source_file_map.
+:- import_module parse_tree.write_deps_file.
 :- import_module parse_tree.prog_event.
 :- import_module parse_tree.module_qual.
 :- import_module parse_tree.equiv_type.
@@ -64,7 +66,7 @@
 :- import_module check_hlds.stratify.
 :- import_module check_hlds.simplify.
 
-    % high-level HLDS transformations
+    % High-level HLDS transformations.
 :- import_module check_hlds.check_typeclass.
 :- import_module transform_hlds.intermod.
 :- import_module transform_hlds.trans_opt.
@@ -106,7 +108,7 @@
 
 :- import_module transform_hlds.rbmm.
 
-    % the LLDS back-end
+    % The LLDS back-end.
 :- import_module ll_backend.continuation_info.
 :- import_module ll_backend.dupproc.
 :- import_module ll_backend.follow_code.
@@ -123,7 +125,7 @@
 :- import_module ll_backend.store_alloc.
 :- import_module ll_backend.transform_llds.
 
-    % the bytecode back-end
+    % The bytecode back-end.
 :- import_module bytecode_backend.bytecode_gen.
 :- import_module bytecode_backend.bytecode.
 
@@ -133,7 +135,7 @@
 :- import_module ll_backend.llds_to_x86_64_out.
 %:- import_module ll_backend.x86_64_instrs.
 
-    % the MLDS back-end
+    % The MLDS back-end.
 :- import_module ml_backend.add_trail_ops.         % HLDS -> HLDS
 :- import_module ml_backend.add_heap_ops.          % HLDS -> HLDS
 :- import_module ml_backend.mark_static_terms.     % HLDS -> HLDS
@@ -149,13 +151,13 @@
 :- import_module ml_backend.maybe_mlds_to_gcc.     % MLDS -> GCC back-end
 :- import_module ml_backend.ml_util.               % MLDS utility predicates
 
-    % the Erlang back-end
+    % The Erlang back-end.
 :- import_module erl_backend.elds.
 :- import_module erl_backend.elds_to_erlang.
 :- import_module erl_backend.erl_code_gen.
 :- import_module erl_backend.erl_rtti.
 
-    % miscellaneous compiler modules
+    % Miscellaneous compiler modules.
 :- import_module check_hlds.goal_path.
 :- import_module check_hlds.inst_check.
 :- import_module check_hlds.unused_imports.
@@ -174,6 +176,7 @@
 :- import_module mdbcomp.program_representation.
 :- import_module parse_tree.error_util.
 :- import_module parse_tree.mercury_to_mercury.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_item.
 :- import_module recompilation.
@@ -181,11 +184,11 @@
 :- import_module recompilation.usage.
 :- import_module transform_hlds.dependency_graph.
 
-    % inter-module analysis framework
+    % Inter-module analysis framework.
 :- import_module analysis.
 :- import_module transform_hlds.mmc_analysis.
 
-    % compiler library modules
+    % Compiler library modules.
 :- import_module backend_libs.base_typeclass_info.
 :- import_module backend_libs.compile_target_code.
 :- import_module backend_libs.export.
@@ -195,13 +198,14 @@
 :- import_module backend_libs.type_class_info.
 :- import_module backend_libs.type_ctor_info.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.handle_options.
 :- import_module libs.options.
 :- import_module libs.timestamp.
 :- import_module libs.trace_params.
 
-    % library modules
+    % Library modules.
 :- import_module assoc_list.
 :- import_module benchmarking.
 :- import_module bool.
@@ -640,10 +644,11 @@
         file_name_to_module_name(Module, ModuleName),
         globals.io_lookup_bool_option(pic, Pic, !IO),
         AsmExt = (Pic = yes -> ".pic_s" ; ".s"),
-        module_name_to_file_name(ModuleName, AsmExt, yes, AsmFile, !IO),
+        module_name_to_file_name(ModuleName, AsmExt, do_create_dirs,
+            AsmFile, !IO),
         ( ModuleName \= FirstModuleName ->
-            module_name_to_file_name(FirstModuleName, AsmExt, no, FirstAsmFile,
-                !IO),
+            module_name_to_file_name(FirstModuleName, AsmExt,
+                do_not_create_dirs, FirstAsmFile, !IO),
             do_rename_file(FirstAsmFile, AsmFile, Result, !IO)
         ;
             Result = ok
@@ -934,8 +939,8 @@
     file_name_to_module_name(FileName, ModuleName).
 file_or_module_to_module_name(fm_module(ModuleName)) = ModuleName.
 
-:- pred read_module_or_file(file_or_module::in, bool::in, module_name::out,
-    file_name::out, maybe(timestamp)::out, list(item)::out,
+:- pred read_module_or_file(file_or_module::in, maybe_return_timestamp::in,
+    module_name::out, file_name::out, maybe(timestamp)::out, list(item)::out,
     module_error::out, read_modules::in, read_modules::out,
     io::di, io::uo) is det.
 
@@ -951,20 +956,19 @@
         % Avoid rereading the module if it was already read
         % by recompilation_version.m.
         find_read_module(!.ReadModules, ModuleName, ".m", ReturnTimestamp,
-            Items0, MaybeTimestamp0, Error0, FileName0)
+            ItemsPrime, MaybeTimestampPrime, ErrorPrime, FileNamePrime)
     ->
         map.delete(!.ReadModules, ModuleName - ".m", !:ReadModules),
-        FileName = FileName0,
-        Items = Items0,
-        Error = Error0,
-        MaybeTimestamp = MaybeTimestamp0
+        FileName = FileNamePrime,
+        Items = ItemsPrime,
+        Error = ErrorPrime,
+        MaybeTimestamp = MaybeTimestampPrime
     ;
         % We don't search `--search-directories' for source files
         % because that can result in the generated interface files
         % being created in the wrong directory.
-        Search = no,
-        read_mod(ModuleName, ".m", "Reading module", Search, ReturnTimestamp,
-            Items, Error, FileName, MaybeTimestamp, !IO)
+        read_module(ModuleName, ".m", "Reading module", do_not_search,
+            ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO)
     ),
     globals.io_lookup_bool_option(statistics, Stats, !IO),
     maybe_report_stats(Stats, !IO).
@@ -980,19 +984,18 @@
         % Avoid rereading the module if it was already read
         % by recompilation_version.m.
         find_read_module(!.ReadModules, DefaultModuleName, ".m",
-            ReturnTimestamp, Items0, MaybeTimestamp0, Error0, _)
+            ReturnTimestamp, ItemsPrime, MaybeTimestampPrime, ErrorPrime, _)
     ->
         map.delete(!.ReadModules, ModuleName - ".m", !:ReadModules),
         ModuleName = DefaultModuleName,
-        Items = Items0,
-        Error = Error0,
-        MaybeTimestamp = MaybeTimestamp0
+        Items = ItemsPrime,
+        Error = ErrorPrime,
+        MaybeTimestamp = MaybeTimestampPrime
     ;
         % We don't search `--search-directories' for source files
         % because that can result in the generated interface files
         % being created in the wrong directory.
-        Search = no,
-        read_mod_from_file(FileName, ".m", "Reading file", Search,
+        read_module_from_file(FileName, ".m", "Reading file", do_not_search,
             ReturnTimestamp, Items, Error, ModuleName, MaybeTimestamp, !IO),
 
         % XXX If the module name doesn't match the file name, the compiler
@@ -1030,6 +1033,11 @@
     maybe_report_stats(Stats, !IO),
     string.append(FileName, ".m", SourceFileName).
 
+:- func version_numbers_return_timestamp(bool) = maybe_return_timestamp.
+
+version_numbers_return_timestamp(no) = do_not_return_timestamp.
+version_numbers_return_timestamp(yes) = do_return_timestamp.
+
 :- pred process_module(options_variables::in, list(string)::in,
     file_or_module::in, list(string)::out, list(string)::out,
     io::di, io::uo) is det.
@@ -1050,13 +1058,15 @@
     (
         ( MakeInterface = yes ->
             ProcessModule = make_interface,
-            ReturnTimestamp = GenerateVersionNumbers
+            ReturnTimestamp =
+                version_numbers_return_timestamp(GenerateVersionNumbers)
         ; MakeShortInterface = yes ->
             ProcessModule = make_short_interface,
-            ReturnTimestamp = no
+            ReturnTimestamp = do_not_return_timestamp
         ; MakePrivateInterface = yes ->
             ProcessModule = make_private_interface,
-            ReturnTimestamp = GenerateVersionNumbers
+            ReturnTimestamp =
+                version_numbers_return_timestamp(GenerateVersionNumbers)
         ;
             fail
         )
@@ -1068,6 +1078,7 @@
             true
         ;
             split_into_submodules(ModuleName, Items, SubModuleList, [], Specs),
+            % XXX _NumErrors
             write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors,
                 !IO),
             list.foldl(apply_process_module(ProcessModule,
@@ -1078,13 +1089,13 @@
     ;
         ConvertToMercury = yes
     ->
-        read_module_or_file(FileOrModule, no, ModuleName, _, _, Items, Error,
-            map.init, _, !IO),
+        read_module_or_file(FileOrModule, do_not_return_timestamp,
+            ModuleName, _, _, Items, Error, map.init, _, !IO),
         ( halt_at_module_error(HaltSyntax, Error) ->
             true
         ;
-            module_name_to_file_name(ModuleName, ".ugly", yes, OutputFileName,
-                !IO),
+            module_name_to_file_name(ModuleName, ".ugly", do_create_dirs,
+                OutputFileName, !IO),
             convert_to_mercury(ModuleName, OutputFileName, Items, !IO)
         ),
         ModulesToLink = [],
@@ -1180,8 +1191,9 @@
 
 process_module_2(FileOrModule, MaybeModulesToRecompile, ReadModules0,
         ModulesToLink, FactTableObjFiles, !IO) :-
-    read_module_or_file(FileOrModule, yes, ModuleName, FileName,
-        MaybeTimestamp, Items, Error, ReadModules0, ReadModules, !IO),
+    read_module_or_file(FileOrModule, do_return_timestamp,
+        ModuleName, FileName, MaybeTimestamp, Items, Error,
+        ReadModules0, ReadModules, !IO),
     globals.io_get_globals(Globals, !IO),
     globals.lookup_bool_option(Globals, halt_at_syntax_errors, HaltSyntax),
     ( halt_at_module_error(HaltSyntax, Error) ->
@@ -1366,7 +1378,8 @@
         % in the `.s' file of the top-level module.
         TargetFiles = []
     ;
-        module_name_to_file_name(ModuleName, TargetSuffix, yes, FileName, !IO),
+        module_name_to_file_name(ModuleName, TargetSuffix, do_create_dirs,
+            FileName, !IO),
         TargetFiles = [FileName]
     ).
 
@@ -1418,8 +1431,8 @@
         % the `.s' file of the top-level module.
         TimestampFiles = []
     ;
-        module_name_to_file_name(ModuleName, TimestampSuffix, yes, FileName,
-            !IO),
+        module_name_to_file_name(ModuleName, TimestampSuffix, do_create_dirs,
+            FileName, !IO),
         TimestampFiles = [FileName]
     ).
 
@@ -1601,7 +1614,8 @@
     % is interrupted after the new output file is written but before the new
     % `.used' file is written.
 
-    module_name_to_file_name(ModuleName, ".used", no, UsageFileName, !IO),
+    module_name_to_file_name(ModuleName, ".used", do_not_create_dirs,
+        UsageFileName, !IO),
     io.remove_file(UsageFileName, _, !IO),
 
     module_info_get_num_errors(!.HLDS, NumErrors),
@@ -1647,8 +1661,8 @@
             ;
                 TargetCodeOnly = no,
                 io.output_stream(OutputStream, !IO),
-                module_name_to_file_name(ModuleName, ".java", no, JavaFile,
-                    !IO),
+                module_name_to_file_name(ModuleName, ".java",
+                    do_not_create_dirs, JavaFile, !IO),
                 compile_target_code.compile_java_file(OutputStream, JavaFile,
                     Succeeded, !IO),
                 maybe_set_exit_status(Succeeded, !IO)
@@ -1687,12 +1701,13 @@
                     TargetCodeOnly = yes
                 ;
                     TargetCodeOnly = no,
-                    module_name_to_file_name(ModuleName, ".c", no, C_File,
-                        !IO),
+                    module_name_to_file_name(ModuleName, ".c",
+                        do_not_create_dirs, C_File, !IO),
                     get_linked_target_type(TargetType, !IO),
                     get_object_code_type(TargetType, PIC, !IO),
                     maybe_pic_object_file_extension(PIC, Obj, !IO),
-                    module_name_to_file_name(ModuleName, Obj, yes, O_File, !IO),
+                    module_name_to_file_name(ModuleName, Obj,
+                        do_create_dirs, O_File, !IO),
                     io.output_stream(OutputStream, !IO),
                     compile_target_code.compile_c_file(OutputStream, PIC,
                         C_File, O_File, CompileOK, !IO),
@@ -1745,9 +1760,11 @@
     get_linked_target_type(TargetType, !IO),
     get_object_code_type(TargetType, PIC, !IO),
     maybe_pic_object_file_extension(PIC, Obj, !IO),
-    module_name_to_file_name(ModuleName, ".c", no, CCode_C_File, !IO),
+    module_name_to_file_name(ModuleName, ".c", do_not_create_dirs,
+        CCode_C_File, !IO),
     ForeignModuleName = foreign_language_module_name(ModuleName, lang_c),
-    module_name_to_file_name(ForeignModuleName, Obj, yes, CCode_O_File, !IO),
+    module_name_to_file_name(ForeignModuleName, Obj, do_create_dirs,
+        CCode_O_File, !IO),
     io.output_stream(OutputStream, !IO),
     compile_target_code.compile_c_file(OutputStream, PIC,
         CCode_C_File, CCode_O_File, CompileOK, !IO),
@@ -1919,7 +1936,8 @@
     maybe_write_string(Verbose, "% Module qualifying items...\n", !IO),
     maybe_flush_output(Verbose, !IO),
     globals.io_get_globals(Globals, !IO),
-    module_name_to_file_name(ModuleName, ".m", no, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+        FileName, !IO),
     module_qualify_items(Items0, Items, EventSpecMap0, EventSpecMap,
         Globals, ModuleName, yes(FileName), EventSpecFileName, MQInfo,
         UndefTypes, UndefModes, [], Specs),
@@ -2365,7 +2383,8 @@
             true
         ),
         module_info_get_name(!.HLDS, ModuleName),
-        module_name_to_file_name(ModuleName, ".opt", yes, OptName, !IO),
+        module_name_to_file_name(ModuleName, ".opt", do_create_dirs,
+            OptName, !IO),
         update_interface(OptName, !IO),
         touch_interface_datestamp(ModuleName, ".optdate", !IO)
     ;
@@ -3606,8 +3625,8 @@
         ShowDepGraph = yes,
         maybe_write_string(Verbose, "% Writing dependency graph...", !IO),
         module_info_get_name(!.HLDS, ModuleName),
-        module_name_to_file_name(ModuleName, ".dependency_graph", yes,
-            FileName, !IO),
+        module_name_to_file_name(ModuleName, ".dependency_graph",
+            do_create_dirs, FileName, !IO),
         io.open_output(FileName, Res, !IO),
         (
             Res = ok(FileStream),
@@ -3645,7 +3664,8 @@
             "% Outputing profiling call graph...", !IO),
         maybe_flush_output(Verbose, !IO),
         module_info_get_name(!.HLDS, ModuleName),
-        module_name_to_file_name(ModuleName, ".prof", yes, ProfFileName, !IO),
+        module_name_to_file_name(ModuleName, ".prof", do_create_dirs,
+            ProfFileName, !IO),
         io.open_output(ProfFileName, Res, !IO),
         (
             Res = ok(FileStream),
@@ -3819,15 +3839,16 @@
         bytecode_gen.gen_module(HLDS1, _HLDS2, Bytecode, !IO),
         maybe_write_string(Verbose, "% done.\n", !IO),
         maybe_report_stats(Stats, !IO),
-        module_name_to_file_name(ModuleName, ".bytedebug", yes, BytedebugFile,
-            !IO),
+        module_name_to_file_name(ModuleName, ".bytedebug", do_create_dirs,
+            BytedebugFile, !IO),
         maybe_write_string(Verbose, "% Writing bytecodes to `", !IO),
         maybe_write_string(Verbose, BytedebugFile, !IO),
         maybe_write_string(Verbose, "'...", !IO),
         maybe_flush_output(Verbose, !IO),
         debug_bytecode_file(BytedebugFile, Bytecode, !IO),
         maybe_write_string(Verbose, " done.\n", !IO),
-        module_name_to_file_name(ModuleName, ".mbc", yes, BytecodeFile, !IO),
+        module_name_to_file_name(ModuleName, ".mbc", do_create_dirs,
+            BytecodeFile, !IO),
         maybe_write_string(Verbose, "% Writing bytecodes to `", !IO),
         maybe_write_string(Verbose, BytecodeFile, !IO),
         maybe_write_string(Verbose, "'...", !IO),
@@ -4867,7 +4888,7 @@
 output_llds(ModuleName, LLDS0, ComplexityProcs, StackLayoutLabels,
         Verbose, Stats, !IO) :-
     maybe_write_string(Verbose, "% Writing output to `", !IO),
-    module_name_to_file_name(ModuleName, ".c", yes, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".c", do_create_dirs, FileName, !IO),
     maybe_write_string(Verbose, FileName, !IO),
     maybe_write_string(Verbose, "'...", !IO),
     maybe_flush_output(Verbose, !IO),
@@ -4884,8 +4905,9 @@
     get_linked_target_type(LinkedTargetType, !IO),
     get_object_code_type(LinkedTargetType, PIC, !IO),
     maybe_pic_object_file_extension(PIC, Obj, !IO),
-    module_name_to_file_name(ModuleName, ".c", no, C_File, !IO),
-    module_name_to_file_name(ModuleName, Obj, yes, O_File, !IO),
+    module_name_to_file_name(ModuleName, ".c", do_not_create_dirs,
+        C_File, !IO),
+    module_name_to_file_name(ModuleName, Obj, do_create_dirs, O_File, !IO),
     compile_target_code.compile_c_file(ErrorStream, PIC, C_File, O_File,
         Succeeded, !IO).
 
@@ -5156,8 +5178,8 @@
     StageNumStr = stage_num_str(StageNum),
     ( should_dump_stage(StageNum, StageNumStr, StageName, DumpHLDSStages) ->
         module_info_get_name(HLDS, ModuleName),
-        module_name_to_file_name(ModuleName, ".hlds_dump", yes, BaseFileName,
-            !IO),
+        module_name_to_file_name(ModuleName, ".hlds_dump", do_create_dirs,
+            BaseFileName, !IO),
         DumpFileName = BaseFileName ++ "." ++ StageNumStr ++ "-" ++ StageName
             ++ UserFileSuffix,
         (
@@ -5185,7 +5207,7 @@
         !:DumpInfo = prev_dumped_hlds(CurDumpFileName, HLDS)
     ; should_dump_stage(StageNum, StageNumStr, StageName, DumpTraceStages) ->
         module_info_get_name(HLDS, ModuleName),
-        module_name_to_file_name(ModuleName, ".trace_counts", yes,
+        module_name_to_file_name(ModuleName, ".trace_counts", do_create_dirs,
             BaseFileName, !IO),
         DumpFileName = BaseFileName ++ "." ++ StageNumStr ++ "-" ++ StageName
             ++ UserFileSuffix,
@@ -5289,8 +5311,8 @@
     ( should_dump_stage(StageNum, StageNumStr, StageName, VerboseDumpStages) ->
         maybe_write_string(Verbose, "% Dumping out raw MLDS...\n", !IO),
         ModuleName = mlds_get_module_name(MLDS),
-        module_name_to_file_name(ModuleName, ".mlds_dump", yes, BaseFileName,
-            !IO),
+        module_name_to_file_name(ModuleName, ".mlds_dump", do_create_dirs,
+            BaseFileName, !IO),
         string.append_list([BaseFileName, ".", StageNumStr, "-", StageName],
             DumpFile),
         dump_mlds(DumpFile, MLDS, !IO),
Index: compiler/mlds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds.m,v
retrieving revision 1.163
diff -u -b -r1.163 mlds.m
--- compiler/mlds.m	11 Feb 2008 21:26:03 -0000	1.163
+++ compiler/mlds.m	18 Jul 2008 07:56:35 -0000
@@ -1775,7 +1775,7 @@
 :- import_module hlds.hlds_data.
 :- import_module libs.compiler_util.
 :- import_module libs.globals.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
 
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.229
diff -u -b -r1.229 mlds_to_c.m
--- compiler/mlds_to_c.m	11 Feb 2008 21:26:03 -0000	1.229
+++ compiler/mlds_to_c.m	18 Jul 2008 16:25:26 -0000
@@ -81,8 +81,8 @@
 :- import_module hlds.code_model.
 :- import_module hlds.hlds_data.
 :- import_module hlds.hlds_pred.         % for pred_proc_id.
-:- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
@@ -92,6 +92,8 @@
                                          % handles derived classes
 :- import_module ml_backend.ml_type_gen. % for ml_gen_type_name
 :- import_module ml_backend.ml_util.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_foreign.
@@ -132,7 +134,8 @@
 
 output_c_file(MLDS, Suffix, !IO) :-
     ModuleName = mlds_get_module_name(MLDS),
-    module_name_to_file_name(ModuleName, ".c" ++ Suffix, yes, SourceFile, !IO),
+    module_name_to_file_name(ModuleName, ".c" ++ Suffix, do_create_dirs,
+        SourceFile, !IO),
     Indent = 0,
     output_to_file(SourceFile, mlds_output_src_file(Indent, MLDS), !IO).
 
@@ -145,10 +148,10 @@
     % changed.
 
     ModuleName = mlds_get_module_name(MLDS),
-    module_name_to_file_name(ModuleName, ".mih" ++ Suffix ++ ".tmp", yes,
-        TmpHeaderFile, !IO),
-    module_name_to_file_name(ModuleName, ".mih" ++ Suffix, yes,
-        HeaderFile, !IO),
+    module_name_to_file_name(ModuleName, ".mih" ++ Suffix ++ ".tmp",
+        do_create_dirs, TmpHeaderFile, !IO),
+    module_name_to_file_name(ModuleName, ".mih" ++ Suffix,
+        do_create_dirs, HeaderFile, !IO),
     Indent = 0,
     output_to_file(TmpHeaderFile, mlds_output_hdr_file(Indent, MLDS), !IO),
     update_interface(HeaderFile, !IO).
@@ -523,7 +526,8 @@
 
 mlds_output_auto_gen_comment(ModuleName, !IO) :-
     library.version(Version),
-    module_name_to_file_name(ModuleName, ".m", no, SourceFileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+        SourceFileName, !IO),
     output_c_file_intro_and_grade(SourceFileName, Version, !IO),
     io.nl(!IO).
 
Index: compiler/mlds_to_gcc.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds_to_gcc.m,v
retrieving revision 1.138
diff -u -b -r1.138 mlds_to_gcc.m
--- compiler/mlds_to_gcc.m	11 Feb 2008 21:26:04 -0000	1.138
+++ compiler/mlds_to_gcc.m	18 Jul 2008 11:40:50 -0000
@@ -157,19 +157,20 @@
 :- import_module backend_libs.rtti.		% for rtti.addr_to_string.
 :- import_module hlds.code_model.
 :- import_module hlds.hlds_pred.	% for proc_id_to_int and invalid_pred_id
+:- import_module libs.file_util.
 :- import_module libs.compiler_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
-:- import_module ml_backend.ml_code_util.% for ml_gen_public_field_decl_flags,
-				% which is used by the code that handles
-				% derived classes
+:- import_module ml_backend.ml_code_util.
+	% For ml_gen_public_field_decl_flags, which is used by the code
+	% that handles derived classes.
 :- import_module ml_backend.ml_util.
 :- import_module ml_backend.mlds_to_c.	% to handle C foreign_code
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_foreign.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 
 :- import_module int.
@@ -193,8 +194,10 @@
 		PicExt = ".s",
 		PicOpt = ""
 	},
-	module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
-	module_name_to_file_name(ModuleName, PicExt, yes, AsmFileName),
+	module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+		SourceFileName),
+	module_name_to_file_name(ModuleName, PicExt, do_create_dirs,
+		AsmFileName),
 	% XXX should use new gcc_* options rather than
 	% reusing cflags, c_optimize
 	globals__io_lookup_bool_option(statistics, Statistics),
Index: compiler/mlds_to_ilasm.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds_to_ilasm.m,v
retrieving revision 1.39
diff -u -b -r1.39 mlds_to_ilasm.m
--- compiler/mlds_to_ilasm.m	25 Jul 2007 06:12:23 -0000	1.39
+++ compiler/mlds_to_ilasm.m	18 Jul 2008 16:46:11 -0000
@@ -33,15 +33,16 @@
 
 :- implementation.
 
-:- import_module hlds.passes_aux.
+% :- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module ml_backend.ilasm.
 :- import_module ml_backend.il_peephole.
 :- import_module ml_backend.mlds_to_il.
 :- import_module ml_backend.mlds_to_managed.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_foreign.
 
 :- import_module bool.
@@ -54,8 +55,10 @@
 
 output_mlds(MLDS, !IO) :-
     ModuleName = mlds_get_module_name(MLDS),
-    module_name_to_file_name(ModuleName, ".il", yes, ILAsmFile, !IO),
-    output_to_file(ILAsmFile, output_assembler(MLDS), Result, !IO),
+    module_name_to_file_name(ModuleName, ".il", do_create_dirs,
+        ILAsmFile, !IO),
+    output_to_file_return_result(ILAsmFile, output_assembler(MLDS), Result,
+        !IO),
 
     (
         Result = yes(ForeignLangs),
@@ -81,7 +84,7 @@
     ->
         handle_foreign_lang(ForeignLang, CodeGenerator),
         module_name_to_file_name(ForeignModuleName, Extension,
-            yes, File, !IO),
+            do_create_dirs, File, !IO),
         output_to_file(File,
             (pred(di, uo) is det --> CodeGenerator(MLDS)), !IO)
     ;
Index: compiler/mlds_to_java.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mlds_to_java.m,v
retrieving revision 1.102
diff -u -b -r1.102 mlds_to_java.m
--- compiler/mlds_to_java.m	11 Feb 2008 21:26:04 -0000	1.102
+++ compiler/mlds_to_java.m	18 Jul 2008 16:29:18 -0000
@@ -106,8 +106,8 @@
 :- import_module backend_libs.rtti.
 :- import_module check_hlds.type_util.
 :- import_module hlds.hlds_pred.           % for pred_proc_id.
-:- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
@@ -115,7 +115,7 @@
 :- import_module ml_backend.ml_code_util.  % for ml_gen_local_var_decl_flags.
 :- import_module ml_backend.ml_type_gen.   % for ml_gen_type_name
 :- import_module ml_backend.ml_util.
-:- import_module parse_tree.modules.       % for mercury_std_library_name.
+:- import_module parse_tree.file_names.    % for mercury_std_library_name.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_out.
@@ -142,8 +142,8 @@
     % that's why we don't call mercury_module_name_to_mlds here.
     ModuleName = mlds_get_module_name(MLDS),
     JavaSafeModuleName = valid_module_name(ModuleName),
-    module_name_to_file_name(JavaSafeModuleName, ".java", yes, JavaSourceFile,
-        !IO),
+    module_name_to_file_name(JavaSafeModuleName, ".java", do_create_dirs,
+        JavaSourceFile, !IO),
     Indent = 0,
     output_to_file(JavaSourceFile,
         output_java_src_file(ModuleInfo, Indent, MLDS), !IO).
@@ -1143,7 +1143,8 @@
 
 output_auto_gen_comment(ModuleName, !IO)  :-
     library.version(Version),
-    module_name_to_file_name(ModuleName, ".m", no, SourceFileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+        SourceFileName, !IO),
     io.write_string("//\n//\n// Automatically generated from ", !IO),
     io.write_string(SourceFileName, !IO),
     io.write_string(" by the Mercury Compiler,\n", !IO),
Index: compiler/mmc_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mmc_analysis.m,v
retrieving revision 1.25
diff -u -b -r1.25 mmc_analysis.m
--- compiler/mmc_analysis.m	5 Jun 2008 06:25:17 -0000	1.25
+++ compiler/mmc_analysis.m	18 Jul 2008 16:46:58 -0000
@@ -45,12 +45,12 @@
 
 :- import_module hlds.pred_table.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_io.
-:- import_module parse_tree.prog_out.
 :- import_module transform_hlds.ctgc.
 :- import_module transform_hlds.ctgc.structure_sharing.
 :- import_module transform_hlds.ctgc.structure_sharing.analysis.
@@ -114,7 +114,7 @@
     maybe_error(string)::out, io::di, io::uo) is det.
 
 mmc_module_name_to_read_file_name(ModuleName, Ext, MaybeFileName, !IO) :-
-    modules.module_name_to_search_file_name(ModuleName, Ext, FileName0, !IO),
+    module_name_to_search_file_name(ModuleName, Ext, FileName0, !IO),
     globals.io_lookup_accumulating_option(intermod_directories, Dirs, !IO),
     search_for_file(Dirs, FileName0, MaybeFileName, !IO),
     (
@@ -129,7 +129,7 @@
     string::out, io::di, io::uo) is det.
 
 mmc_module_name_to_write_file_name(ModuleName, Ext, FileName, !IO) :-
-    module_name_to_file_name(ModuleName, Ext, yes, FileName, !IO).
+    module_name_to_file_name(ModuleName, Ext, do_create_dirs, FileName, !IO).
 
 module_name_func_id(ModuleInfo, proc(PredId, ProcId), PredModule, FuncId) :-
     module_info_pred_info(ModuleInfo, PredId, PredInfo),
Index: compiler/mode_constraints.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_constraints.m,v
retrieving revision 1.47
diff -u -b -r1.47 mode_constraints.m
--- compiler/mode_constraints.m	27 Feb 2008 07:23:10 -0000	1.47
+++ compiler/mode_constraints.m	18 Jul 2008 11:31:24 -0000
@@ -73,6 +73,7 @@
 % :- import_module mode_robdd.tfeir.
 :- import_module mode_robdd.tfeirn.
 :- import_module parse_tree.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_mode.
@@ -191,9 +192,8 @@
 dump_abstract_constraints(ModuleInfo, ConstraintVarset, ModeConstraints,
         !IO) :-
     hlds_module.module_info_get_name(ModuleInfo, ModuleName),
-    CreateDirectories = yes,
-    parse_tree.modules.module_name_to_file_name(ModuleName,
-        ".mode_constraints", CreateDirectories, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".mode_constraints", do_create_dirs,
+        FileName, !IO),
     OutputFile = FileName,
 
     io.open_output(OutputFile, IOResult, !IO),
Index: compiler/mode_debug.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/mode_debug.m,v
retrieving revision 1.30
diff -u -b -r1.30 mode_debug.m
--- compiler/mode_debug.m	23 Nov 2007 07:35:15 -0000	1.30
+++ compiler/mode_debug.m	18 Jul 2008 10:03:33 -0000
@@ -35,12 +35,13 @@
 
 :- implementation.
 
+:- import_module libs.
+:- import_module libs.file_util.
 :- import_module hlds.
 :- import_module hlds.instmap.
 :- import_module parse_tree.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 
 :- import_module assoc_list.
 :- import_module bool.
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.368
diff -u -b -r1.368 modes.m
--- compiler/modes.m	16 Jul 2008 03:30:28 -0000	1.368
+++ compiler/modes.m	18 Jul 2008 16:47:46 -0000
@@ -377,6 +377,7 @@
 :- import_module hlds.special_pred.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.
Index: compiler/module_cmds.m
===================================================================
RCS file: compiler/module_cmds.m
diff -N compiler/module_cmds.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/module_cmds.m	18 Jul 2008 15:59:31 -0000
@@ -0,0 +1,878 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: module_cmds.m.
+%
+% This module handles the most of the commands generated by the
+% parse_tree package.
+%
+%-----------------------------------------------------------------------------%
+
+:- module parse_tree.module_cmds.
+:- interface.
+
+:- import_module mdbcomp.prim_data.
+:- import_module libs.file_util.
+
+:- import_module bool.
+:- import_module io.
+:- import_module maybe.
+
+%-----------------------------------------------------------------------------%
+
+    % update_interface_return_succeeded(FileName, Succeeded):
+    %
+    % Call the shell script mercury_update_interface to update the
+    % interface file FileName from FileName.tmp if it has changed.
+    %
+:- pred update_interface_return_succeeded(file_name::in, bool::out,
+    io::di, io::uo) is det.
+
+:- pred update_interface(file_name::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % copy_file(Source, Destination, Succeeded).
+    %
+    % XXX This belongs in the standard library.
+    %
+:- pred copy_file(file_name::in, file_name::in, io.res::out,
+    io::di, io::uo) is det.
+
+    % maybe_make_symlink(TargetFile, LinkName, Result):
+    %
+    % If `--use-symlinks' is set, attempt to make LinkName a symlink
+    % pointing to LinkTarget.
+    %
+:- pred maybe_make_symlink(file_name::in, file_name::in, bool::out,
+    io::di, io::uo) is det.
+
+    % make_symlink_or_copy_file(LinkTarget, LinkName, Succeeded):
+    %
+    % Attempt to make LinkName a symlink pointing to LinkTarget, copying
+    % LinkTarget to LinkName if that fails (or if `--use-symlinks' is not set).
+    %
+:- pred make_symlink_or_copy_file(file_name::in, file_name::in, bool::out,
+    io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % touch_interface_datestamp(ModuleName, Ext):
+    %
+    % Touch the datestamp file `ModuleName.Ext'. Datestamp files are used
+    % to record when each of the interface files was last updated.
+    %
+:- pred touch_interface_datestamp(module_name::in, string::in,
+    io::di, io::uo) is det.
+
+    % touch_datestamp(FileName):
+    %
+    % Update the modification time for the given file,
+    % clobbering the contents of the file.
+    %
+:- pred touch_datestamp(file_name::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % If the bool is `no', set the exit status to 1.
+    %
+:- pred maybe_set_exit_status(bool::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- type quote_char
+    --->    forward     % '
+    ;       double.     % "
+
+:- type command_verbosity
+    --->    cmd_verbose
+            % Output the command line only with `--verbose'.
+
+    ;       cmd_verbose_commands.
+            % Output the command line with `--verbose-commands'. This should be
+            % used for commands that may be of interest to the user.
+
+    % invoke_system_command(ErrorStream, Verbosity, Command, Succeeded)
+    %
+    % Invoke an executable. Both standard and error output will go to the
+    % specified output stream.
+    %
+:- pred invoke_system_command(io.output_stream::in,
+    command_verbosity::in, string::in, bool::out, io::di, io::uo) is det.
+
+    % invoke_system_command_maybe_filter_output(ErrorStream, Verbosity,
+    %   Command, MaybeProcessOutput, Succeeded)
+    %
+    % Invoke an executable. Both standard and error output will go to the
+    % specified output stream after being piped through `ProcessOutput'
+    % if MaybeProcessOutput is yes(ProcessOutput).
+    %
+:- pred invoke_system_command_maybe_filter_output(io.output_stream::in,
+    command_verbosity::in, string::in, maybe(string)::in, bool::out,
+    io::di, io::uo) is det.
+
+    % Make a command string, which needs to be invoked in a shell environment.
+    %
+:- pred make_command_string(string::in, quote_char::in, string::out) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Java command-line tools utilities
+%
+
+    % Create a shell script with the same name as the given module to invoke
+    % Java with the appropriate options on the class of the same name.
+    %
+:- pred create_java_shell_script(module_name::in, bool::out,
+    io::di, io::uo) is det.
+
+    % Strip away the path prefix for a list of .class files.
+    %
+:- pred list_class_files_for_jar(module_name::in, string::in, string::out,
+    io::di, io::uo) is det.
+
+    % Get the value of the Java class path from the environment. (Normally
+    % it will be obtained from the CLASSPATH environment variable, but if
+    % that isn't present then the java.class.path variable may be used instead.
+    % This is used for the Java back-end, which doesn't support environment
+    % variables properly.)
+    %
+:- pred get_env_classpath(string::out, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+%
+% Erlang utilities
+%
+
+    % Create a shell script with the same name as the given module to invoke
+    % the Erlang runtime system and execute the main/2 predicate in that
+    % module.
+    %
+:- pred create_erlang_shell_script(module_name::in, bool::out, io::di, io::uo)
+    is det.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.compiler_util.
+:- import_module libs.process_util.
+:- import_module libs.globals.
+:- import_module libs.handle_options.   % for grade_directory_component
+:- import_module libs.options.
+:- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
+
+:- import_module dir.
+:- import_module list.
+:- import_module getopt_io.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+update_interface(OutputFileName, !IO) :-
+    update_interface_return_succeeded(OutputFileName, Succeeded, !IO),
+    (
+        Succeeded = no,
+        report_error("problem updating interface files.", !IO)
+    ;
+        Succeeded = yes
+    ).
+
+update_interface_return_succeeded(OutputFileName, Succeeded, !IO) :-
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    maybe_write_string(Verbose, "% Updating interface:\n", !IO),
+    TmpOutputFileName = OutputFileName ++ ".tmp",
+    io.open_binary_input(OutputFileName, OutputFileRes, !IO),
+    (
+        OutputFileRes = ok(OutputFileStream),
+        io.open_binary_input(TmpOutputFileName, TmpOutputFileRes, !IO),
+        (
+            TmpOutputFileRes = ok(TmpOutputFileStream),
+            binary_input_stream_cmp(OutputFileStream, TmpOutputFileStream,
+                FilesDiffer, !IO),
+            io.close_binary_input(OutputFileStream, !IO),
+            io.close_binary_input(TmpOutputFileStream, !IO),
+            (
+                FilesDiffer = ok(ok(no)),
+                Succeeded = yes,
+                maybe_write_string(Verbose, "% ", !IO),
+                maybe_write_string(Verbose, OutputFileName, !IO),
+                maybe_write_string(Verbose, "' has not changed.\n", !IO),
+                io.remove_file(TmpOutputFileName, _, !IO)
+            ;
+                FilesDiffer = ok(ok(yes)),
+                update_interface_create_file("CHANGED", OutputFileName,
+                    TmpOutputFileName, Succeeded, !IO)
+            ;
+                FilesDiffer = ok(error(TmpFileError)),
+                Succeeded = no,
+                io.write_string("Error reading `", !IO),
+                io.write_string(TmpOutputFileName, !IO),
+                io.write_string("': ", !IO),
+                io.write_string(io.error_message(TmpFileError), !IO),
+                io.nl(!IO)
+            ;
+                FilesDiffer = error(_, _),
+                update_interface_create_file("been CREATED", OutputFileName,
+                    TmpOutputFileName, Succeeded, !IO)
+            )
+        ;
+
+            TmpOutputFileRes = error(TmpOutputFileError),
+            Succeeded = no,
+            io.close_binary_input(OutputFileStream, !IO),
+            io.write_string("Error creating `", !IO),
+            io.write_string(OutputFileName, !IO),
+            io.write_string("': ", !IO),
+            io.write_string(io.error_message(TmpOutputFileError), !IO),
+            io.nl(!IO)
+        )
+    ;
+        OutputFileRes = error(_),
+        update_interface_create_file("been CREATED", OutputFileName,
+            TmpOutputFileName, Succeeded, !IO)
+    ).
+
+:- pred update_interface_create_file(string::in, string::in, string::in,
+    bool::out, io::di, io::uo) is det.
+
+update_interface_create_file(Msg, OutputFileName, TmpOutputFileName, Succeeded,
+        !IO) :-
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    maybe_write_string(Verbose,
+        "% `" ++ OutputFileName ++ "' has " ++ Msg ++ ".\n", !IO),
+    copy_file(TmpOutputFileName, OutputFileName, MoveRes, !IO),
+    (
+        MoveRes = ok,
+        Succeeded = yes
+    ;
+        MoveRes = error(MoveError),
+        Succeeded = no,
+        io.write_string("Error creating `" ++ OutputFileName ++ "': " ++
+            io.error_message(MoveError), !IO),
+        io.nl(!IO)
+    ),
+    io.remove_file(TmpOutputFileName, _, !IO).
+
+:- pred binary_input_stream_cmp(io.binary_input_stream::in,
+    io.binary_input_stream::in, io.maybe_partial_res(io.res(bool))::out,
+    io::di, io::uo) is det.
+
+binary_input_stream_cmp(OutputFileStream, TmpOutputFileStream, FilesDiffer,
+        !IO) :-
+    io.binary_input_stream_foldl2_io_maybe_stop(OutputFileStream,
+        binary_input_stream_cmp_2(TmpOutputFileStream),
+        ok(no), FilesDiffer0, !IO),
+
+    % Check whether there is anything left in TmpOutputFileStream
+    ( FilesDiffer0 = ok(ok(no)) ->
+        io.read_byte(TmpOutputFileStream, TmpByteResult2, !IO),
+        (
+            TmpByteResult2 = ok(_),
+            FilesDiffer = ok(ok(yes))
+        ;
+            TmpByteResult2 = eof,
+            FilesDiffer = FilesDiffer0
+        ;
+            TmpByteResult2 = error(Error),
+            FilesDiffer = ok(error(Error))
+        )
+    ;
+        FilesDiffer = FilesDiffer0
+    ).
+
+:- pred binary_input_stream_cmp_2(io.binary_input_stream::in, int::in,
+    bool::out, io.res(bool)::in, io.res(bool)::out,
+    io::di, io::uo) is det.
+
+binary_input_stream_cmp_2(TmpOutputFileStream, Byte, Continue, _, Differ,
+        !IO) :-
+    io.read_byte(TmpOutputFileStream, TmpByteResult, !IO),
+    (
+        TmpByteResult = ok(TmpByte),
+        ( TmpByte = Byte ->
+            Differ = ok(no),
+            Continue = yes
+        ;
+            Differ = ok(yes),
+            Continue = no
+        )
+    ;
+        TmpByteResult = eof,
+        Differ = ok(yes),
+        Continue = no
+    ;
+        TmpByteResult = error(TmpByteError),
+        Differ = error(TmpByteError) : io.res(bool),
+        Continue = no
+    ).
+
+%-----------------------------------------------------------------------------%
+
+copy_file(Source, Destination, Res, !IO) :-
+    % Try to use the system's cp command in order to preserve metadata.
+    globals.io_lookup_string_option(install_command, InstallCommand, !IO),
+    Command = string.join_list("   ", list.map(quote_arg,
+        [InstallCommand, Source, Destination])),
+    io.output_stream(OutputStream, !IO),
+    invoke_system_command(OutputStream, cmd_verbose, Command, Succeeded, !IO),
+    (
+        Succeeded = yes,
+        Res = ok
+    ;
+        Succeeded = no,
+        io.open_binary_input(Source, SourceRes, !IO),
+        (
+            SourceRes = ok(SourceStream),
+            io.open_binary_output(Destination, DestRes, !IO),
+            (
+                DestRes = ok(DestStream),
+                WriteByte = io.write_byte(DestStream),
+                io.binary_input_stream_foldl_io(SourceStream, WriteByte, Res,
+                    !IO),
+                io.close_binary_input(SourceStream, !IO),
+                io.close_binary_output(DestStream, !IO)
+            ;
+                DestRes = error(Error),
+                Res = error(Error)
+            )
+        ;
+            SourceRes = error(Error),
+            Res = error(Error)
+        )
+    ).
+
+maybe_make_symlink(LinkTarget, LinkName, Result, !IO) :-
+    globals.io_lookup_bool_option(use_symlinks, UseSymLinks, !IO),
+    (
+        UseSymLinks = yes,
+        io.remove_file_recursively(LinkName, _, !IO),
+        io.make_symlink(LinkTarget, LinkName, LinkResult, !IO),
+        Result = ( if LinkResult = ok then yes else no )
+    ;
+        UseSymLinks = no,
+        Result = no
+    ).
+
+make_symlink_or_copy_file(SourceFileName, DestinationFileName, Succeeded,
+        !IO) :-
+    globals.io_lookup_bool_option(use_symlinks, UseSymLinks, !IO),
+    (
+        UseSymLinks = yes,
+        LinkOrCopy = "linking",
+        io.make_symlink(SourceFileName, DestinationFileName, Result, !IO)
+    ;
+        UseSymLinks = no,
+        LinkOrCopy = "copying",
+        copy_file(SourceFileName, DestinationFileName, Result, !IO)
+    ),
+    (
+        Result = ok,
+        Succeeded = yes
+    ;
+        Result = error(Error),
+        Succeeded = no,
+        io.progname_base("mercury_compile", ProgName, !IO),
+        io.write_string(ProgName, !IO),
+        io.write_string(": error ", !IO),
+        io.write_string(LinkOrCopy, !IO),
+        io.write_string(" `", !IO),
+        io.write_string(SourceFileName, !IO),
+        io.write_string("' to `", !IO),
+        io.write_string(DestinationFileName, !IO),
+        io.write_string("': ", !IO),
+        io.write_string(io.error_message(Error), !IO),
+        io.nl(!IO),
+        io.flush_output(!IO)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+touch_interface_datestamp(ModuleName, Ext, !IO) :-
+    module_name_to_file_name(ModuleName, Ext, do_create_dirs,
+        OutputFileName, !IO),
+    touch_datestamp(OutputFileName, !IO).
+
+touch_datestamp(OutputFileName, !IO) :-
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    maybe_write_string(Verbose,
+        "% Touching `" ++ OutputFileName ++ "'... ", !IO),
+    maybe_flush_output(Verbose, !IO),
+    io.open_output(OutputFileName, Result, !IO),
+    (
+        Result = ok(OutputStream),
+        io.write_string(OutputStream, "\n", !IO),
+        io.close_output(OutputStream, !IO),
+        maybe_write_string(Verbose, " done.\n", !IO)
+    ;
+        Result = error(IOError),
+        io.error_message(IOError, IOErrorMessage),
+        io.write_string("\nError opening `" ++ OutputFileName
+            ++ "' for output: " ++ IOErrorMessage ++ ".\n", !IO)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+maybe_set_exit_status(yes, !IO).
+maybe_set_exit_status(no, !IO) :-
+    io.set_exit_status(1, !IO).
+
+%-----------------------------------------------------------------------------%
+
+invoke_system_command(ErrorStream, Verbosity, Command, Succeeded, !IO) :-
+    invoke_system_command_maybe_filter_output(ErrorStream, Verbosity, Command,
+        no, Succeeded, !IO).
+
+invoke_system_command_maybe_filter_output(ErrorStream, Verbosity, Command,
+        MaybeProcessOutput, Succeeded, !IO) :-
+    % This predicate shouldn't alter the exit status of mercury_compile.
+    io.get_exit_status(OldStatus, !IO),
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    (
+        Verbosity = cmd_verbose,
+        PrintCommand = Verbose
+    ;
+        Verbosity = cmd_verbose_commands,
+        globals.io_lookup_bool_option(verbose_commands, PrintCommand, !IO)
+    ),
+    (
+        PrintCommand = yes,
+        io.write_string("% Invoking system command `", !IO),
+        io.write_string(Command, !IO),
+        io.write_string("'...\n", !IO),
+        io.flush_output(!IO)
+    ;
+        PrintCommand = no
+    ),
+
+    % The output from the command is written to a temporary file,
+    % which is then written to the output stream. Without this,
+    % the output from the command would go to the current C output
+    % and error streams.
+
+    io.make_temp(TmpFile, !IO),
+    ( use_dotnet ->
+        % XXX can't use Bourne shell syntax to redirect on .NET
+        % XXX the output will go to the wrong place!
+        CommandRedirected = Command
+    ; use_win32 ->
+        % On windows we can't in general redirect standard error in the
+        % shell.
+        CommandRedirected = Command ++ " > " ++ TmpFile
+    ;
+        CommandRedirected =
+            string.append_list([Command, " > ", TmpFile, " 2>&1"])
+    ),
+    io.call_system_return_signal(CommandRedirected, Result, !IO),
+    (
+        Result = ok(exited(Status)),
+        maybe_write_string(PrintCommand, "% done.\n", !IO),
+        ( Status = 0 ->
+            CommandSucceeded = yes
+        ;
+            % The command should have produced output describing the error.
+            CommandSucceeded = no
+        )
+    ;
+        Result = ok(signalled(Signal)),
+        % Make sure the current process gets the signal. Some systems (e.g.
+        % Linux) ignore SIGINT during a call to system().
+        raise_signal(Signal, !IO),
+        report_error_to_stream(ErrorStream, "system command received signal "
+            ++ int_to_string(Signal) ++ ".", !IO),
+        CommandSucceeded = no
+    ;
+        Result = error(Error),
+        report_error_to_stream(ErrorStream, io.error_message(Error), !IO),
+        CommandSucceeded = no
+    ),
+
+    (
+        % We can't do bash style redirection on .NET.
+        not use_dotnet,
+        MaybeProcessOutput = yes(ProcessOutput)
+    ->
+        io.make_temp(ProcessedTmpFile, !IO),
+        
+        ( use_win32 ->
+            % On windows we can't in general redirect standard
+            % error in the shell.
+            ProcessOutputRedirected = string.append_list(
+                [ProcessOutput, " < ", TmpFile, " > ",
+                    ProcessedTmpFile])
+        ;
+            ProcessOutputRedirected = string.append_list(
+                [ProcessOutput, " < ", TmpFile, " > ",
+                    ProcessedTmpFile, " 2>&1"])
+        ),
+        io.call_system_return_signal(ProcessOutputRedirected,
+            ProcessOutputResult, !IO),
+        io.remove_file(TmpFile, _, !IO),
+        (
+            ProcessOutputResult = ok(exited(ProcessOutputStatus)),
+            maybe_write_string(PrintCommand, "% done.\n", !IO),
+            ( ProcessOutputStatus = 0 ->
+                ProcessOutputSucceeded = yes
+            ;
+                % The command should have produced output
+                % describing the error.
+                ProcessOutputSucceeded = no
+            )
+        ;
+            ProcessOutputResult = ok(signalled(ProcessOutputSignal)),
+            % Make sure the current process gets the signal. Some systems
+            % (e.g. Linux) ignore SIGINT during a call to system().
+            raise_signal(ProcessOutputSignal, !IO),
+            report_error_to_stream(ErrorStream,
+                "system command received signal "
+                ++ int_to_string(ProcessOutputSignal) ++ ".", !IO),
+            ProcessOutputSucceeded = no
+        ;
+            ProcessOutputResult = error(ProcessOutputError),
+            report_error_to_stream(ErrorStream,
+                io.error_message(ProcessOutputError), !IO),
+            ProcessOutputSucceeded = no
+        )
+    ;
+        ProcessOutputSucceeded = yes,
+        ProcessedTmpFile = TmpFile
+    ),
+    Succeeded = CommandSucceeded `and` ProcessOutputSucceeded,
+
+    % Write the output to the error stream.
+
+    io.open_input(ProcessedTmpFile, TmpFileRes, !IO),
+    (
+        TmpFileRes = ok(TmpFileStream),
+        io.input_stream_foldl_io(TmpFileStream, io.write_char(ErrorStream),
+            Res, !IO),
+        (
+            Res = ok
+        ;
+            Res = error(TmpFileReadError),
+            report_error_to_stream(ErrorStream,
+                "error reading command output: " ++
+                io.error_message(TmpFileReadError), !IO)
+        ),
+        io.close_input(TmpFileStream, !IO)
+    ;
+        TmpFileRes = error(TmpFileError),
+        report_error_to_stream(ErrorStream,
+            "error opening command output: " ++ io.error_message(TmpFileError),
+            !IO)
+    ),
+    io.remove_file(ProcessedTmpFile, _, !IO),
+    io.set_exit_status(OldStatus, !IO).
+
+make_command_string(String0, QuoteType, String) :-
+    ( use_win32 ->
+        (
+            QuoteType = forward,
+            Quote = " '"
+        ;
+            QuoteType = double,
+            Quote = " """
+        ),
+        string.append_list(["sh -c ", Quote, String0, Quote], String)
+    ;
+        String = String0
+    ).
+
+%-----------------------------------------------------------------------------%
+
+    % Are we compiling in a .NET environment?
+    %
+:- pred use_dotnet is semidet.
+:- pragma foreign_proc("C#",
+    use_dotnet,
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+    SUCCESS_INDICATOR = true;
+").
+% The following clause is only used if there is no matching foreign_proc.
+use_dotnet :-
+    semidet_fail.
+
+    % Are we compiling in a win32 environment?
+    %
+    % If in doubt, use_win32 should succeed.  This is only used to decide
+    % whether to invoke Bourne shell command and shell scripts directly,
+    % or whether to invoke them via `sh -c ...'. The latter should work
+    % correctly in a Unix environment too, but is a little less efficient
+    % since it invokes another process.
+    %
+:- pred use_win32 is semidet.
+:- pragma foreign_proc("C",
+    use_win32,
+    [will_not_call_mercury, promise_pure, thread_safe],
+"
+#ifdef MR_WIN32
+    SUCCESS_INDICATOR = 1;
+#else
+    SUCCESS_INDICATOR = 0;
+#endif
+").
+% The following clause is only used if there is no matching foreign_proc.
+% See comment above for why it is OK to just succeed here.
+use_win32 :-
+    semidet_succeed.
+
+%-----------------------------------------------------------------------------%
+%
+% Java command-line utilities.
+%
+
+create_java_shell_script(MainModuleName, Succeeded, !IO) :-
+    % XXX Extension should be ".bat" on Windows
+    Extension = "",
+    module_name_to_file_name(MainModuleName, Extension, do_not_create_dirs,
+        FileName, !IO),
+
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    maybe_write_string(Verbose, "% Generating shell script `" ++
+        FileName ++ "'...\n", !IO),
+
+    module_name_to_file_name(MainModuleName, ".class", do_not_create_dirs,
+        ClassFileName, !IO),
+    DirName = dir.dirname(ClassFileName),
+
+    % XXX PathSeparator should be ";" on Windows
+    PathSeparator = ":",
+    globals.io_lookup_accumulating_option(java_classpath, Java_Incl_Dirs0,
+        !IO),
+    % We prepend the .class files' directory and the current CLASSPATH.
+    Java_Incl_Dirs = [DirName, "$CLASSPATH" | Java_Incl_Dirs0],
+    ClassPath = string.join_list(PathSeparator, Java_Incl_Dirs),
+
+    globals.io_lookup_string_option(java_interpreter, Java, !IO),
+    module_name_to_file_name(MainModuleName, "", do_not_create_dirs,
+        Name_No_Extn, !IO),
+
+    io.open_output(FileName, OpenResult, !IO),
+    (
+        OpenResult = ok(ShellScript),
+        % XXX On Windows we should output a .bat file instead
+        io.write_string(ShellScript, "#!/bin/sh\n", !IO),
+        io.write_string(ShellScript, "CLASSPATH=" ++ ClassPath ++ " ", !IO),
+        io.write_string(ShellScript, Java ++ " ", !IO),
+        io.write_string(ShellScript, Name_No_Extn ++ "\n", !IO),
+        io.close_output(ShellScript, !IO),
+        io.call_system("chmod a+x " ++ FileName, ChmodResult, !IO),
+        (
+            ChmodResult = ok(Status),
+            ( Status = 0 ->
+                Succeeded = yes,
+                maybe_write_string(Verbose, "% done.\n", !IO)
+            ;
+                unexpected(this_file, "chmod exit status != 0"),
+                Succeeded = no
+            )
+        ;
+            ChmodResult = error(Message),
+            unexpected(this_file, io.error_message(Message)),
+            Succeeded = no
+        )
+    ;
+        OpenResult = error(Message),
+        unexpected(this_file, io.error_message(Message)),
+        Succeeded = no
+    ).
+
+list_class_files_for_jar(ModuleName, ClassFiles, ListClassFiles, !IO) :-
+    globals.io_lookup_bool_option(use_subdirs, UseSubdirs, !IO),
+    globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
+    AnySubdirs = UseSubdirs `or` UseGradeSubdirs,
+    (
+        AnySubdirs = yes,
+        module_name_to_file_name(ModuleName, ".class", do_not_create_dirs,
+            ClassFile, !IO),
+        ClassSubdir = dir.dirname(ClassFile),
+        % Here we use the `-C' option of jar to change directory during
+        % execution, then use sed to strip away the Mercury/classs/
+        % prefix to the class files.
+        % Otherwise, the class files would be stored as
+        %   Mercury/classs/*.class
+        % within the jar file, which is not what we want.
+        % XXX It would be nice to avoid this dependency on sed.
+        ListClassFiles = "-C " ++ ClassSubdir ++ " \\\n" ++
+            "\t\t`echo "" " ++ ClassFiles ++ """" ++
+            " | sed 's| '" ++ ClassSubdir ++ "/| |'`"
+    ;
+        AnySubdirs = no,
+        ListClassFiles = ClassFiles
+    ).
+
+get_env_classpath(Classpath, !IO) :-
+    io.get_environment_var("CLASSPATH", MaybeCP, !IO),
+    (
+        MaybeCP = yes(Classpath)
+    ;
+        MaybeCP = no,
+        io.get_environment_var("java.class.path", MaybeJCP, !IO),
+        (
+            MaybeJCP = yes(Classpath)
+        ;
+            MaybeJCP = no,
+            Classpath = ""
+        )
+    ).
+
+%-----------------------------------------------------------------------------%
+%
+% Erlang utilities
+%
+
+create_erlang_shell_script(MainModuleName, Succeeded, !IO) :-
+    Extension = "",
+    module_name_to_file_name(MainModuleName, Extension, do_not_create_dirs,
+        ScriptFileName, !IO),
+    globals.io_get_globals(Globals, !IO),
+    grade_directory_component(Globals, GradeDir),
+
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    maybe_write_string(Verbose, "% Generating shell script `" ++
+        ScriptFileName ++ "'...\n", !IO),
+
+    globals.io_lookup_string_option(erlang_object_file_extension, BeamExt,
+        !IO),
+    module_name_to_file_name(MainModuleName, BeamExt, do_not_create_dirs,
+        BeamFileName, !IO),
+    BeamDirName = dir.dirname(BeamFileName),
+    module_name_to_file_name(MainModuleName, BeamBaseNameNoExt),
+
+    % Add `-pa <dir>' option to find the standard library.
+    % (-pa adds the directory to the beginning of the list of paths to search
+    % for .beam files)
+    globals.io_lookup_maybe_string_option(
+        mercury_standard_library_directory, MaybeStdLibDir, !IO),
+    (
+        MaybeStdLibDir = yes(StdLibDir),
+        StdLibBeamsPath = StdLibDir/"lib"/GradeDir/"libmer_std.beams",
+        SearchStdLib = pa_option(yes, StdLibBeamsPath),
+        % Added by elds_to_erlang.m
+        MainFunc = "mercury__main_wrapper"
+    ;
+        MaybeStdLibDir = no,
+        SearchStdLib = "",
+        MainFunc = "main_2_p_0"
+    ),
+
+    % Add `-pa <dir>' options to find any other libraries specified by the user.
+    globals.io_lookup_accumulating_option(
+        mercury_library_directories, MercuryLibDirs0, !IO),
+    MercuryLibDirs = list.map((func(LibDir) = LibDir/"lib"/GradeDir),
+        MercuryLibDirs0),
+    globals.io_lookup_accumulating_option(link_libraries,
+        LinkLibrariesList0, !IO),
+    list.map_foldl2(find_erlang_library_path(MercuryLibDirs),
+        LinkLibrariesList0, LinkLibrariesList, yes, LibrariesSucceeded,
+        !IO),
+    (
+        LibrariesSucceeded = yes,
+        % Remove symlink in the way, if any.
+        io.remove_file(ScriptFileName, _, !IO),
+        io.open_output(ScriptFileName, OpenResult, !IO),
+        (
+            OpenResult = ok(ShellScript),
+
+            globals.io_lookup_string_option(erlang_interpreter, Erlang, !IO),
+            SearchLibs = string.append_list(list.map(pa_option(yes),
+                list.sort_and_remove_dups(LinkLibrariesList))),
+
+            % XXX main_2_p_0 is not necessarily in the main module itself and
+            % could be in a submodule.  We don't handle that yet.
+            SearchProg = pa_option(no, """$DIR""/" ++ quote_arg(BeamDirName)),
+
+            % Write the shell script.
+            % Note we need to use '-extra' instead of '--' for "-flag" and
+            % "+flag" arguments to be pass through to the Mercury program.
+            io.write_strings(ShellScript, [
+                "#!/bin/sh\n",
+                "# Generated by the Mercury compiler.\n",
+                "DIR=`dirname ""$0""`\n",
+                "exec ", Erlang, " -noshell \\\n",
+                SearchStdLib, SearchLibs, SearchProg,
+                " -s ", BeamBaseNameNoExt, " ", MainFunc,
+                " -s init stop -extra ""$@""\n"
+            ], !IO),
+            io.close_output(ShellScript, !IO),
+
+            % Set executable bit.
+            io.call_system("chmod a+x " ++ ScriptFileName, ChmodResult, !IO),
+            (
+                ChmodResult = ok(Status),
+                ( Status = 0 ->
+                    Succeeded = yes,
+                    maybe_write_string(Verbose, "% done.\n", !IO)
+                ;
+                    unexpected(this_file, "chmod exit status != 0"),
+                    Succeeded = no
+                )
+            ;
+                ChmodResult = error(Message),
+                unexpected(this_file, io.error_message(Message)),
+                Succeeded = no
+            )
+        ;
+            OpenResult = error(Message),
+            unexpected(this_file, io.error_message(Message)),
+            Succeeded = no
+        )
+    ;
+        LibrariesSucceeded = no,
+        Succeeded = no
+    ).
+
+:- pred find_erlang_library_path(list(dir_name)::in, string::in, string::out,
+    bool::in, bool::out, io::di, io::uo) is det.
+
+find_erlang_library_path(MercuryLibDirs, LibName, LibPath, !Succeeded, !IO) :-
+    globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
+    file_name_to_module_name(LibName, LibModuleName),
+    globals.io_set_option(use_grade_subdirs, bool(no), !IO),
+    module_name_to_lib_file_name("lib", LibModuleName, ".beams",
+        do_not_create_dirs, LibFileName, !IO),
+    globals.io_set_option(use_grade_subdirs, bool(UseGradeSubdirs), !IO),
+
+    io.input_stream(InputStream, !IO),
+    search_for_file_returning_dir(MercuryLibDirs, LibFileName,
+        SearchResult, !IO),
+    (
+        SearchResult = ok(DirName),
+        LibPath = DirName/LibFileName,
+        io.set_input_stream(InputStream, LibInputStream, !IO),
+        io.close_input(LibInputStream, !IO)
+    ;
+        SearchResult = error(Error),
+        LibPath = "",
+        write_error_pieces_maybe_with_context(no, 0, [words(Error)], !IO),
+        !:Succeeded = no
+    ).
+
+:- func pa_option(bool, dir_name) = string.
+
+pa_option(Quote, Dir0) = " -pa " ++ Dir ++ " \\\n" :-
+    (
+        Quote = yes,
+        Dir = quote_arg(Dir0)
+    ;
+        Quote = no,
+        Dir = Dir0
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "module_cmds.m".
+
+%-----------------------------------------------------------------------------%
+:- end_module parse_tree.module_cmds.
+%-----------------------------------------------------------------------------%
Index: compiler/module_imports.m
===================================================================
RCS file: compiler/module_imports.m
diff -N compiler/module_imports.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/module_imports.m	19 Jul 2008 07:52:33 -0000
@@ -0,0 +1,664 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1996-2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: module_imports.m.
+% Main author: fjh.
+%
+% This module contains the data structure for recording module imports
+% and its access predicates.
+%-----------------------------------------------------------------------------%
+
+:- module parse_tree.module_imports.
+:- interface.
+
+:- import_module libs.file_util.
+:- import_module libs.globals.
+:- import_module libs.timestamp.
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_item.
+:- import_module parse_tree.prog_io.    % for module_error;
+                                        % undesirable dependency
+
+:- import_module list.
+:- import_module map.
+:- import_module maybe.
+:- import_module pair.
+
+    % When doing smart recompilation record for each module the suffix of
+    % the file that was read and the modification time of the file.
+    %
+:- type module_timestamps == map(module_name, module_timestamp).
+:- type module_timestamp
+    --->    module_timestamp(
+                suffix          :: string,
+                timestamp       :: timestamp,
+                need_qualifier  :: need_qualifier
+            ).
+
+    % The `module_imports' structure holds information about
+    % a module and the modules that it imports.
+    %
+    % Note that we build this structure up as we go along.
+    % When generating the dependencies (for `--generate-dependencies'), the
+    % two fields that hold the direct imports do not include the imports via
+    % ancestors when the module is first read in; the ancestor imports are
+    % added later, once all the modules have been read in.  Similarly the
+    % indirect imports field is initially set to the empty list and filled
+    % in later.
+    %
+    % When compiling or when making interface files, the same sort of thing
+    % applies: initially all the list(module_name) fields except the public
+    % children field are set to empty lists, and then we add ancestor
+    % modules and imported modules to their respective lists as we process
+    % the interface files for those imported or ancestor modules.
+    %
+:- type module_imports
+    --->    module_imports(
+                % The source file.
+                source_file_name            :: file_name,
+
+                % The name of the top-level module in the source file
+                % containing the module that we are compiling.
+                source_file_module_name     :: module_name,
+
+                % The module (or sub-module) that we are compiling.
+                module_name                 :: module_name,
+
+                % The list of ancestor modules it inherits.
+                parent_deps                 :: list(module_name),
+
+                % The list of modules it directly imports in the interface
+                % (imports via ancestors count as direct).
+                int_deps                    :: list(module_name),
+
+                % The list of modules it directly imports in the
+                % implementation.
+                impl_deps                   :: list(module_name),
+
+                % The list of modules it indirectly imports.
+                indirect_deps               :: list(module_name),
+
+                children                    :: list(module_name),
+
+                % The list of its public children, i.e. child modules that
+                % it includes in the interface section.
+                public_children             :: list(module_name),
+
+                % The modules included in the same source file. This field
+                % is only set for the top-level module in each file.
+                nested_children             :: list(module_name),
+
+                % The list of filenames for fact tables in this module.
+                fact_table_deps             :: list(string),
+
+                % Whether or not the module contains foreign code, and if yes,
+                % which languages they use.
+                has_foreign_code            :: contains_foreign_code,
+
+                % The `:- pragma foreign_import_module' declarations.
+                foreign_import_modules      :: foreign_import_module_info_list,
+
+                % Does the module contain any `:- pragma foreign_export'
+                % declarations?
+                contains_foreign_export     :: contains_foreign_export,
+
+                % The contents of the module and its imports.
+                items                       :: list(item),
+
+                % Whether an error has been encountered when reading in
+                % this module.
+                error                       :: module_error,
+
+                % If we are doing smart recompilation, we need to keep
+                % the timestamps of the modules read in.
+                maybe_timestamps            :: maybe(module_timestamps),
+
+                % Does this module contain main/2?
+                has_main                    :: has_main,
+
+                % The directory containing the module source.
+                module_dir                  :: dir_name
+            ).
+
+:- pred module_imports_get_source_file_name(module_imports::in, file_name::out)
+    is det.
+:- pred module_imports_get_module_name(module_imports::in, module_name::out)
+    is det.
+:- pred module_imports_get_impl_deps(module_imports::in,
+    list(module_name)::out) is det.
+:- pred module_imports_get_items(module_imports::in, list(item)::out) is det.
+:- pred module_imports_get_error(module_imports::in, module_error::out) is det.
+
+:- pred module_imports_set_items(list(item)::in,
+    module_imports::in, module_imports::out) is det.
+:- pred module_imports_set_error(module_error::in,
+    module_imports::in, module_imports::out) is det.
+
+    % Set the interface dependencies.
+    %
+:- pred module_imports_set_int_deps(list(module_name)::in,
+    module_imports::in, module_imports::out) is det.
+
+    % Set the implementation dependencies.
+    %
+:- pred module_imports_set_impl_deps(list(module_name)::in,
+    module_imports::in, module_imports::out) is det.
+
+    % Set the indirect dependencies.
+    %
+:- pred module_imports_set_indirect_deps(list(module_name)::in,
+    module_imports::in, module_imports::out) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % init_dependencies(FileName, SourceFileModuleName, NestedModuleNames,
+    %   Error, Globals, ModuleName - Items, ModuleImports).
+    %
+:- pred init_dependencies(file_name::in, module_name::in,
+    list(module_name)::in, module_error::in, globals::in,
+    pair(module_name, list(item))::in, module_imports::out) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % get_dependencies(Items, ImportDeps, UseDeps):
+    %
+    % Get the list of modules that a list of items (explicitly) depends on.
+    % ImportDeps is the list of modules imported using `:- import_module',
+    % UseDeps is the list of modules imported using `:- use_module'.
+    % N.B. Typically you also need to consider the module's implicit
+    % dependencies (see get_implicit_dependencies/3), its parent modules
+    % (see get_ancestors/1) and possibly also the module's child modules
+    % (see get_children/2). You may also need to consider indirect
+    % dependencies.
+    %
+:- pred get_dependencies(list(item)::in, list(module_name)::out,
+    list(module_name)::out) is det.
+
+    % get_dependencies_int_imp(Items, IntImportDeps, IntUseDeps,
+    %   ImpImportDeps, ImpUseDeps):
+    %
+    % Get the list of modules that a list of items (explicitly) depends on.
+    %
+    % IntImportDeps is the list of modules imported using `:- import_module'
+    % in the interface, and ImpImportDeps those modules imported in the
+    % implementation. IntUseDeps is the list of modules imported using
+    % `:- use_module' in the interface, and ImpUseDeps those modules imported
+    % in the implementation.
+    %
+    % N.B. Typically you also need to consider the module's implicit
+    % dependencies (see get_implicit_dependencies/3), its parent modules
+    % (see get_ancestors/1) and possibly also the module's child modules
+    % (see get_children/2). You may also need to consider indirect
+    % dependencies.
+    %
+    % N.B This predicate assumes that any declarations between the `:- module'
+    % and the first `:- interface' or `:- implementation' are in the
+    % implementation.
+    %
+:- pred get_dependencies_int_imp(list(item)::in,
+    list(module_name)::out, list(module_name)::out,
+    list(module_name)::out, list(module_name)::out) is det.
+
+    % get_implicit_dependencies(Items, Globals, ImportDeps, UseDeps):
+    %
+    % Get the list of builtin modules (e.g. "public_builtin",
+    % "private_builtin") that a list of items may implicitly depend on.
+    % ImportDeps is the list of modules which should be automatically
+    % implicitly imported as if via `:- import_module', and UseDeps is
+    % the list which should be automatically implicitly imported as if via
+    % `:- use_module'.
+    %
+:- pred get_implicit_dependencies(list(item)::in, globals::in,
+    list(module_name)::out, list(module_name)::out) is det.
+
+:- pred add_implicit_imports(list(item)::in, globals::in,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out) is det.
+
+    % Get the fact table dependencies for a module.
+    %
+:- pred get_fact_table_dependencies(list(item)::in, list(string)::out) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.compiler_util.
+:- import_module libs.options.
+:- import_module parse_tree.modules.    % undesirable dependency
+
+:- import_module bool.
+:- import_module dir.
+:- import_module set.
+:- import_module term.
+
+module_imports_get_source_file_name(Module, Module ^ source_file_name).
+module_imports_get_module_name(Module, Module ^ module_name).
+module_imports_get_impl_deps(Module, Module ^ impl_deps).
+module_imports_get_items(Module, Module ^ items).
+module_imports_get_error(Module, Module ^ error).
+module_imports_set_items(Items, Module, Module ^ items := Items).
+module_imports_set_error(Error, Module, Module ^ error := Error).
+module_imports_set_int_deps(IntDeps, Module, Module ^ int_deps := IntDeps).
+module_imports_set_impl_deps(ImplDeps, Module,
+        Module ^ impl_deps := ImplDeps).
+module_imports_set_indirect_deps(IndirectDeps, Module,
+        Module ^ indirect_deps := IndirectDeps).
+
+%-----------------------------------------------------------------------------%
+
+init_dependencies(FileName, SourceFileModuleName, NestedModuleNames,
+        Error, Globals, ModuleName - Items, ModuleImports) :-
+    ParentDeps = get_ancestors(ModuleName),
+
+    get_dependencies(Items, ImplImportDeps0, ImplUseDeps0),
+    add_implicit_imports(Items, Globals,
+        ImplImportDeps0, ImplImportDeps,
+        ImplUseDeps0, ImplUseDeps),
+    list.append(ImplImportDeps, ImplUseDeps, ImplementationDeps),
+
+    get_interface(ModuleName, no, Items, InterfaceItems),
+    get_dependencies(InterfaceItems,
+        InterfaceImportDeps0, InterfaceUseDeps0),
+    add_implicit_imports(InterfaceItems, Globals,
+        InterfaceImportDeps0, InterfaceImportDeps,
+        InterfaceUseDeps0, InterfaceUseDeps),
+    list.append(InterfaceImportDeps, InterfaceUseDeps, InterfaceDeps),
+
+    % We don't fill in the indirect dependencies yet.
+    IndirectDeps = [],
+
+    get_children(Items, IncludeDeps),
+    get_children(InterfaceItems, InterfaceIncludeDeps),
+
+    ( ModuleName = SourceFileModuleName ->
+        list.delete_all(NestedModuleNames, ModuleName, NestedDeps)
+    ;
+        NestedDeps = []
+    ),
+
+    get_fact_table_dependencies(Items, FactTableDeps),
+
+    % Figure out whether the items contain foreign code.
+    get_item_list_foreign_code(Globals, Items, LangSet,
+        ForeignImports0, ContainsPragmaExport),
+    ( set.empty(LangSet) ->
+        ContainsForeignCode = contains_no_foreign_code
+    ;
+        ContainsForeignCode = contains_foreign_code(LangSet)
+    ),
+
+    % If this module contains `:- pragma foreign_export' or
+    % `:- pragma foreign_type' declarations, importing modules
+    % may need to import its `.mh' file.
+    get_foreign_self_imports(Items, SelfImportLangs),
+    ForeignSelfImports = list.map(
+        (func(Lang) = foreign_import_module_info(Lang, ModuleName,
+            term.context_init)),
+        SelfImportLangs),
+    ForeignImports = ForeignSelfImports ++ ForeignImports0,
+
+    % Work out whether the items contain main/2.
+    (
+        list.member(Item, Items),
+        Item = item_pred_decl(ItemPredDecl),
+        ItemPredDecl = item_pred_decl_info(_, _, _, _, pf_predicate, Name,
+            [_, _], WithType, _, _, _, _, _, _),
+        unqualify_name(Name) = "main",
+
+        % XXX We should allow `main/2' to be declared using `with_type`,
+        % but equivalences haven't been expanded at this point. The `has_main'
+        % field is only used for some special case handling of the module
+        % containing main for the IL backend (we generate a `.exe' file
+        % rather than a `.dll' file). This would arguably be better done
+        % by generating a `.dll' file as normal, and a separate `.exe' file
+        % containing initialization code and a call to `main/2', as we do
+        % with the `_init.c' file in the C backend.
+        WithType = no
+    ->
+        HasMain = has_main
+    ;
+        HasMain = no_main
+    ),
+
+    ModuleImports = module_imports(FileName, SourceFileModuleName,
+        ModuleName, ParentDeps, InterfaceDeps,
+        ImplementationDeps, IndirectDeps, IncludeDeps,
+        InterfaceIncludeDeps, NestedDeps, FactTableDeps,
+        ContainsForeignCode, ForeignImports, ContainsPragmaExport,
+        [], Error, no, HasMain, dir.this_directory).
+
+%-----------------------------------------------------------------------------%
+
+get_dependencies(Items, ImportDeps, UseDeps) :-
+    get_dependencies_implementation(Items,
+        [], IntImportDeps, [], IntUseDeps, [], ImpImportDeps, [], ImpUseDeps),
+    ImportDeps = IntImportDeps ++ ImpImportDeps,
+    UseDeps = IntUseDeps ++ ImpUseDeps.
+
+get_dependencies_int_imp(Items, IntImportDeps, IntUseDeps,
+        ImpImportDeps, ImpUseDeps) :-
+    get_dependencies_implementation(Items,
+        [], IntImportDeps, [], IntUseDeps, [], ImpImportDeps, [], ImpUseDeps).
+
+:- pred get_dependencies_implementation(list(item)::in,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out) is det.
+
+get_dependencies_implementation([],
+        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps).
+get_dependencies_implementation([Item | Items],
+        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps) :-
+    ( Item = item_module_defn(ItemModuleDefn) ->
+        ItemModuleDefn = item_module_defn_info(ModuleDefn, _),
+        ( ModuleDefn = md_interface ->
+            get_dependencies_interface(Items,
+                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
+        ;
+            ( ModuleDefn = md_import(Modules) ->
+                !:ImpImportDeps = !.ImpImportDeps ++ Modules
+            ; ModuleDefn = md_use(Modules) ->
+                !:ImpUseDeps = !.ImpUseDeps ++ Modules
+            ;
+                true
+            ),
+            get_dependencies_implementation(Items,
+                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
+        )
+    ;
+        get_dependencies_implementation(Items,
+            !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
+    ).
+
+:- pred get_dependencies_interface(list(item)::in,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out,
+    list(module_name)::in, list(module_name)::out) is det.
+
+get_dependencies_interface([],
+        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps).
+get_dependencies_interface([Item | Items],
+        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps) :-
+    ( Item = item_module_defn(ItemModuleDefn) ->
+        ItemModuleDefn = item_module_defn_info(ModuleDefn, _),
+        ( ModuleDefn = md_implementation ->
+            get_dependencies_implementation(Items,
+                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
+        ;
+            ( ModuleDefn = md_import(Modules) ->
+                !:IntImportDeps = !.IntImportDeps ++ Modules
+            ; ModuleDefn = md_use(Modules) ->
+                !:IntUseDeps = !.IntUseDeps ++ Modules
+            ;
+                true
+            ),
+            get_dependencies_interface(Items,
+                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
+        )
+    ;
+        get_dependencies_interface(Items,
+            !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+get_implicit_dependencies(Items, Globals, ImportDeps, UseDeps) :-
+    add_implicit_imports(Items, Globals, [], ImportDeps, [], UseDeps).
+
+add_implicit_imports(Items, Globals, !ImportDeps, !UseDeps) :-
+    !:ImportDeps = [mercury_public_builtin_module | !.ImportDeps],
+    !:UseDeps = [mercury_private_builtin_module | !.UseDeps],
+    items_need_imports(Items, no, ItemsNeedTabling,
+        no, ItemsNeedTablingStatistics, no, ItemsNeedSTM),
+    % We should include mercury_table_builtin_module if the Items contain
+    % a tabling pragma, or if one of --use-minimal-model (either kind) and
+    % --trace-table-io is specified. In the former case, we may also need
+    % to import mercury_table_statistics_module.
+    (
+        ItemsNeedTabling = yes,
+        !:UseDeps = [mercury_table_builtin_module | !.UseDeps],
+        (
+            ItemsNeedTablingStatistics = yes,
+            !:UseDeps = [mercury_table_statistics_module | !.UseDeps]
+        ;
+            ItemsNeedTablingStatistics = no
+        )
+    ;
+        ItemsNeedTabling = no,
+        expect(unify(ItemsNeedTablingStatistics, no), this_file,
+            "add_implicit_imports: tabling statistics without tabling"),
+        (
+            % These forms of tabling cannot ask for statistics.
+            (
+                globals.lookup_bool_option(Globals,
+                    use_minimal_model_stack_copy, yes)
+            ;
+                globals.lookup_bool_option(Globals,
+                    use_minimal_model_own_stacks, yes)
+            ;
+                globals.lookup_bool_option(Globals, trace_table_io, yes)
+            )
+        ->
+            !:UseDeps = [mercury_table_builtin_module | !.UseDeps]
+        ;
+            true
+        )
+    ),
+    (
+        ItemsNeedSTM = yes,
+        !:UseDeps = [mercury_stm_builtin_module, mercury_exception_module,
+            mercury_univ_module | !.UseDeps]
+    ;
+        ItemsNeedSTM = no
+    ),
+    globals.lookup_bool_option(Globals, profile_deep, Deep),
+    (
+        Deep = yes,
+        !:UseDeps = [mercury_profiling_builtin_module | !.UseDeps]
+    ;
+        Deep = no
+    ),
+    (
+        (
+            globals.lookup_bool_option(Globals,
+                record_term_sizes_as_words, yes)
+        ;
+            globals.lookup_bool_option(Globals,
+                record_term_sizes_as_cells, yes)
+        )
+    ->
+        !:UseDeps = [mercury_term_size_prof_builtin_module | !.UseDeps]
+    ;
+        true
+    ),
+    globals.get_target(Globals, Target),
+    globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
+    globals.lookup_bool_option(Globals, parallel, Parallel),
+    (
+        Target = target_c,
+        HighLevelCode = no,
+        Parallel = yes
+    ->
+        !:UseDeps = [mercury_par_builtin_module | !.UseDeps]
+    ;
+        true
+    ),
+    globals.lookup_bool_option(Globals, use_regions, UseRegions),
+    (
+        UseRegions = yes,
+        !:UseDeps = [mercury_region_builtin_module | !.UseDeps]
+    ;
+        UseRegions = no
+    ),
+    globals.lookup_bool_option(Globals, source_to_source_debug, SSDB),
+    (
+        SSDB = yes,
+        !:UseDeps = [mercury_ssdb_builtin_module | !.UseDeps]
+    ;
+        SSDB = no
+    ).
+
+:- pred items_need_imports(list(item)::in,
+    bool::in, bool::out, bool::in, bool::out, bool::in, bool::out) is det.
+
+items_need_imports([], !ItemsNeedTabling,
+        !ItemsNeedTablingStatistics, !ItemsNeedSTM).
+items_need_imports([Item | Items], !ItemsNeedTabling,
+        !ItemsNeedTablingStatistics, !ItemsNeedSTM) :-
+    (
+        Item = item_pragma(ItemPragma),
+        ItemPragma = item_pragma_info(_, Pragma, _),
+        Pragma = pragma_tabled(_, _, _, _, _, MaybeAttributes)
+    ->
+        !:ItemsNeedTabling = yes,
+        (
+            MaybeAttributes = no,
+            % We cannot be done yet. If !.ItemsNeedTablingStatistics and
+            % !.ItemsNeedSTM were already both `yes', !.ItemsNeedTabling
+            % would have been too, and we would have stopped before looking
+            % at this item.
+            items_need_imports(Items, !ItemsNeedTabling,
+                !ItemsNeedTablingStatistics, !ItemsNeedSTM)
+        ;
+            MaybeAttributes = yes(Attributes),
+            StatsAttr = Attributes ^ table_attr_statistics,
+            (
+                StatsAttr = table_gather_statistics,
+                !:ItemsNeedTablingStatistics = yes,
+                (
+                    !.ItemsNeedSTM = yes
+                    % There is nothing left to search for; stop recursing.
+                ;
+                    !.ItemsNeedSTM = no,
+                    items_need_imports(Items, !ItemsNeedTabling,
+                        !ItemsNeedTablingStatistics, !ItemsNeedSTM)
+                )
+            ;
+                StatsAttr = table_dont_gather_statistics
+            )
+        )
+    ;
+        Item = item_clause(ItemClause),
+        Body = ItemClause ^ cl_body,
+        goal_contains_stm_atomic(Body) = yes
+    ->
+        !:ItemsNeedSTM = yes,
+        (
+            !.ItemsNeedTabling = yes,
+            !.ItemsNeedTablingStatistics = yes
+        ->
+            % There is nothing left to search for; stop recursing.
+            true
+        ;
+            items_need_imports(Items, !ItemsNeedTabling,
+                !ItemsNeedTablingStatistics, !ItemsNeedSTM)
+        )
+    ;
+        items_need_imports(Items, !ItemsNeedTabling,
+            !ItemsNeedTablingStatistics, !ItemsNeedSTM)
+    ).
+
+:- func goal_contains_stm_atomic(goal) = bool.
+
+goal_contains_stm_atomic(GoalExpr - _Context) = ContainsAtomic :-
+    (
+        ( GoalExpr = true_expr
+        ; GoalExpr = fail_expr
+        ),
+        ContainsAtomic = no
+    ;
+        ( GoalExpr = conj_expr(SubGoalA, SubGoalB)
+        ; GoalExpr = par_conj_expr(SubGoalA, SubGoalB)
+        ; GoalExpr = disj_expr(SubGoalA, SubGoalB)
+        ),
+        ContainsAtomic = two_goals_contain_stm_atomic(SubGoalA, SubGoalB)
+    ;
+        ( GoalExpr = some_expr(_, SubGoal)
+        ; GoalExpr = all_expr(_, SubGoal)
+        ; GoalExpr = some_state_vars_expr(_, SubGoal)
+        ; GoalExpr = all_state_vars_expr(_, SubGoal)
+        ; GoalExpr = promise_purity_expr(_, _, SubGoal)
+        ; GoalExpr = promise_equivalent_solutions_expr(_, _, _, SubGoal)
+        ; GoalExpr = promise_equivalent_solution_sets_expr(_, _, _, SubGoal)
+        ; GoalExpr = promise_equivalent_solution_arbitrary_expr(_, _, _,
+            SubGoal)
+        ; GoalExpr = trace_expr(_, _, _, _, SubGoal)
+        ),
+        ContainsAtomic = goal_contains_stm_atomic(SubGoal)
+    ;
+        ( GoalExpr = implies_expr(SubGoalA, SubGoalB)
+        ; GoalExpr = equivalent_expr(SubGoalA, SubGoalB)
+        ),
+        ContainsAtomic = two_goals_contain_stm_atomic(SubGoalA, SubGoalB)
+    ;
+        GoalExpr = not_expr(SubGoal),
+        ContainsAtomic = goal_contains_stm_atomic(SubGoal)
+    ;
+        GoalExpr = if_then_else_expr(_, _, Cond, Then, Else),
+        ContainsAtomic = three_goals_contain_stm_atomic(Cond, Then, Else)
+    ;
+        GoalExpr = atomic_expr(_, _, _, _, _),
+        ContainsAtomic = yes
+    ;
+        ( GoalExpr = event_expr(_, _)
+        ; GoalExpr = call_expr(_, _, _)
+        ; GoalExpr = unify_expr(_, _, _)
+        ),
+        ContainsAtomic = no
+    ).
+
+:- func two_goals_contain_stm_atomic(goal, goal) = bool.
+
+two_goals_contain_stm_atomic(GoalA, GoalB) = ContainsAtomic :-
+    ( goal_contains_stm_atomic(GoalA) = yes ->
+        ContainsAtomic = yes
+    ;
+        ContainsAtomic = goal_contains_stm_atomic(GoalB)
+    ).
+
+:- func three_goals_contain_stm_atomic(goal, goal, goal) = bool.
+
+three_goals_contain_stm_atomic(GoalA, GoalB, GoalC) = ContainsAtomic :-
+    ( goal_contains_stm_atomic(GoalA) = yes ->
+        ContainsAtomic = yes
+    ;
+        ContainsAtomic = two_goals_contain_stm_atomic(GoalB, GoalC)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+get_fact_table_dependencies(Items, Deps) :-
+    get_fact_table_dependencies_2(Items, [], Deps).
+
+:- pred get_fact_table_dependencies_2(list(item)::in, list(string)::in,
+    list(string)::out) is det.
+
+get_fact_table_dependencies_2([], !Deps).
+get_fact_table_dependencies_2([Item | Items], !Deps) :-
+    (
+        Item = item_pragma(ItemPragma),
+        ItemPragma = item_pragma_info(_, Pragma, _),
+        Pragma = pragma_fact_table(_SymName, _Arity, FileName)
+    ->
+        !:Deps = [FileName | !.Deps]
+    ;
+        true
+    ),
+    get_fact_table_dependencies_2(Items, !Deps).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "module_imports.m".
+
+%-----------------------------------------------------------------------------%
Index: compiler/module_qual.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/module_qual.m,v
retrieving revision 1.166
diff -u -b -r1.166 module_qual.m
--- compiler/module_qual.m	3 Apr 2008 05:26:45 -0000	1.166
+++ compiler/module_qual.m	19 Jul 2008 08:03:35 -0000
@@ -130,7 +130,7 @@
 
 :- import_module libs.compiler_util.
 :- import_module libs.options.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.module_imports.
 :- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_util.
@@ -1439,7 +1439,8 @@
             Ms = M0s
         ;
             ClassName = qualified(_, _),
-            sym_name_get_module_name(ClassName, unqualified(""), Module),
+            sym_name_get_module_name_default(ClassName, unqualified(""),
+                Module),
             Qualify = (pred(M0::in, M::out) is det :-
                 M0 = instance_method(A, Method0, C, D, E),
                 add_module_qualifier(Module, Method0, Method),
Index: compiler/modules.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/modules.m,v
retrieving revision 1.448
diff -u -b -r1.448 modules.m
--- compiler/modules.m	16 Jul 2008 03:30:29 -0000	1.448
+++ compiler/modules.m	19 Jul 2008 07:49:57 -0000
@@ -41,171 +41,23 @@
 :- module parse_tree.modules.
 :- interface.
 
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.timestamp.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.module_imports.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_item.
 :- import_module parse_tree.prog_io.
+:- import_module parse_tree.read_modules.
 
 :- import_module assoc_list.
 :- import_module bool.
 :- import_module digraph.
 :- import_module io.
 :- import_module list.
-:- import_module map.
 :- import_module maybe.
-:- import_module pair.
-:- import_module set.
-
-%-----------------------------------------------------------------------------%
-
-    % Succeeds iff the module referred to by the module name is one
-    % of the modules in the standard library.
-    %
-:- pred mercury_std_library_module_name(module_name::in) is semidet.
-
-    % module_name_to_file_name(Module, Extension, Mkdir, FileName):
-    %
-    % Convert a module name and file extension to the corresponding file name.
-    % If `MkDir' is yes, then create any directories needed.
-    %
-    % Currently we use the convention that the module `foo.bar.baz' should be
-    % named `foo.bar.baz.m', and allow other naming conventions with the
-    % `-f' option.
-    %
-    % Note that this predicate is also used to create some "phony" Makefile
-    % targets that do not have corresponding files, e.g. `<foo>.clean'.
-    %
-:- pred module_name_to_file_name(module_name::in, string::in, bool::in,
-    file_name::out, io::di, io::uo) is det.
-
-    % module_name_to_search_file_name(Module, Extension, FileName):
-    %
-    % As above, but for a file which might be in an installed library,
-    % not the current directory.
-    %
-    % With `--use-grade-subdirs', the current directory's `.mih' files are in
-    % `Mercury/<grade>/<arch>/Mercury/mihs', and those for installed libraries
-    % are in `<prefix>/lib/mercury/lib/<grade>/<arch>/inc/Mercury/mihs'.
-    %
-    % handle_options.m sets up the `--c-include-directory' options so that
-    % the name `<module>.mih' should be used in a context which requires
-    % searching for the `.mih files, for example in a C file.
-    %
-    % module_name_to_file_name would return
-    % `Mercury/<grade>/<arch>/Mercury/mihs/<module>.mihs',
-    % which would be used when writing or removing the `.mih' file.
-    %
-:- pred module_name_to_search_file_name(module_name::in, string::in,
-    file_name::out, io::di, io::uo) is det.
-
-    % module_name_to_lib_file_name(Prefix, Module, Extension, MkDir,
-    %       FileName):
-    %
-    % Like module_name_to_file_name, but also allows a prefix.
-    %
-    % Used for creating library names, e.g. `lib<foo>.$A' and `lib<foo>.so'.
-    %
-:- pred module_name_to_lib_file_name(string::in, module_name::in, string::in,
-    bool::in, file_name::out, io::di, io::uo) is det.
-
-    % fact_table_file_name(Module, FactTableFileName, Ext, MkDir, FileName):
-    % Returns the filename to use when compiling fact table files.
-    % If 'MkDir' is yes, then create any directories needed.
-    %
-:- pred fact_table_file_name(module_name::in, file_name::in, string::in,
-    bool::in, file_name::out, io::di, io::uo) is det.
-
-    % Convert a file name (excluding the trailing `.m') to the corresponding
-    % module name.
-    %
-:- pred file_name_to_module_name(file_name::in, module_name::out) is det.
-
-    % Convert a module name to a file name stem (e.g. foo.bar.baz).
-    %
-:- pred module_name_to_file_name(module_name::in, file_name::out) is det.
-
-    % Convert a module name to something that is suitable
-    % for use as a variable name in makefiles.
-    %
-:- pred module_name_to_make_var_name(module_name::in, string::out) is det.
-
-    % Generate the list of .NET DLLs which could be referred to by this module
-    % (including the module itself).
-    %
-    % If we are compiling a module within the standard library we should
-    % reference the runtime DLLs and all other library DLLs.  If we are
-    % outside the library we should just reference mercury.dll (which will
-    % contain all the DLLs).
-    %
-:- func referenced_dlls(module_name, list(module_name)) = list(module_name).
-
-%-----------------------------------------------------------------------------%
-
-    % read_mod(ModuleName, Extension, Descr, Search, ReturnTimestamp,
-    %       Items, Error, SourceFileName, MaybeTimestamp):
-    % Given a module name and a file extension (e.g. `.m', `.int', or `int2'),
-    % read in the list of items in that file.
-    %
-    % If Extension is ".m", and ModuleName is a nested module, then try
-    % searching for different filenames: for modules such as `foo.bar.baz.m'
-    % search first for `foo.bar.baz.m', then `bar.baz.m', then `baz.m'.
-    % If Search is yes, search all directories given by the option
-    % search_directories for the module.
-    % If ReturnTimestamp is yes, attempt to return the modification time
-    % of the file in MaybeTimestamp.
-    % If the actual module name (as determined by the `:- module' declaration)
-    % does not match the specified module name, then report an error message.
-    % Return the actual source file name found (excluding the directory part).
-    %
-    % N.B. This reads a module given the module name. If you want to read
-    % a module given the file name, use `read_mod_from_file'.
-    %
-:- pred read_mod(module_name::in, string::in, string::in, bool::in, bool::in,
-    list(item)::out, module_error::out, file_name::out,
-    maybe(timestamp)::out, io::di, io::uo) is det.
-
-    % read_mod_if_changed(ModuleName, Extension, Descr, Search,
-    %   OldTimestamp, Items, Error, SourceFileName, MaybeTimestamp):
-    %
-    % If the timestamp of the file specified by the given module name and
-    % file extension is newer than OldTimestamp, read the file, returning
-    % the new timestamp.
-    %
-    % If the file was read, MaybeTimestamp will contain the new timestamp.
-    % If the timestamp was unchanged, MaybeTimestamp will be
-    % `yes(OldTimestamp)'. If the file could not be read, MaybeTimestamp
-    % will be `no'.
-    %
-:- pred read_mod_if_changed(module_name::in, string::in, string::in, bool::in,
-    timestamp::in, list(item)::out, module_error::out, file_name::out,
-    maybe(timestamp)::out, io::di, io::uo) is det.
-
-    % Similar to read_mod, but doesn't return error messages.
-    %
-:- pred read_mod_ignore_errors(module_name::in, string::in, string::in,
-    bool::in, bool::in, list(item)::out, module_error::out, file_name::out,
-    maybe(timestamp)::out, io::di, io::uo) is det.
-
-    % read_mod_from_file(SourceFileName, Extension, Descr, Search,
-    %   ReturnTimestamp, Items, Error, ModuleName, MaybeTimestamp):
-    %
-    % Given a file name and a file extension (e.g. `.m', `.int', or `int2'),
-    % read in the list of items in that file.
-    % If Search is yes, search all directories given by the option
-    % search_directories for the module.
-    % If ReturnTimestamp is yes, attempt to return the modification time
-    % of the file in MaybeTimestamp. Return the module name (as determined
-    % by the `:- module' declaration, if any).
-    %
-    % N.B.  This reads a module given the file name. If you want to read a
-    % module given the module name, use `read_mod'.
-    %
-:- pred read_mod_from_file(file_name::in, string::in, string::in, bool::in,
-    bool::in, list(item)::out, module_error::out, module_name::out,
-    maybe(timestamp)::out, io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
 
@@ -237,172 +89,6 @@
     io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
-%
-% The `module_imports' structure
-%
-
-    % The `module_imports' structure holds information about
-    % a module and the modules that it imports.
-    %
-    % Note that we build this structure up as we go along.
-    % When generating the dependencies (for `--generate-dependencies'), the
-    % two fields that hold the direct imports do not include the imports via
-    % ancestors when the module is first read in; the ancestor imports are
-    % added later, once all the modules have been read in.  Similarly the
-    % indirect imports field is initially set to the empty list and filled
-    % in later.
-    %
-    % When compiling or when making interface files, the same sort of thing
-    % applies: initially all the list(module_name) fields except the public
-    % children field are set to empty lists, and then we add ancestor
-    % modules and imported modules to their respective lists as we process
-    % the interface files for those imported or ancestor modules.
-    %
-:- type module_imports
-    --->    module_imports(
-                % The source file.
-                source_file_name            :: file_name,
-
-                % The name of the top-level module in the source file
-                % containing the module that we are compiling.
-                source_file_module_name     :: module_name,
-
-                % The module (or sub-module) that we are compiling.
-                module_name                 :: module_name,
-
-                % The list of ancestor modules it inherits.
-                parent_deps                 :: list(module_name),
-
-                % The list of modules it directly imports in the interface
-                % (imports via ancestors count as direct).
-                int_deps                    :: list(module_name),
-
-                % The list of modules it directly imports in the
-                % implementation.
-                impl_deps                   :: list(module_name),
-
-                % The list of modules it indirectly imports.
-                indirect_deps               :: list(module_name),
-
-                children                    :: list(module_name),
-
-                % The list of its public children, i.e. child modules that
-                % it includes in the interface section.
-                public_children             :: list(module_name),
-
-                % The modules included in the same source file. This field
-                % is only set for the top-level module in each file.
-                nested_children             :: list(module_name),
-
-                % The list of filenames for fact tables in this module.
-                fact_table_deps             :: list(string),
-
-                % Whether or not the module contains foreign code, and if yes,
-                % which languages they use.
-                has_foreign_code            :: contains_foreign_code,
-
-                % The `:- pragma foreign_import_module' declarations.
-                foreign_import_modules      :: foreign_import_module_info_list,
-
-                % Does the module contain any `:- pragma foreign_export'
-                % declarations?
-                contains_foreign_export     :: contains_foreign_export,
-
-                % The contents of the module and its imports.
-                items                       :: list(item),
-
-                % Whether an error has been encountered when reading in
-                % this module.
-                error                       :: module_error,
-
-                % If we are doing smart recompilation, we need to keep
-                % the timestamps of the modules read in.
-                maybe_timestamps            :: maybe(module_timestamps),
-
-                % Does this module contain main/2?
-                has_main                    :: has_main,
-
-                % The directory containing the module source.
-                module_dir                  :: dir_name
-            ).
-
-:- type contains_foreign_code
-    --->    contains_foreign_code(set(foreign_language))
-    ;       no_foreign_code
-    ;       unknown.
-
-:- type contains_foreign_export
-    --->    contains_foreign_export
-    ;       no_foreign_export.
-
-    % When doing smart recompilation record for each module the suffix of
-    % the file that was read and the modification time of the file.
-    %
-:- type module_timestamps == map(module_name, module_timestamp).
-:- type module_timestamp
-    --->    module_timestamp(
-                suffix          :: string,
-                timestamp       :: timestamp,
-                need_qualifier  :: need_qualifier
-            ).
-
-    % recompilation_check.m records each file read to avoid reading it
-    % again. The string is the suffix of the file name.
-    %
-:- type read_modules == map(pair(module_name, string), read_module).
-
-:- type read_module
-    --->    read_module(
-                module_timestamp,
-                list(item),
-                module_error,
-                file_name
-            ).
-
-    % find_read_module(ReadModules, ModuleName, Suffix, ReturnTimestamp,
-    %   Items, MaybeTimestamp, Error, FileName)
-    %
-    % Check whether a file was read during recompilation checking.
-    %
-:- pred find_read_module(read_modules::in, module_name::in, string::in,
-    bool::in, list(item)::out, maybe(timestamp)::out, module_error::out,
-    file_name::out) is semidet.
-
-%-----------------------------------------------------------------------------%
-%
-% Access predicates for the module_imports structure
-%
-
-:- pred module_imports_get_source_file_name(module_imports::in, file_name::out)
-    is det.
-:- pred module_imports_get_module_name(module_imports::in, module_name::out)
-    is det.
-:- pred module_imports_get_impl_deps(module_imports::in,
-    list(module_name)::out) is det.
-:- pred module_imports_get_items(module_imports::in, list(item)::out) is det.
-:- pred module_imports_get_error(module_imports::in, module_error::out) is det.
-
-:- pred module_imports_set_items(list(item)::in,
-    module_imports::in, module_imports::out) is det.
-:- pred module_imports_set_error(module_error::in,
-    module_imports::in, module_imports::out) is det.
-
-    % Set the interface dependencies.
-    %
-:- pred module_imports_set_int_deps(list(module_name)::in,
-    module_imports::in, module_imports::out) is det.
-
-    % Set the implementation dependencies.
-    %
-:- pred module_imports_set_impl_deps(list(module_name)::in,
-    module_imports::in, module_imports::out) is det.
-
-    % Set the indirect dependencies.
-    %
-:- pred module_imports_set_indirect_deps(list(module_name)::in,
-    module_imports::in, module_imports::out) is det.
-
-%-----------------------------------------------------------------------------%
 
     % Make an item for a module declaration or pseudo-declaration
     % such as `:- imported' (which is inserted by the compiler, but can't be
@@ -569,20 +255,6 @@
 
 %-----------------------------------------------------------------------------%
 
-    % write_dependency_file(Module, AllDeps, MaybeTransOptDeps):
-    %
-    % Write out the per-module makefile dependencies (`.d') file for the
-    % specified module. AllDeps is the set of all module names which the
-    % generated code for this module might depend on, i.e. all that have been
-    % used or imported, directly or indirectly, into this module, including
-    % via .opt or .trans_opt files, and including parent modules of nested
-    % modules. MaybeTransOptDeps is a list of module names which the
-    % `.trans_opt' file may depend on.  This is set to `no' if the
-    % dependency list is not available.
-    %
-:- pred write_dependency_file(module_imports::in, set(module_name)::in,
-    maybe(list(module_name))::in, io::di, io::uo) is det.
-
     % maybe_read_dependency_file(ModuleName, MaybeTransOptDeps):
     %
     % If transitive intermodule optimization has been enabled, then read
@@ -639,98 +311,31 @@
 :- type lookup_module_imports == (func(module_name) = module_imports).
 :- mode lookup_module_imports == in(func(in) = out is det).
 
-    % get_dependencies(Items, ImportDeps, UseDeps):
-    %
-    % Get the list of modules that a list of items (explicitly) depends on.
-    % ImportDeps is the list of modules imported using `:- import_module',
-    % UseDeps is the list of modules imported using `:- use_module'.
-    % N.B. Typically you also need to consider the module's implicit
-    % dependencies (see get_implicit_dependencies/3), its parent modules
-    % (see get_ancestors/1) and possibly also the module's child modules
-    % (see get_children/2). You may also need to consider indirect
-    % dependencies.
-    %
-:- pred get_dependencies(list(item)::in, list(module_name)::out,
-    list(module_name)::out) is det.
-
-    % get_implicit_dependencies(Items, Globals, ImportDeps, UseDeps):
-    %
-    % Get the list of builtin modules (e.g. "public_builtin",
-    % "private_builtin") that a list of items may implicitly depend on.
-    % ImportDeps is the list of modules which should be automatically
-    % implicitly imported as if via `:- import_module', and UseDeps is
-    % the list which should be automatically implicitly imported as if via
-    % `:- use_module'.
-    %
-:- pred get_implicit_dependencies(list(item)::in, globals::in,
-    list(module_name)::out, list(module_name)::out) is det.
-
-    % get_ancestors(ModuleName) =  ParentDeps:
-    %
-    % ParentDeps is the list of ancestor modules for this module, oldest first;
-    % e.g. if the ModuleName is `foo.bar.baz', then ParentDeps would be
-    % [`foo', `foo.bar'].
-    %
-:- func get_ancestors(module_name) = list(module_name).
-
-    % init_dependencies(FileName, SourceFileModuleName, NestedModuleNames,
-    %   Error, Globals, ModuleName - Items, ModuleImports).
-    %
-:- pred init_dependencies(file_name::in, module_name::in,
-    list(module_name)::in, module_error::in, globals::in,
-    pair(module_name, list(item))::in, module_imports::out) is det.
-
 %-----------------------------------------------------------------------------%
+%
+% These predicates are exported for use by module_imports.m.
+%
+% XXX They shouldn't be needed; the representation of the program should have
+% all this information readily accessible.
 
-    % touch_interface_datestamp(ModuleName, Ext):
-    %
-    % Touch the datestamp file `ModuleName.Ext'. Datestamp files
-    % are used to record when each of the interface files was last
-    % updated.
-    %
-:- pred touch_interface_datestamp(module_name::in, string::in,
-    io::di, io::uo) is det.
-
-    % touch_datestamp(FileName):
-    %
-    % Update the modification time for the given file,
-    % clobbering the contents of the file.
-    %
-:- pred touch_datestamp(file_name::in, io::di, io::uo) is det.
-
-    % update_interface_return_succeeded(FileName, Succeeded):
-    %
-    % Call the shell script mercury_update_interface to update the
-    % interface file FileName from FileName.tmp if it has changed.
-    %
-:- pred update_interface_return_succeeded(file_name::in, bool::out,
-    io::di, io::uo) is det.
-
-:- pred update_interface(file_name::in, io::di, io::uo) is det.
-
-    % maybe_make_symlink(TargetFile, LinkName, Result):
+    % get_children(Items, IncludeDeps):
     %
-    % If `--use-symlinks' is set, attempt to make LinkName a
-    % symlink pointing to LinkTarget.
+    % IncludeDeps is the list of sub-modules declared with `:- include_module'
+    % in Items.
     %
-:- pred maybe_make_symlink(file_name::in, file_name::in, bool::out,
-    io::di, io::uo) is det.
+:- pred get_children(list(item)::in, list(module_name)::out) is det.
 
-    % copy_file(Source, Destination, Succeeded).
-    %
-    % XXX This belongs in the standard library.
+    % Given a module (well, a list of items), extract the interface
+    % part of that module, i.e. all the items between `:- interface'
+    % and `:- implementation'.
+    % The bodies of instance definitions are removed because
+    % the instance methods have not yet been module qualified.
     %
-:- pred copy_file(file_name::in, file_name::in, io.res::out,
-    io::di, io::uo) is det.
+:- pred get_interface(module_name::in, bool::in,
+    list(item)::in, list(item)::out) is det.
 
-    % make_symlink_or_copy_file(LinkTarget, LinkName, Succeeded):
-    %
-    % Attempt to make LinkName a symlink pointing to LinkTarget,
-    % copying LinkTarget to LinkName if that fails (or if
-    % `--use-symlinks' is not set).
-    %
-:- pred make_symlink_or_copy_file(file_name::in, file_name::in, bool::out,
-    io::di, io::uo) is det.
+:- pred get_foreign_self_imports(list(item)::in, list(foreign_language)::out)
+    is det.
 
 %-----------------------------------------------------------------------------%
 
@@ -748,61 +353,6 @@
     io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
-%
-% Java command-line tools utilities
-%
-
-    % Create a shell script with the same name as the given module to invoke
-    % Java with the appropriate options on the class of the same name.
-    %
-:- pred create_java_shell_script(module_name::in, bool::out,
-    io::di, io::uo) is det.
-
-    % Strip away the path prefix for a list of .class files.
-    %
-:- pred list_class_files_for_jar(module_name::in, string::in, string::out,
-    io::di, io::uo) is det.
-
-    % Get the value of the Java class path from the environment. (Normally
-    % it will be obtained from the CLASSPATH environment variable, but if
-    % that isn't present then the java.class.path variable may be used instead.
-    % This is used for the Java back-end, which doesn't support environment
-    % variables properly.)
-    %
-:- pred get_env_classpath(string::out, io::di, io::uo) is det.
-
-%-----------------------------------------------------------------------------%
-%
-% Erlang utilities
-%
-
-    % To avoid namespace collisions between Mercury standard modules and
-    % Erlang standard modules, we pretend the Mercury standard modules are in
-    % a "mercury" supermodule.  This function returns ModuleName with the
-    % extra qualifier if it is a standard library module.  Otherwise it
-    % returns it unchanged.
-    %
-:- func erlang_module_name(module_name) = module_name.
-
-    % Create a shell script with the same name as the given module to invoke
-    % the Erlang runtime system and execute the main/2 predicate in that
-    % module.
-    %
-:- pred create_erlang_shell_script(module_name::in, bool::out, io::di, io::uo)
-    is det.
-
-%-----------------------------------------------------------------------------%
-
-    % get_install_name_option(FileName, Option, !IO):
-    %
-    % Get the option string for setting the install-name of the shared library
-    % FileName. This is only used for systems which support the install-name
-    % option for shared libraries (such as Darwin).
-    %
-:- pred get_install_name_option(string::in, string::out, io::di, io::uo)
-    is det.
-
-%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -812,6 +362,8 @@
 :- import_module libs.handle_options.
 :- import_module libs.options.
 :- import_module make.              % XXX undesirable dependency
+:- import_module parse_tree.deps_map.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.module_qual.
 :- import_module parse_tree.prog_foreign.
@@ -820,6 +372,8 @@
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_util.
 :- import_module parse_tree.source_file_map.
+:- import_module parse_tree.module_cmds.
+:- import_module parse_tree.write_deps_file.
 :- import_module recompilation.version.
 
 :- import_module char.
@@ -827,7 +381,10 @@
 :- import_module getopt_io.
 :- import_module int.
 :- import_module library.
+:- import_module map.
 :- import_module multi_map.
+:- import_module pair.
+:- import_module set.
 :- import_module solutions.
 :- import_module sparse_bitset.
 :- import_module string.
@@ -838,526 +395,77 @@
 :- import_module varset.
 
 %-----------------------------------------------------------------------------%
+%
+% Private interfaces (.int0 files)
+%
 
-mercury_std_library_module_name(unqualified(Name)) :-
-    mercury_std_library_module(Name).
-mercury_std_library_module_name(qualified(Module, Name)) :-
-    module_name_to_file_name(qualified(Module, Name), ModuleNameStr),
-    mercury_std_library_module(ModuleNameStr).
-mercury_std_library_module_name(qualified(Module, Name)) :-
-    strip_outermost_qualifier(qualified(Module, Name), "mercury", ModuleName),
-    module_name_to_file_name(ModuleName, ModuleNameStr),
-    mercury_std_library_module(ModuleNameStr).
-
-module_name_to_search_file_name(ModuleName, Ext, FileName, !IO) :-
-    module_name_to_file_name_2(ModuleName, Ext, yes, no, FileName, !IO).
-
-module_name_to_file_name(ModuleName, Ext, MkDir, FileName, !IO) :-
-    module_name_to_file_name_2(ModuleName, Ext, no, MkDir, FileName,
-        !IO).
-
-:- pred module_name_to_file_name_2(module_name::in, string::in,
-    bool::in, bool::in, file_name::out, io::di, io::uo) is det.
-
-module_name_to_file_name_2(ModuleName0, Ext, Search, MkDir, FileName, !IO) :-
-    ( Ext = ".m" ->
-        % Look up the module in the module->file mapping.
-        source_file_map.lookup_module_source_file(ModuleName0, FileName, !IO)
-    ;
-        (
-            ( string.suffix(Ext, ".erl")
-            ; string.suffix(Ext, ".hrl")
-            ; string.suffix(Ext, ".beam")
-            )
-        ->
-            % Erlang uses `.' as a package separator and expects a module
-            % `a.b.c' to be in a file `a/b/c.erl'.  Rather than that, we use
-            % a flat namespace with `__' as module separators.
-            Sep = "__",
-            ModuleName = erlang_module_name(ModuleName0)
-        ;
-            Sep = ".",
-            ModuleName = ModuleName0
-        ),
-        string.append(sym_name_to_string_sep(ModuleName, Sep), Ext, BaseName),
-        choose_file_name(ModuleName, BaseName, Ext, Search, MkDir, FileName,
-            !IO)
-    ).
-
-module_name_to_lib_file_name(Prefix, ModuleName, Ext, MkDir, FileName, !IO) :-
-    BaseFileName = sym_name_to_string(ModuleName),
-    string.append_list([Prefix, BaseFileName, Ext], BaseName),
-    choose_file_name(ModuleName, BaseName, Ext, no, MkDir, FileName, !IO).
-
-fact_table_file_name(ModuleName, FactTableFileName, Ext, MkDir, FileName,
-        !IO) :-
-    extra_link_obj_file_name(ModuleName, FactTableFileName, Ext, MkDir,
-        FileName, !IO).
-
-    % extra_link_obj_file_name(Module, ExtraLinkObjName,
-    %   Ext, MkDir, FileName):
-    % Returns the filename to use when compiling extra objects that must be
-    % linked into the executable (currently used only for fact tables).
-    % If `MkDir' is yes, make any directories necessary.
-    %
-:- pred extra_link_obj_file_name(module_name::in, file_name::in, string::in,
-    bool::in, file_name::out, io::di, io::uo) is det.
-
-extra_link_obj_file_name(ModuleName, ExtraLinkObjName, Ext, MkDir, FileName,
-        !IO) :-
-    string.append(ExtraLinkObjName, Ext, BaseName),
-    choose_file_name(ModuleName, BaseName, Ext, no, MkDir, FileName, !IO).
-
-:- pred choose_file_name(module_name::in, string::in, string::in, bool::in,
-    bool::in, file_name::out, io::di, io::uo) is det.
+    % Read in the .int3 files that the current module depends on, and use
+    % these to qualify all the declarations as much as possible. Then write
+    % out the .int0 file.
+    %
+make_private_interface(SourceFileName, SourceFileModuleName, ModuleName,
+        MaybeTimestamp, Items0, !IO) :-
+    grab_unqual_imported_modules(SourceFileName, SourceFileModuleName,
+        ModuleName, Items0, Module, Error, !IO),
 
-choose_file_name(_ModuleName, BaseName, Ext, Search, MkDir, FileName, !IO) :-
-    globals.io_get_globals(Globals, !IO),
-    globals.lookup_bool_option(Globals, use_subdirs, UseSubdirs),
-    globals.lookup_bool_option(Globals, use_grade_subdirs, UseGradeSubdirs),
-    globals.lookup_string_option(Globals, library_extension, LibExt),
-    globals.lookup_string_option(Globals, shared_library_extension,
-        SharedLibExt),
-    (
-        (
-            UseSubdirs = no
-        ;
-            % If we're searching for (rather than writing) a `.mih' file,
-            % use the plain file name.  This is so that searches for files
-            % in installed libraries will work.  `--c-include-directory' is
-            % set so that searches for files in the current directory will
-            % work.
-            % Similarly for `.hrl' files.  We set `--erlang-include-directory'
-            % for those.
-            %
-            Search = yes,
-            ( Ext = ".mih"
-            ; Ext = ".mih.tmp"
-            ; Ext = ".hrl"
-            ; Ext = ".hrl.tmp"
-            )
-        )
-    ->
-        FileName = BaseName
+    % Check whether we succeeded.
+    % XXX zs: why does this code not check for fatal_module_errors?
+    ( Error = some_module_errors ->
+        module_name_to_file_name(ModuleName, ".int0", do_not_create_dirs,
+            FileName, !IO),
+        io.write_strings(["Error reading interface files.\n",
+            "`", FileName, "' not written.\n"], !IO)
     ;
-        %
-        % The source files, the final executables, library files (including
-        % .init files) output files intended for use by the user, and phony
-        % Mmake targets names go in the current directory
-        %
-        \+ (
-            UseGradeSubdirs = yes,
-            file_is_arch_or_grade_dependent(Globals, Ext)
-        ),
+        % Module-qualify all items.
+        module_imports_get_items(Module, Items1),
+        globals.io_get_globals(Globals, !IO),
+        module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+            FileName, !IO),
+        module_qualify_items(Items1, Items2, map.init, _, Globals, ModuleName,
+            yes(FileName), "", _, _, _, [], Specs),
         (
-            % Executable files.
-            ( Ext = ""
-            ; Ext = ".exe"
-            ; Ext = ".dll"
-            % Library files.
-            ; Ext = ".a"
-            ; Ext = ".$A"
-            ; Ext = ".so"
-            ; Ext = ".dylib"
-            ; Ext = ".$(EXT_FOR_SHARED_LIB)"
-            ; Ext = ".jar"
-            ; Ext = ".beams"
-            ; Ext = ".init"
-                    % mercury_update_interface
-                    % requires the `.init.tmp' files to
-                    % be in the same directory as the
-                    % `.init' files.
-            ; Ext = ".init.tmp"
-
-            % output files intended for use by the user
-            % (the .h_dump* and .c_dump* MLDS dumps
-            % also fit into this category, but for
-            % efficiency, to keep this as a switch,
-            % we deal with them below)
-            ; Ext = ".mh"
-                    % mercury_update_interface
-                    % requires the `.mh.tmp' files to
-                    % be in the same directory as the
-                    % `.mh' files.
-            ; Ext = ".mh.tmp"
-            ; Ext = ".err"
-            ; Ext = ".ugly"
-            ; Ext = ".hlds_dump"
-            ; Ext = ".mlds_dump"
-            ; Ext = ".dependency_graph"
-            ; Ext = ".order"
-            % Mmake targets
-            ; Ext = ".clean"
-            ; Ext = ".realclean"
-            ; Ext = ".depend"
-            ; Ext = ".install_ints"
-            ; Ext = ".install_opts"
-            ; Ext = ".install_hdrs"
-            ; Ext = ".install_grade_hdrs"
-            ; Ext = ".check"
-            ; Ext = ".ints"
-            ; Ext = ".int3s"
-            ; Ext = ".ss"
-            ; Ext = ".pic_ss"
-            ; Ext = ".ils"
-            ; Ext = ".javas"
-            ; Ext = ".classes"
-            ; Ext = ".erls"
-            ; Ext = ".beams"
-            ; Ext = ".opts"
-            ; Ext = ".trans_opts"
-            )
+            Specs = [_ | _],
+            write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors,
+                !IO),
+            io.write_strings(["`", FileName, "' not written.\n"], !IO)
         ;
-            % Output files intended for use by the user.
+            Specs = [],
+
+            % Write out the `.int0' file.
             %
-            ( string.prefix(Ext, ".c_dump")
-            ; string.prefix(Ext, ".mih_dump")
-            )
+            % XXX The following sequence of operations relies on the fact that
+            % any reversals done while processing it are undone by subsequent
+            % operations. Also, we should sort the contents of the .int0 file
+            % as we do for the other types of interface file. We don't do that
+            % at the moment because the code for doing that cannot handle
+            % the structure of lists of items that represent private
+            % interfaces.
+
+            strip_imported_items(Items2, Items3),
+            strip_clauses_from_interface(Items3, Items4),
+            handle_mutables_in_private_interface(ModuleName, Items4, Items5),
+            list.map(make_any_instances_abstract, Items5, Items6),
+            list.reverse(Items6, Items),
+            write_interface_file(SourceFileName, ModuleName,
+                ".int0", MaybeTimestamp,
+                [make_pseudo_decl(md_interface) | Items], !IO),
+            touch_interface_datestamp(ModuleName, ".date0", !IO)
         )
-    ->
-        FileName = BaseName
+    ).
+
+:- pred make_any_instances_abstract(item::in, item::out) is det.
+
+make_any_instances_abstract(Item0, Item) :-
+    ( Item0 = item_instance(InstanceInfo0) ->
+        InstanceInfo = make_instance_abstract(InstanceInfo0),
+        Item = item_instance(InstanceInfo)
     ;
-        %
-        % We need to handle a few cases specially.
-        %
-        (
-            ( Ext = ".dir/*.o"
-            ; Ext = ".dir/*.$O"
-            )
-        ->
-            SubDirName = "dirs"
-        ;
-            % .$O, .pic_o and .lpic_o files need to go in the
-            % same directory, so that using
-            % .$(EXT_FOR_PIC_OBJECTS) will work.
-            ( Ext = ".o"
-            ; Ext = ".$O"
-            ; Ext = ".lpic_o"
-            ; Ext = ".pic_o"
-            ; Ext = "$(EXT_FOR_PIC_OBJECTS)"
-            ; Ext = "_init.o"
-            ; Ext = "_init.$O"
-            ; Ext = "_init.lpic_o"
-            ; Ext = "_init.pic_o"
-            ; Ext = "_init.$(EXT_FOR_PIC_OBJECTS)"
-            )
-        ->
-            SubDirName = "os"
-        ;
-            % _init.c, _init.s, _init.o etc. files
-            % go in the cs, ss, os etc. subdirectories
-            string.append("_init.", ExtName, Ext)
-        ->
-            string.append(ExtName, "s", SubDirName)
-        ;
-            % .int.tmp, .opt.tmp, etc. files
-            % need to go in the ints, opts, etc. subdirectories
-            string.append(".", ExtName0, Ext),
-            string.remove_suffix(ExtName0, ".tmp", ExtName)
-        ->
-            string.append(ExtName, "s", SubDirName)
-        ;
-            % `.dv' files go in the `deps' subdirectory,
-            % along with the `.dep' files
-            Ext = ".dv"
-        ->
-            SubDirName = "deps"
-        ;
-            % Static and shared libraries go in the `lib' subdirectory.
-            ( Ext = LibExt
-            ; Ext = SharedLibExt
-            )
-        ->
-            SubDirName = "lib"
-        ;
-            % The usual case: `*.foo' files go in the `foos' subdirectory.
-            string.append(".", ExtName, Ext)
-        ->
-            string.append(ExtName, "s", SubDirName)
-        ;
-            Ext = ""
-        ->
-            SubDirName = "bin"
-        ;
-            string.append_list(["unknown extension `", Ext, "'"], ErrorMsg),
-            unexpected(this_file, ErrorMsg)
-        ),
-        make_file_name(SubDirName, Search, MkDir, BaseName, Ext, FileName, !IO)
-    ).
-
-file_name_to_module_name(FileName, ModuleName) :-
-    ModuleName = string_to_sym_name(FileName).
-
-module_name_to_file_name(ModuleName, FileName) :-
-    FileName = sym_name_to_string(ModuleName).
-
-module_name_to_make_var_name(ModuleName, MakeVarName) :-
-    MakeVarName = sym_name_to_string(ModuleName).
-
-maybe_make_symlink(LinkTarget, LinkName, Result, !IO) :-
-    globals.io_lookup_bool_option(use_symlinks, UseSymLinks, !IO),
-    (
-        UseSymLinks = yes,
-        io.remove_file_recursively(LinkName, _, !IO),
-        io.make_symlink(LinkTarget, LinkName, LinkResult, !IO),
-        Result = ( if LinkResult = ok then yes else no )
-    ;
-        UseSymLinks = no,
-        Result = no
-    ).
-
-copy_file(Source, Destination, Res, !IO) :-
-    % Try to use the system's cp command in order to preserve metadata.
-    globals.io_lookup_string_option(install_command, InstallCommand, !IO),
-    Command = string.join_list("   ", list.map(quote_arg,
-        [InstallCommand, Source, Destination])),
-    io.output_stream(OutputStream, !IO),
-    invoke_system_command(OutputStream, cmd_verbose, Command, Succeeded, !IO),
-    (
-        Succeeded = yes,
-        Res = ok
-    ;
-        Succeeded = no,
-        io.open_binary_input(Source, SourceRes, !IO),
-        (
-            SourceRes = ok(SourceStream),
-            io.open_binary_output(Destination, DestRes, !IO),
-            (
-                DestRes = ok(DestStream),
-                WriteByte = io.write_byte(DestStream),
-                io.binary_input_stream_foldl_io(SourceStream, WriteByte, Res,
-                    !IO),
-                io.close_binary_input(SourceStream, !IO),
-                io.close_binary_output(DestStream, !IO)
-            ;
-                DestRes = error(Error),
-                Res = error(Error)
-            )
-        ;
-            SourceRes = error(Error),
-            Res = error(Error)
-        )
-    ).
-
-make_symlink_or_copy_file(SourceFileName, DestinationFileName, Succeeded,
-        !IO) :-
-    globals.io_lookup_bool_option(use_symlinks, UseSymLinks, !IO),
-    (
-        UseSymLinks = yes,
-        LinkOrCopy = "linking",
-        io.make_symlink(SourceFileName, DestinationFileName, Result, !IO)
-    ;
-        UseSymLinks = no,
-        LinkOrCopy = "copying",
-        copy_file(SourceFileName, DestinationFileName, Result, !IO)
-    ),
-    (
-        Result = ok,
-        Succeeded = yes
-    ;
-        Result = error(Error),
-        Succeeded = no,
-        io.progname_base("mercury_compile", ProgName, !IO),
-        io.write_string(ProgName, !IO),
-        io.write_string(": error ", !IO),
-        io.write_string(LinkOrCopy, !IO),
-        io.write_string(" `", !IO),
-        io.write_string(SourceFileName, !IO),
-        io.write_string("' to `", !IO),
-        io.write_string(DestinationFileName, !IO),
-        io.write_string("': ", !IO),
-        io.write_string(io.error_message(Error), !IO),
-        io.nl(!IO),
-        io.flush_output(!IO)
-    ).
-
-:- pred make_file_name(dir_name::in, bool::in, bool::in, file_name::in,
-    string::in, file_name::out, io::di, io::uo) is det.
-
-make_file_name(SubDirName, Search, MkDir, BaseName, Ext, FileName, !IO) :-
-    globals.io_get_globals(Globals, !IO),
-    globals.lookup_bool_option(Globals, use_grade_subdirs, UseGradeSubdirs),
-    globals.lookup_string_option(Globals, fullarch, FullArch),
-    (
-        UseGradeSubdirs = yes,
-        file_is_arch_or_grade_dependent(Globals, Ext),
-        %
-        % If we're searching for (rather than writing) the file, just search
-        % in Mercury/<ext>s. This is so that searches for files in installed
-        % libraries work.  `--intermod-directories' is set so this will
-        % work.
-        %
-        \+ (
-            Search = yes,
-            ( Ext = ".opt"
-            ; Ext = ".trans_opt"
-            ; Ext = ".analysis"
-            ; Ext = ".imdg"
-            ; Ext = ".request"
-            )
-        )
-    ->
-        grade_directory_component(Globals, Grade),
-
-        % The extra "Mercury" is needed so we can use `--intermod-directory
-        % Mercury/<grade>/<fullarch>' and `--c-include
-        % Mercury/<grade>/<fullarch>' to find the local `.opt' and `.mih'
-        % files without messing up the search for the files for installed
-        % libraries.
-        DirComponents = ["Mercury", Grade, FullArch, "Mercury", SubDirName]
-    ;
-        DirComponents = ["Mercury", SubDirName]
-    ),
-    (
-        MkDir = yes,
-        DirName = dir.relative_path_name_from_components(DirComponents),
-        make_directory(DirName, _, !IO)
-    ;
-        MkDir = no
-    ),
-    Components = DirComponents ++ [BaseName],
-    FileName = dir.relative_path_name_from_components(Components).
-
-:- pred file_is_arch_or_grade_dependent(globals::in, string::in) is semidet.
-
-file_is_arch_or_grade_dependent(_, Ext) :-
-    file_is_arch_or_grade_dependent_2(Ext).
-file_is_arch_or_grade_dependent(Globals, Ext0) :-
-    string.append(Ext, ".tmp", Ext0), % for mercury_update_interface.
-    file_is_arch_or_grade_dependent(Globals, Ext).
-file_is_arch_or_grade_dependent(Globals, Ext) :-
-    globals.lookup_string_option(Globals, executable_file_extension, Ext).
-file_is_arch_or_grade_dependent(Globals, Ext) :-
-    (
-        globals.lookup_string_option(Globals,
-            object_file_extension, ObjExt)
-    ;
-        globals.lookup_string_option(Globals,
-            pic_object_file_extension, ObjExt)
-    ;
-        globals.lookup_string_option(Globals,
-            link_with_pic_object_file_extension, ObjExt)
-    ),
-    ( Ext = ObjExt
-    ; Ext = "_init" ++ ObjExt
-    ).
-file_is_arch_or_grade_dependent(Globals, Ext) :-
-    globals.lookup_string_option(Globals, library_extension, LibExt),
-    Ext = LibExt.
-file_is_arch_or_grade_dependent(Globals, Ext) :-
-    globals.lookup_string_option(Globals, shared_library_extension, Ext).
-
-:- pred file_is_arch_or_grade_dependent_2(string::in) is semidet.
-
-    % The `.used' file isn't grade dependent itself, but it contains
-    % information collected while compiling a grade-dependent
-    % `.c', `il', etc file.
-file_is_arch_or_grade_dependent_2(".used").
-file_is_arch_or_grade_dependent_2(".opt").
-file_is_arch_or_grade_dependent_2(".optdate").
-file_is_arch_or_grade_dependent_2(".trans_opt").
-file_is_arch_or_grade_dependent_2(".trans_opt_date").
-file_is_arch_or_grade_dependent_2(".analysis").
-file_is_arch_or_grade_dependent_2(".analysis_date").
-file_is_arch_or_grade_dependent_2(".imdg").
-file_is_arch_or_grade_dependent_2(".init").
-file_is_arch_or_grade_dependent_2(".request").
-file_is_arch_or_grade_dependent_2(".mih").
-file_is_arch_or_grade_dependent_2(".c").
-file_is_arch_or_grade_dependent_2(".c_date").
-file_is_arch_or_grade_dependent_2(".s").
-file_is_arch_or_grade_dependent_2(".s_date").
-file_is_arch_or_grade_dependent_2(".pic_s").
-file_is_arch_or_grade_dependent_2(".pic_s_date").
-file_is_arch_or_grade_dependent_2(".il").
-file_is_arch_or_grade_dependent_2(".il_date").
-file_is_arch_or_grade_dependent_2(".java").
-file_is_arch_or_grade_dependent_2(".java_date").
-file_is_arch_or_grade_dependent_2(".class").
-file_is_arch_or_grade_dependent_2(".erl").
-file_is_arch_or_grade_dependent_2(".erl_date").
-file_is_arch_or_grade_dependent_2(".beam").
-file_is_arch_or_grade_dependent_2(".beams").
-file_is_arch_or_grade_dependent_2(".hrl").
-file_is_arch_or_grade_dependent_2(".dir").
-file_is_arch_or_grade_dependent_2(".dll").
-file_is_arch_or_grade_dependent_2(".$A").
-file_is_arch_or_grade_dependent_2(".a").
-file_is_arch_or_grade_dependent_2("_init.c").
-file_is_arch_or_grade_dependent_2("_init.$O").
-file_is_arch_or_grade_dependent_2("_init.erl").
-file_is_arch_or_grade_dependent_2("_init.beam").
-
-%-----------------------------------------------------------------------------%
-%
-% Private interfaces (.int0 files)
-%
-
-    % Read in the .int3 files that the current module depends on, and use
-    % these to qualify all the declarations as much as possible. Then write
-    % out the .int0 file.
-    %
-make_private_interface(SourceFileName, SourceFileModuleName, ModuleName,
-        MaybeTimestamp, Items0, !IO) :-
-    grab_unqual_imported_modules(SourceFileName, SourceFileModuleName,
-        ModuleName, Items0, Module, Error, !IO),
-
-    % Check whether we succeeded.
-    % XXX zs: why does this code not check for fatal_module_errors?
-    ( Error = some_module_errors ->
-        module_name_to_file_name(ModuleName, ".int0", no, FileName, !IO),
-        io.write_strings(["Error reading interface files.\n",
-            "`", FileName, "' not written.\n"], !IO)
-    ;
-        % Module-qualify all items.
-        module_imports_get_items(Module, Items1),
-        globals.io_get_globals(Globals, !IO),
-        module_name_to_file_name(ModuleName, ".m", no, FileName, !IO),
-        module_qualify_items(Items1, Items2, map.init, _, Globals, ModuleName,
-            yes(FileName), "", _, _, _, [], Specs),
-        (
-            Specs = [_ | _],
-            write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors,
-                !IO),
-            io.write_strings(["`", FileName, "' not written.\n"], !IO)
-        ;
-            Specs = [],
-
-            % Write out the `.int0' file.
-            %
-            % XXX The following sequence of operations relies on the fact that
-            % any reversals done while processing it are undone by subsequent
-            % operations. Also, we should sort the contents of the .int0 file
-            % as we do for the other types of interface file. We don't do that
-            % at the moment because the code for doing that cannot handle
-            % the structure of lists of items that represent private
-            % interfaces.
-
-            strip_imported_items(Items2, Items3),
-            strip_clauses_from_interface(Items3, Items4),
-            handle_mutables_in_private_interface(ModuleName, Items4, Items5),
-            list.map(make_any_instances_abstract, Items5, Items6),
-            list.reverse(Items6, Items),
-            write_interface_file(SourceFileName, ModuleName,
-                ".int0", MaybeTimestamp,
-                [make_pseudo_decl(md_interface) | Items], !IO),
-            touch_interface_datestamp(ModuleName, ".date0", !IO)
-        )
-    ).
-
-:- pred make_any_instances_abstract(item::in, item::out) is det.
-
-make_any_instances_abstract(Item0, Item) :-
-    ( Item0 = item_instance(InstanceInfo0) ->
-        InstanceInfo = make_instance_abstract(InstanceInfo0),
-        Item = item_instance(InstanceInfo)
-    ;
-        Item = Item0
-    ).
-
-    % Expand any mutable declarations in the item list into the pred and mode
-    % declarations for their access predicates.  Only these components of a
-    % mutable declaration should be written to a private interface file.
+        Item = Item0
+    ).
+
+    % Expand any mutable declarations in the item list into the pred and mode
+    % declarations for their access predicates.  Only these components of a
+    % mutable declaration should be written to a private interface file.
     %
 :- pred handle_mutables_in_private_interface(module_name::in,
     list(item)::in, list(item)::out) is det.
@@ -1426,16 +534,18 @@
         module_imports_get_items(Module0, !:InterfaceItems),
         % XXX zs: why does this code not check for fatal_module_errors?
         ( Error = some_module_errors ->
-            module_name_to_file_name(ModuleName, ".int", no, IntFileName, !IO),
-            module_name_to_file_name(ModuleName, ".int2", no, Int2FileName,
-                !IO),
+            module_name_to_file_name(ModuleName, ".int", do_not_create_dirs,
+                IntFileName, !IO),
+            module_name_to_file_name(ModuleName, ".int2", do_not_create_dirs,
+                Int2FileName, !IO),
             io.write_strings(["Error reading short interface files.\n",
                 "`", IntFileName, "' and ",
                 "`", Int2FileName, "' not written.\n"], !IO)
         ;
             % Module-qualify all items.
             globals.io_get_globals(Globals, !IO),
-            module_name_to_file_name(ModuleName, ".m", no, FileName, !IO),
+            module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+                FileName, !IO),
             module_qualify_items(!InterfaceItems, map.init, _, Globals,
                 ModuleName, yes(FileName), "", _, _, _, [], Specs),
 
@@ -1445,8 +555,8 @@
             write_error_specs(Specs, Globals, 0, _NumWarnings, 0, NumErrors,
                 !IO),
             ( NumErrors > 0 ->
-                module_name_to_file_name(ModuleName, ".int", no, IntFileName,
-                    !IO),
+                module_name_to_file_name(ModuleName, ".int",
+                    do_not_create_dirs, IntFileName, !IO),
                 io.write_strings(["`", IntFileName, "' ", "not written.\n"],
                     !IO)
             ;
@@ -2159,7 +1269,7 @@
             ArgType = higher_order_type(Args0, MaybeRetType, _, _),
             (
                 MaybeRetType = yes(RetType),
-                Args = [ RetType  | Args0 ]
+                Args = [RetType  | Args0]
             ;
                 MaybeRetType = no,
                 Args = Args0
@@ -2395,7 +1505,8 @@
 :- pred warn_no_exports(module_name::in, io::di, io::uo) is det.
 
 warn_no_exports(ModuleName, !IO) :-
-    module_name_to_file_name(ModuleName, ".m", no, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+        FileName, !IO),
     Context = context_init(FileName, 1),
     Severity = severity_conditional(warn_nothing_exported, yes,
         severity_warning, no),
@@ -2427,9 +1538,10 @@
         InterfaceItems0, !IO) :-
     % Create (e.g.) `foo.int.tmp'.
     string.append(Suffix, ".tmp", TmpSuffix),
-    module_name_to_file_name(ModuleName, Suffix, yes, OutputFileName, !IO),
-    module_name_to_file_name(ModuleName, TmpSuffix, no, TmpOutputFileName,
-        !IO),
+    module_name_to_file_name(ModuleName, Suffix, do_create_dirs,
+        OutputFileName, !IO),
+    module_name_to_file_name(ModuleName, TmpSuffix, do_not_create_dirs,
+        TmpOutputFileName, !IO),
     globals.io_lookup_bool_option(line_numbers, LineNumbers, !IO),
     globals.io_set_option(line_numbers, bool(no), !IO),
     globals.io_lookup_bool_option(generate_item_version_numbers,
@@ -2441,9 +1553,10 @@
             MaybeTimestamp = yes(Timestamp),
 
             % Read in the previous version of the file.
-            read_mod_ignore_errors(ModuleName, Suffix,
-                "Reading old interface for module", yes, no,
-                OldItems, OldError, _OldIntFileName, _OldTimestamp, !IO),
+            read_module_ignore_errors(ModuleName, Suffix,
+                "Reading old interface for module",
+                do_search, do_not_return_timestamp, OldItems, OldError,
+                _OldIntFileName, _OldTimestamp, !IO),
             ( OldError = no_module_errors ->
                 MaybeOldItems = yes(OldItems)
             ;
@@ -2483,168 +1596,6 @@
     globals.io_set_option(line_numbers, bool(LineNumbers), !IO),
     update_interface(OutputFileName, !IO).
 
-update_interface(OutputFileName, !IO) :-
-    update_interface_return_succeeded(OutputFileName, Succeeded, !IO),
-    (
-        Succeeded = no,
-        report_error("problem updating interface files.", !IO)
-    ;
-        Succeeded = yes
-    ).
-
-update_interface_return_succeeded(OutputFileName, Succeeded, !IO) :-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    maybe_write_string(Verbose, "% Updating interface:\n", !IO),
-    TmpOutputFileName = OutputFileName ++ ".tmp",
-    io.open_binary_input(OutputFileName, OutputFileRes, !IO),
-    (
-        OutputFileRes = ok(OutputFileStream),
-        io.open_binary_input(TmpOutputFileName, TmpOutputFileRes, !IO),
-        (
-            TmpOutputFileRes = ok(TmpOutputFileStream),
-            binary_input_stream_cmp(OutputFileStream, TmpOutputFileStream,
-                FilesDiffer, !IO),
-            io.close_binary_input(OutputFileStream, !IO),
-            io.close_binary_input(TmpOutputFileStream, !IO),
-            (
-                FilesDiffer = ok(ok(no)),
-                Succeeded = yes,
-                maybe_write_string(Verbose, "% ", !IO),
-                maybe_write_string(Verbose, OutputFileName, !IO),
-                maybe_write_string(Verbose, "' has not changed.\n", !IO),
-                io.remove_file(TmpOutputFileName, _, !IO)
-            ;
-                FilesDiffer = ok(ok(yes)),
-                update_interface_create_file("CHANGED", OutputFileName,
-                    TmpOutputFileName, Succeeded, !IO)
-            ;
-                FilesDiffer = ok(error(TmpFileError)),
-                Succeeded = no,
-                io.write_string("Error reading `", !IO),
-                io.write_string(TmpOutputFileName, !IO),
-                io.write_string("': ", !IO),
-                io.write_string(io.error_message(TmpFileError), !IO),
-                io.nl(!IO)
-            ;
-                FilesDiffer = error(_, _),
-                update_interface_create_file("been CREATED", OutputFileName,
-                    TmpOutputFileName, Succeeded, !IO)
-            )
-        ;
-
-            TmpOutputFileRes = error(TmpOutputFileError),
-            Succeeded = no,
-            io.close_binary_input(OutputFileStream, !IO),
-            io.write_string("Error creating `", !IO),
-            io.write_string(OutputFileName, !IO),
-            io.write_string("': ", !IO),
-            io.write_string(io.error_message(TmpOutputFileError), !IO),
-            io.nl(!IO)
-        )
-    ;
-        OutputFileRes = error(_),
-        update_interface_create_file("been CREATED", OutputFileName,
-            TmpOutputFileName, Succeeded, !IO)
-    ).
-
-:- pred binary_input_stream_cmp_2(io.binary_input_stream::in, int::in,
-    bool::out, io.res(bool)::in, io.res(bool)::out,
-    io::di, io::uo) is det.
-
-binary_input_stream_cmp_2(TmpOutputFileStream, Byte, Continue, _, Differ,
-        !IO) :-
-    io.read_byte(TmpOutputFileStream, TmpByteResult, !IO),
-    (
-        TmpByteResult = ok(TmpByte),
-        ( TmpByte = Byte ->
-            Differ = ok(no),
-            Continue = yes
-        ;
-            Differ = ok(yes),
-            Continue = no
-        )
-    ;
-        TmpByteResult = eof,
-        Differ = ok(yes),
-        Continue = no
-    ;
-        TmpByteResult = error(TmpByteError),
-        Differ = error(TmpByteError) : io.res(bool),
-        Continue = no
-    ).
-
-:- pred binary_input_stream_cmp(io.binary_input_stream::in,
-    io.binary_input_stream::in, io.maybe_partial_res(io.res(bool))::out,
-    io::di, io::uo) is det.
-
-binary_input_stream_cmp(OutputFileStream, TmpOutputFileStream, FilesDiffer,
-        !IO) :-
-    io.binary_input_stream_foldl2_io_maybe_stop(OutputFileStream,
-        binary_input_stream_cmp_2(TmpOutputFileStream),
-        ok(no), FilesDiffer0, !IO),
-
-    % Check whether there is anything left in TmpOutputFileStream
-    ( FilesDiffer0 = ok(ok(no)) ->
-        io.read_byte(TmpOutputFileStream, TmpByteResult2, !IO),
-        (
-            TmpByteResult2 = ok(_),
-            FilesDiffer = ok(ok(yes))
-        ;
-            TmpByteResult2 = eof,
-            FilesDiffer = FilesDiffer0
-        ;
-            TmpByteResult2 = error(Error),
-            FilesDiffer = ok(error(Error))
-        )
-    ;
-        FilesDiffer = FilesDiffer0
-    ).
-
-:- pred update_interface_create_file(string::in, string::in, string::in,
-    bool::out, io::di, io::uo) is det.
-
-update_interface_create_file(Msg, OutputFileName, TmpOutputFileName, Succeeded,
-        !IO) :-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    maybe_write_string(Verbose,
-        "% `" ++ OutputFileName ++ "' has " ++ Msg ++ ".\n", !IO),
-    copy_file(TmpOutputFileName, OutputFileName, MoveRes, !IO),
-    (
-        MoveRes = ok,
-        Succeeded = yes
-    ;
-        MoveRes = error(MoveError),
-        Succeeded = no,
-        io.write_string("Error creating `" ++ OutputFileName ++ "': " ++
-            io.error_message(MoveError), !IO),
-        io.nl(!IO)
-    ),
-    io.remove_file(TmpOutputFileName, _, !IO).
-
-%-----------------------------------------------------------------------------%
-
-touch_interface_datestamp(ModuleName, Ext, !IO) :-
-    module_name_to_file_name(ModuleName, Ext, yes, OutputFileName, !IO),
-    touch_datestamp(OutputFileName, !IO).
-
-touch_datestamp(OutputFileName, !IO) :-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    maybe_write_string(Verbose,
-        "% Touching `" ++ OutputFileName ++ "'... ", !IO),
-    maybe_flush_output(Verbose, !IO),
-    io.open_output(OutputFileName, Result, !IO),
-    (
-        Result = ok(OutputStream),
-        io.write_string(OutputStream, "\n", !IO),
-        io.close_output(OutputStream, !IO),
-        maybe_write_string(Verbose, " done.\n", !IO)
-    ;
-        Result = error(IOError),
-        io.error_message(IOError, IOErrorMessage),
-        io.write_string("\nError opening `" ++ OutputFileName
-            ++ "' for output: " ++ IOErrorMessage ++ ".\n", !IO)
-    ).
-
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -2653,7 +1604,7 @@
         Error, !IO) :-
     % Find out which modules this one depends on.
     AncestorModules = get_ancestors(ModuleName),
-    get_dependencies(Items0, IntImportedModules0, IntUsedModules0,
+    get_dependencies_int_imp(Items0, IntImportedModules0, IntUsedModules0,
         ImpImportedModules0, ImpUsedModules0),
 
     ImportedModules0 = IntImportedModules0 ++ ImpImportedModules0,
@@ -2662,7 +1613,8 @@
     some [!Specs] (
         !:Specs = [],
 
-        module_name_to_file_name(ModuleName, ".m", no, FileName, !IO),
+        module_name_to_file_name(ModuleName, ".m", do_not_create_dirs,
+            FileName, !IO),
         warn_if_import_self_or_ancestor(ModuleName, FileName, AncestorModules,
             ImportedModules0, UsedModules0, !Specs),
 
@@ -2694,7 +1646,7 @@
         % exported_to_submodules.  We do that by splitting out the
         % implementation declarations and putting them in a special
         % `:- private_interface' section.
-        %
+
         get_children(Items0, Children),
         (
             Children = [],
@@ -2815,7 +1767,7 @@
         Items0, !:Module, Error, !IO) :-
     % Find out which modules this one depends on.
     ParentDeps = get_ancestors(ModuleName),
-    get_dependencies(Items0, IntImportDeps0, IntUseDeps0,
+    get_dependencies_int_imp(Items0, IntImportDeps0, IntUseDeps0,
         ImpImportDeps, ImpUseDeps),
 
     % Construct the initial module import structure.
@@ -2906,47 +1858,6 @@
 
 %-----------------------------------------------------------------------------%
 
-find_read_module(ReadModules, ModuleName, Suffix, ReturnTimestamp,
-        Items, MaybeTimestamp, Error, FileName) :-
-    map.search(ReadModules, ModuleName - Suffix, ReadModule),
-    ReadModule = read_module(ModuleTimestamp, Items, Error, FileName),
-    (
-        ReturnTimestamp = yes,
-        ModuleTimestamp = module_timestamp(_, Timestamp, _),
-        MaybeTimestamp = yes(Timestamp)
-    ;
-        ReturnTimestamp = no,
-        MaybeTimestamp = no
-    ).
-
-:- pred init_module_imports(file_name::in, module_name::in, module_name::in,
-    list(item)::in, list(module_name)::in, list(module_name)::in,
-    list(string)::in, maybe(module_timestamps)::in, module_imports::out)
-    is det.
-
-init_module_imports(SourceFileName, SourceFileModuleName, ModuleName,
-        Items0, PublicChildren, NestedChildren, FactDeps,
-        MaybeTimestamps, Module) :-
-    maybe_add_foreign_import_module(ModuleName, Items0, Items),
-    Module = module_imports(SourceFileName, SourceFileModuleName,
-        ModuleName, [], [], [], [], [], PublicChildren,
-        NestedChildren, FactDeps, unknown, [],
-        no_foreign_export, Items, no_module_errors,
-        MaybeTimestamps, no_main, dir.this_directory).
-
-module_imports_get_source_file_name(Module, Module ^ source_file_name).
-module_imports_get_module_name(Module, Module ^ module_name).
-module_imports_get_impl_deps(Module, Module ^ impl_deps).
-module_imports_get_items(Module, Module ^ items).
-module_imports_get_error(Module, Module ^ error).
-module_imports_set_items(Items, Module, Module ^ items := Items).
-module_imports_set_error(Error, Module, Module ^ error := Error).
-module_imports_set_int_deps(IntDeps, Module, Module ^ int_deps := IntDeps).
-module_imports_set_impl_deps(ImplDeps, Module,
-        Module ^ impl_deps := ImplDeps).
-module_imports_set_indirect_deps(IndirectDeps, Module,
-        Module ^ indirect_deps := IndirectDeps).
-
 append_pseudo_decl(PseudoDecl, Module0, Module) :-
     Items0 = Module0 ^ items,
     list.append(Items0, [make_pseudo_decl(PseudoDecl)], Items),
@@ -2958,270 +1869,43 @@
 
 %-----------------------------------------------------------------------------%
 
-get_implicit_dependencies(Items, Globals, ImportDeps, UseDeps) :-
-    add_implicit_imports(Items, Globals, [], ImportDeps, [], UseDeps).
-
-:- pred add_implicit_imports(list(item)::in, globals::in,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out) is det.
+    % Warn if a module imports itself, or an ancestor.
+    %
+:- pred warn_if_import_self_or_ancestor(module_name::in, string::in,
+    list(module_name)::in, list(module_name)::in, list(module_name)::in,
+    list(error_spec)::in, list(error_spec)::out) is det.
 
-add_implicit_imports(Items, Globals, !ImportDeps, !UseDeps) :-
-    !:ImportDeps = [mercury_public_builtin_module | !.ImportDeps],
-    !:UseDeps = [mercury_private_builtin_module | !.UseDeps],
-    items_need_imports(Items, no, ItemsNeedTabling,
-        no, ItemsNeedTablingStatistics, no, ItemsNeedSTM),
-    % We should include mercury_table_builtin_module if the Items contain
-    % a tabling pragma, or if one of --use-minimal-model (either kind) and
-    % --trace-table-io is specified. In the former case, we may also need
-    % to import mercury_table_statistics_module.
-    (
-        ItemsNeedTabling = yes,
-        !:UseDeps = [mercury_table_builtin_module | !.UseDeps],
-        (
-            ItemsNeedTablingStatistics = yes,
-            !:UseDeps = [mercury_table_statistics_module | !.UseDeps]
-        ;
-            ItemsNeedTablingStatistics = no
-        )
-    ;
-        ItemsNeedTabling = no,
-        expect(unify(ItemsNeedTablingStatistics, no), this_file,
-            "add_implicit_imports: tabling statistics without tabling"),
-        (
-            % These forms of tabling cannot ask for statistics.
-            (
-                globals.lookup_bool_option(Globals,
-                    use_minimal_model_stack_copy, yes)
-            ;
-                globals.lookup_bool_option(Globals,
-                    use_minimal_model_own_stacks, yes)
-            ;
-                globals.lookup_bool_option(Globals, trace_table_io, yes)
-            )
-        ->
-            !:UseDeps = [mercury_table_builtin_module | !.UseDeps]
-        ;
-            true
+warn_if_import_self_or_ancestor(ModuleName, FileName, AncestorModules,
+        ImportedModules, UsedModules, !Specs) :-
+    IsImportedAncestor = (pred(Import::out) is nondet :-
+        list.member(Import, AncestorModules),
+        ( list.member(Import, ImportedModules)
+        ; list.member(Import, UsedModules)
         )
     ),
+    solutions.aggregate(IsImportedAncestor,
+        warn_imported_ancestor(ModuleName, FileName), !Specs),
     (
-        ItemsNeedSTM = yes,
-        !:UseDeps = [mercury_stm_builtin_module, mercury_exception_module,
-            mercury_univ_module | !.UseDeps]
-    ;
-        ItemsNeedSTM = no
-    ),
-    globals.lookup_bool_option(Globals, profile_deep, Deep),
-    (
-        Deep = yes,
-        !:UseDeps = [mercury_profiling_builtin_module | !.UseDeps]
-    ;
-        Deep = no
-    ),
-    (
-        (
-            globals.lookup_bool_option(Globals,
-                record_term_sizes_as_words, yes)
-        ;
-            globals.lookup_bool_option(Globals,
-                record_term_sizes_as_cells, yes)
+        ( list.member(ModuleName, ImportedModules)
+        ; list.member(ModuleName, UsedModules)
         )
     ->
-        !:UseDeps = [mercury_term_size_prof_builtin_module | !.UseDeps]
-    ;
-        true
-    ),
-    globals.get_target(Globals, Target),
-    globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
-    globals.lookup_bool_option(Globals, parallel, Parallel),
-    (
-        Target = target_c,
-        HighLevelCode = no,
-        Parallel = yes
-    ->
-        !:UseDeps = [mercury_par_builtin_module | !.UseDeps]
+        term.context_init(FileName, 1, Context),
+        SelfPieces = [words("Warning: module"),
+            sym_name(ModuleName), words("imports itself!")],
+        SelfMsg = simple_msg(Context,
+            [option_is_set(warn_simple_code, yes, [always(SelfPieces)])]),
+        Severity = severity_conditional(warn_simple_code, yes,
+            severity_warning, no),
+        SelfSpec = error_spec(Severity, phase_parse_tree_to_hlds,
+            [SelfMsg]),
+        !:Specs = [SelfSpec | !.Specs]
     ;
         true
-    ),
-    globals.lookup_bool_option(Globals, use_regions, UseRegions),
-    (
-        UseRegions = yes,
-        !:UseDeps = [mercury_region_builtin_module | !.UseDeps]
-    ;
-        UseRegions = no
-    ),
-    globals.lookup_bool_option(Globals, source_to_source_debug, SSDB),
-    (
-        SSDB = yes,
-        !:UseDeps = [mercury_ssdb_builtin_module | !.UseDeps]
-    ;
-        SSDB = no
     ).
 
-:- pred items_need_imports(list(item)::in,
-    bool::in, bool::out, bool::in, bool::out, bool::in, bool::out) is det.
-
-items_need_imports([], !ItemsNeedTabling,
-        !ItemsNeedTablingStatistics, !ItemsNeedSTM).
-items_need_imports([Item | Items], !ItemsNeedTabling,
-        !ItemsNeedTablingStatistics, !ItemsNeedSTM) :-
-    (
-        Item = item_pragma(ItemPragma),
-        ItemPragma = item_pragma_info(_, Pragma, _),
-        Pragma = pragma_tabled(_, _, _, _, _, MaybeAttributes)
-    ->
-        !:ItemsNeedTabling = yes,
-        (
-            MaybeAttributes = no,
-            % We cannot be done yet. If !.ItemsNeedTablingStatistics and
-            % !.ItemsNeedSTM were already both `yes', !.ItemsNeedTabling
-            % would have been too, and we would have stopped before looking
-            % at this item.
-            items_need_imports(Items, !ItemsNeedTabling,
-                !ItemsNeedTablingStatistics, !ItemsNeedSTM)
-        ;
-            MaybeAttributes = yes(Attributes),
-            StatsAttr = Attributes ^ table_attr_statistics,
-            (
-                StatsAttr = table_gather_statistics,
-                !:ItemsNeedTablingStatistics = yes,
-                (
-                    !.ItemsNeedSTM = yes
-                    % There is nothing left to search for; stop recursing.
-                ;
-                    !.ItemsNeedSTM = no,
-                    items_need_imports(Items, !ItemsNeedTabling,
-                        !ItemsNeedTablingStatistics, !ItemsNeedSTM)
-                )
-            ;
-                StatsAttr = table_dont_gather_statistics
-            )
-        )
-    ;
-        Item = item_clause(ItemClause),
-        Body = ItemClause ^ cl_body,
-        goal_contains_stm_atomic(Body) = yes
-    ->
-        !:ItemsNeedSTM = yes,
-        (
-            !.ItemsNeedTabling = yes,
-            !.ItemsNeedTablingStatistics = yes
-        ->
-            % There is nothing left to search for; stop recursing.
-            true
-        ;
-            items_need_imports(Items, !ItemsNeedTabling,
-                !ItemsNeedTablingStatistics, !ItemsNeedSTM)
-        )
-    ;
-        items_need_imports(Items, !ItemsNeedTabling,
-            !ItemsNeedTablingStatistics, !ItemsNeedSTM)
-    ).
-
-:- func goal_contains_stm_atomic(goal) = bool.
-
-goal_contains_stm_atomic(GoalExpr - _Context) = ContainsAtomic :-
-    (
-        ( GoalExpr = true_expr
-        ; GoalExpr = fail_expr
-        ),
-        ContainsAtomic = no
-    ;
-        ( GoalExpr = conj_expr(SubGoalA, SubGoalB)
-        ; GoalExpr = par_conj_expr(SubGoalA, SubGoalB)
-        ; GoalExpr = disj_expr(SubGoalA, SubGoalB)
-        ),
-        ContainsAtomic = two_goals_contain_stm_atomic(SubGoalA, SubGoalB)
-    ;
-        ( GoalExpr = some_expr(_, SubGoal)
-        ; GoalExpr = all_expr(_, SubGoal)
-        ; GoalExpr = some_state_vars_expr(_, SubGoal)
-        ; GoalExpr = all_state_vars_expr(_, SubGoal)
-        ; GoalExpr = promise_purity_expr(_, _, SubGoal)
-        ; GoalExpr = promise_equivalent_solutions_expr(_, _, _, SubGoal)
-        ; GoalExpr = promise_equivalent_solution_sets_expr(_, _, _, SubGoal)
-        ; GoalExpr = promise_equivalent_solution_arbitrary_expr(_, _, _,
-            SubGoal)
-        ; GoalExpr = trace_expr(_, _, _, _, SubGoal)
-        ),
-        ContainsAtomic = goal_contains_stm_atomic(SubGoal)
-    ;
-        ( GoalExpr = implies_expr(SubGoalA, SubGoalB)
-        ; GoalExpr = equivalent_expr(SubGoalA, SubGoalB)
-        ),
-        ContainsAtomic = two_goals_contain_stm_atomic(SubGoalA, SubGoalB)
-    ;
-        GoalExpr = not_expr(SubGoal),
-        ContainsAtomic = goal_contains_stm_atomic(SubGoal)
-    ;
-        GoalExpr = if_then_else_expr(_, _, Cond, Then, Else),
-        ContainsAtomic = three_goals_contain_stm_atomic(Cond, Then, Else)
-    ;
-        GoalExpr = atomic_expr(_, _, _, _, _),
-        ContainsAtomic = yes
-    ;
-        ( GoalExpr = event_expr(_, _)
-        ; GoalExpr = call_expr(_, _, _)
-        ; GoalExpr = unify_expr(_, _, _)
-        ),
-        ContainsAtomic = no
-    ).
-
-:- func two_goals_contain_stm_atomic(goal, goal) = bool.
-
-two_goals_contain_stm_atomic(GoalA, GoalB) = ContainsAtomic :-
-    ( goal_contains_stm_atomic(GoalA) = yes ->
-        ContainsAtomic = yes
-    ;
-        ContainsAtomic = goal_contains_stm_atomic(GoalB)
-    ).
-
-:- func three_goals_contain_stm_atomic(goal, goal, goal) = bool.
-
-three_goals_contain_stm_atomic(GoalA, GoalB, GoalC) = ContainsAtomic :-
-    ( goal_contains_stm_atomic(GoalA) = yes ->
-        ContainsAtomic = yes
-    ;
-        ContainsAtomic = two_goals_contain_stm_atomic(GoalB, GoalC)
-    ).
-
-    % Warn if a module imports itself, or an ancestor.
-    %
-:- pred warn_if_import_self_or_ancestor(module_name::in, string::in,
-    list(module_name)::in, list(module_name)::in, list(module_name)::in,
-    list(error_spec)::in, list(error_spec)::out) is det.
-
-warn_if_import_self_or_ancestor(ModuleName, FileName, AncestorModules,
-        ImportedModules, UsedModules, !Specs) :-
-    IsImportedAncestor = (pred(Import::out) is nondet :-
-        list.member(Import, AncestorModules),
-        ( list.member(Import, ImportedModules)
-        ; list.member(Import, UsedModules)
-        )
-    ),
-    solutions.aggregate(IsImportedAncestor,
-        warn_imported_ancestor(ModuleName, FileName), !Specs),
-    (
-        ( list.member(ModuleName, ImportedModules)
-        ; list.member(ModuleName, UsedModules)
-        )
-    ->
-        term.context_init(FileName, 1, Context),
-        SelfPieces = [words("Warning: module"),
-            sym_name(ModuleName), words("imports itself!")],
-        SelfMsg = simple_msg(Context,
-            [option_is_set(warn_simple_code, yes, [always(SelfPieces)])]),
-        Severity = severity_conditional(warn_simple_code, yes,
-            severity_warning, no),
-        SelfSpec = error_spec(Severity, phase_parse_tree_to_hlds,
-            [SelfMsg]),
-        !:Specs = [SelfSpec | !.Specs]
-    ;
-        true
-    ).
-
-:- pred warn_imported_ancestor(module_name::in, string::in, module_name::in,
-    list(error_spec)::in, list(error_spec)::out) is det.
+:- pred warn_imported_ancestor(module_name::in, string::in, module_name::in,
+    list(error_spec)::in, list(error_spec)::out) is det.
 
 warn_imported_ancestor(ModuleName, FileName, AncestorName, !Specs) :-
     term.context_init(FileName, 1, Context),
@@ -3312,780 +1996,13 @@
 
 %-----------------------------------------------------------------------------%
 
-write_dependency_file(Module, AllDepsSet, MaybeTransOptDeps, !IO) :-
-    Module = module_imports(SourceFileName, SourceFileModuleName,
-        ModuleName, ParentDeps, IntDeps, ImplDeps, IndirectDeps,
-        _Children, InclDeps, NestedDeps, FactDeps0,
-        ContainsForeignCode, ForeignImports0, _ContainsForeignExport,
-        Items, _Error, _Timestamps, _HasMain, _Dir),
-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    module_name_to_make_var_name(ModuleName, MakeVarName),
-    module_name_to_file_name(ModuleName, ".d", yes, DependencyFileName, !IO),
-    module_name_to_file_name(ModuleName, ".trans_opt_date", no,
-        TransOptDateFileName, !IO),
-    %
-    % To avoid problems with concurrent updates of `.d' files
-    % during parallel makes, we first create the file with a
-    % temporary name, and then rename it to the desired name
-    % when we've finished.
-    %
-    io.make_temp(dir.dirname(DependencyFileName), "tmp_d",
-        TmpDependencyFileName, !IO),
-    maybe_write_string(Verbose, "% Writing auto-dependency file `", !IO),
-    maybe_write_string(Verbose, DependencyFileName, !IO),
-    maybe_write_string(Verbose, "'...", !IO),
-    maybe_flush_output(Verbose, !IO),
-    io.open_output(TmpDependencyFileName, Result, !IO),
-    (
-        Result = error(IOError),
-        maybe_write_string(Verbose, " failed.\n", !IO),
-        maybe_flush_output(Verbose, !IO),
-        io.error_message(IOError, IOErrorMessage),
-        string.append_list(["error opening temporary file `",
-            TmpDependencyFileName, "' for output: ",
-            IOErrorMessage], Message),
-        report_error(Message, !IO)
-    ;
-        Result = ok(DepStream),
-        list.append(IntDeps, ImplDeps, LongDeps0),
-        ShortDeps0 = IndirectDeps,
-        set.list_to_set(LongDeps0, LongDepsSet0),
-        set.delete(LongDepsSet0, ModuleName, LongDepsSet),
-        set.list_to_set(ShortDeps0, ShortDepsSet0),
-        set.difference(ShortDepsSet0, LongDepsSet, ShortDepsSet1),
-        set.delete(ShortDepsSet1, ModuleName, ShortDepsSet),
-        set.to_sorted_list(LongDepsSet, LongDeps),
-        set.to_sorted_list(ShortDepsSet, ShortDeps),
-        set.to_sorted_list(AllDepsSet, AllDeps),
-        list.sort_and_remove_dups(FactDeps0, FactDeps),
-
-        (
-            MaybeTransOptDeps = yes(TransOptDeps0),
-            set.list_to_set(TransOptDeps0, TransOptDepsSet0),
-            set.intersect(TransOptDepsSet0, LongDepsSet, TransOptDepsSet),
-            set.to_sorted_list(TransOptDepsSet, TransOptDateDeps),
-            %
-            % Note that maybe_read_dependency_file searches for
-            % this exact pattern.
-            %
-            io.write_strings(DepStream, [TransOptDateFileName, " :"], !IO),
-            write_dependencies_list(TransOptDateDeps, ".trans_opt", DepStream,
-                !IO)
-        ;
-            MaybeTransOptDeps = no
-        ),
-
-        (
-            FactDeps = [_ | _],
-            io.write_strings(DepStream,
-                ["\n\n", MakeVarName, ".fact_tables ="], !IO),
-            write_file_dependencies_list(FactDeps, "", DepStream, !IO),
-            io.nl(DepStream, !IO),
-            globals.io_lookup_bool_option(assume_gmake, AssumeGmake, !IO),
-            (
-                AssumeGmake = yes,
-                io.write_strings(DepStream, [
-                    "\n\n", MakeVarName,
-                    ".fact_tables.os = $(", MakeVarName,
-                    ".fact_tables:%=$(os_subdir)%.$O)\n\n",
-                    MakeVarName,
-                    ".fact_tables.cs = $(", MakeVarName,
-                    ".fact_tables:%=$(cs_subdir)%.c)\n\n"
-                ], !IO)
-            ;
-                AssumeGmake = no,
-                io.write_strings(DepStream,
-                    [MakeVarName, ".fact_tables.cs ="], !IO),
-                write_fact_table_dependencies_list(ModuleName,
-                    FactDeps, ".c", DepStream, !IO),
-                io.write_strings(DepStream, ["\n\n",
-                    MakeVarName, ".fact_tables.os ="], !IO),
-                write_fact_table_dependencies_list(ModuleName,
-                    FactDeps, ".$O", DepStream, !IO),
-                io.nl(DepStream, !IO)
-            )
-        ;
-            FactDeps = []
-        ),
-
-        ( string.remove_suffix(SourceFileName, ".m", SourceFileBase) ->
-            ErrFileName = SourceFileBase ++ ".err"
-        ;
-            unexpected(this_file, "source file doesn't end in `.m'")
-        ),
-        module_name_to_file_name(ModuleName, ".optdate", no, OptDateFileName,
-            !IO),
-        module_name_to_file_name(ModuleName, ".c_date", no, CDateFileName,
-            !IO),
-        module_name_to_file_name(ModuleName, ".s_date", no, AsmDateFileName,
-            !IO),
-        module_name_to_file_name(ModuleName, ".pic_s_date", no,
-            PicAsmDateFileName, !IO),
-        module_name_to_file_name(ModuleName, ".$O", no, ObjFileName, !IO),
-        module_name_to_file_name(ModuleName, ".il_date", no, ILDateFileName,
-            !IO),
-        module_name_to_file_name(ModuleName, ".java_date", no,
-            JavaDateFileName, !IO),
-        % XXX Why is the extension hardcoded to .pic_o here?  That looks
-        % wrong.  It should probably be .$(EXT_FOR_PIC_OBJECT) - juliensf.
-        module_name_to_file_name(ModuleName, ".pic_o", no, PicObjFileName,
-            !IO),
-        module_name_to_file_name(ModuleName, ".int0", no, Int0FileName, !IO),
-        io.write_strings(DepStream, ["\n\n",
-            OptDateFileName, " ",
-            TransOptDateFileName, " ",
-            ErrFileName, " ",
-            CDateFileName, " ",
-            AsmDateFileName, " ",
-            PicAsmDateFileName, " ",
-            ILDateFileName, " ",
-            JavaDateFileName
-        ], !IO),
-        io.write_strings(DepStream, [" : ", SourceFileName], !IO),
-        % If the module contains nested sub-modules then `.int0'
-        % file must first be built.
-        (
-            InclDeps = [_ | _],
-            io.write_strings(DepStream, [" ", Int0FileName], !IO)
-        ;
-            InclDeps = []
-        ),
-        write_dependencies_list(ParentDeps, ".int0", DepStream, !IO),
-        write_dependencies_list(LongDeps, ".int", DepStream, !IO),
-        write_dependencies_list(ShortDeps, ".int2", DepStream, !IO),
-
-        NestedExts = [
-            ".optdate",
-            ".trans_opt_date",
-            ".c_date",
-            ".s_date",
-            ".pic_s_date",
-            ".dir/*.$O",
-            ".il_date",
-            ".java_date"],
-
-        % If a module contains nested-submodules then we need to build
-        % the nested children before attempting to build the parent module.
-        (
-            NestedDeps = []
-        ;
-            NestedDeps = [_ | _],
-            Write = (pred(Ext::in, !.LIO::di, !:LIO::uo) is det :-
-                module_name_to_file_name(ModuleName, Ext, no, ExtName, !LIO),
-                io.write_strings(DepStream, ["\n\n", ExtName, " : "], !LIO),
-                write_dependencies_list(NestedDeps, Ext, DepStream, !LIO)
-            ),
-            list.foldl(Write, NestedExts, !IO)
-        ),
-        (
-            FactDeps = [_ | _],
-            io.write_strings(DepStream, [
-                " \\\n\t$(", MakeVarName, ".fact_tables)\n\n",
-                "$(", MakeVarName, ".fact_tables.os) : $(",
-                MakeVarName, ".fact_tables) ",
-                SourceFileName, "\n\n",
-                "$(", MakeVarName, ".fact_tables.cs) : ",
-                ObjFileName, "\n"
-            ], !IO)
-        ;
-            FactDeps = []
-        ),
-
-        globals.io_lookup_bool_option(use_opt_files, UseOptFiles, !IO),
-        globals.io_lookup_bool_option(intermodule_optimization, Intermod, !IO),
-        globals.io_lookup_accumulating_option(intermod_directories,
-            IntermodDirs, !IO),
-
-        % If intermodule_optimization is enabled then all the .mh files
-        % must exist because it is possible that the .c file imports them
-        % directly or indirectly.
-        (
-            Intermod = yes,
-            io.write_strings(DepStream, ["\n\n", ObjFileName, " : "], !IO),
-            write_dependencies_list(AllDeps, ".mh", DepStream, !IO)
-        ;
-            Intermod = no
-        ),
-        (
-            ( Intermod = yes
-            ; UseOptFiles = yes
-            )
-        ->
-            io.write_strings(DepStream, [
-                "\n\n",
-                TransOptDateFileName, " ",
-                ErrFileName, " ",
-                CDateFileName, " ",
-                AsmDateFileName, " ",
-                PicAsmDateFileName, " ",
-                ILDateFileName, " ",
-                JavaDateFileName, " : "
-            ], !IO),
-
-            % The target (e.g. C) file only depends on the .opt files
-            % from the current directory, so that inter-module optimization
-            % works when the .opt files for the library are unavailable.
-            % This is only necessary because make doesn't allow conditional
-            % dependencies. The dependency on the current module's .opt file
-            % is to make sure the module gets type-checked without having
-            % the definitions of abstract types from other modules.
-            %
-            % XXX The code here doesn't correctly handle dependencies
-            % on `.int' and `.int2' files needed by the `.opt' files.
-            globals.io_lookup_bool_option(transitive_optimization, TransOpt,
-                !IO),
-            globals.io_lookup_bool_option(use_trans_opt_files, UseTransOpt,
-                !IO),
-
-            (
-                ( TransOpt = yes
-                ; UseTransOpt = yes
-                )
-            ->
-                bool.not(UseTransOpt, BuildOptFiles),
-                get_both_opt_deps(BuildOptFiles, [ModuleName | LongDeps],
-                    IntermodDirs, OptDeps, TransOptDeps, !IO),
-                OptInt0Deps = sort_and_remove_dups(
-                    condense(list.map(get_ancestors, OptDeps))),
-                write_dependencies_list(OptDeps, ".opt", DepStream, !IO),
-                write_dependencies_list(OptInt0Deps, ".int0", DepStream, !IO),
-
-                io.write_strings(DepStream, [
-                    "\n\n",
-                    ErrFileName, " ",
-                    CDateFileName, " ",
-                    AsmDateFileName, " ",
-                    PicAsmDateFileName, " ",
-                    ILDateFileName, " ",
-                    JavaDateFileName, " : "
-                ], !IO),
-                write_dependencies_list(TransOptDeps, ".trans_opt", DepStream,
-                    !IO)
-            ;
-                bool.not(UseOptFiles, BuildOptFiles),
-                get_opt_deps(BuildOptFiles, [ModuleName | LongDeps],
-                    IntermodDirs, ".opt", OptDeps, !IO),
-                OptInt0Deps = sort_and_remove_dups(
-                    condense(list.map(get_ancestors, OptDeps))),
-                write_dependencies_list(OptDeps, ".opt", DepStream, !IO),
-                write_dependencies_list(OptInt0Deps, ".int0", DepStream, !IO)
-            )
-        ;
-            true
-        ),
-
-        globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
-        globals.io_get_target(CompilationTarget, !IO),
-        (
-            HighLevelCode = yes,
-            CompilationTarget = target_c
-        ->
-            % For --high-level-code with --target c, we need to make sure that
-            % we generate the header files for imported modules before
-            % compiling the C files, since the generated C files
-            % #include those header files.
-
-            io.write_strings(DepStream, [
-                "\n\n",
-                PicObjFileName, " ",
-                ObjFileName, " :"
-            ], !IO),
-            write_dependencies_list(AllDeps, ".mih", DepStream, !IO)
-        ;
-            true
-        ),
-
-        % We need to tell make how to make the header files. The header files
-        % are actually built by the same command that creates the .c or .s
-        % file, so we just make them depend on the .c or .s files.
-        % This is needed for the --high-level-code rule above, and for
-        % the rules introduced for `:- pragma foreign_import_module'
-        % declarations. In some grades the header file won't actually be built
-        % (e.g. LLDS grades for modules not containing `:- pragma export'
-        % declarations), but this rule won't do any harm.
-
-        module_name_to_file_name(ModuleName, ".c", no, CFileName, !IO),
-        module_name_to_file_name(ModuleName, ".s", no, AsmFileName, !IO),
-        module_name_to_file_name(ModuleName, ".mh", no, HeaderFileName, !IO),
-        module_name_to_file_name(ModuleName, ".mih", no, HeaderFileName2, !IO),
-        io.write_strings(DepStream, [
-            "\n\n",
-            "ifeq ($(TARGET_ASM),yes)\n",
-            HeaderFileName, " ", HeaderFileName2, " : ", AsmFileName, "\n",
-            "else\n",
-            HeaderFileName, " ",  HeaderFileName2, " : ", CFileName, "\n",
-            "endif"
-        ], !IO),
-
-        %
-        % The `.module_dep' file is made as a side effect of
-        % creating the `.c', `.s', `.il', or `.java'.
-        %
-        module_name_to_file_name(ModuleName, ".il", no, ILFileName, !IO),
-        module_name_to_file_name(ModuleName, ".java", no, JavaFileName, !IO),
-        module_name_to_file_name(ModuleName, make_module_dep_file_extension,
-            no, ModuleDepFileName, !IO),
-        io.write_strings(DepStream, [
-            "\n\n",
-            "ifeq ($(TARGET_ASM),yes)\n",
-            ModuleDepFileName, " : ", AsmFileName, "\n",
-            "else\n",
-            " ifeq ($(findstring il,$(GRADE)),il)\n",
-            ModuleDepFileName, " : ", ILFileName, "\n",
-            "  ifeq ($(findstring java,$(GRADE)),java)\n",
-            ModuleDepFileName, " : ", JavaFileName, "\n",
-            "  else\n",
-            ModuleDepFileName, " : ", CFileName, "\n",
-            "  endif\n",
-            " endif\n",
-            "endif"
-        ], !IO),
-
-        % The .date and .date0 files depend on the .int0 files for the parent
-        % modules, and the .int3 files for the directly and indirectly imported
-        % modules.
-        %
-        % For nested sub-modules, the `.date' files for the parent modules
-        % also depend on the same things as the `.date' files for this module,
-        % since all the `.date' files will get produced by a single mmc
-        % command. Similarly for `.date0' files, except these don't depend
-        % on the `.int0' files, because when doing the
-        % `--make-private-interface' for nested modules, mmc will process
-        % the modules in outermost to innermost order so as to produce each
-        % `.int0' file before it is needed.
-
-        module_name_to_file_name(ModuleName, ".date", no, DateFileName, !IO),
-        module_name_to_file_name(ModuleName, ".date0", no, Date0FileName, !IO),
-        io.write_strings(DepStream, [
-            "\n\n", DateFileName, " ",
-            Date0FileName
-        ], !IO),
-        write_dependencies_list(ParentDeps, ".date", DepStream, !IO),
-        io.write_strings(DepStream, [" : ", SourceFileName], !IO),
-        write_dependencies_list(ParentDeps, ".int0", DepStream, !IO),
-        write_dependencies_list(LongDeps, ".int3", DepStream, !IO),
-        write_dependencies_list(ShortDeps, ".int3", DepStream, !IO),
-
-        io.write_strings(DepStream, ["\n\n", Date0FileName], !IO),
-        write_dependencies_list(ParentDeps, ".date0", DepStream, !IO),
-        io.write_strings(DepStream, [" : ", SourceFileName], !IO),
-        write_dependencies_list(LongDeps, ".int3", DepStream, !IO),
-        write_dependencies_list(ShortDeps, ".int3", DepStream, !IO),
-        io.write_string(DepStream, "\n\n", !IO),
-
-        % If we can pass the module name rather than the file name, then do so.
-        % `--smart-recompilation' doesn't work if the file name is passed
-        % and the module name doesn't match the file name.
-
-        have_source_file_map(HaveMap, !IO),
-        (
-            HaveMap = yes,
-            module_name_to_file_name(SourceFileModuleName, ModuleArg)
-        ;
-            HaveMap = no,
-            ModuleArg = SourceFileName
-        ),
-
-        globals.io_get_target(Target, !IO),
-        globals.io_lookup_bool_option(sign_assembly, SignAssembly, !IO),
-        globals.io_get_globals(Globals, !IO),
-
-        % If we are on the IL backend, add the dependency that the
-        % top level dll of a nested module hierachy depends on all
-        % of it sub-modules dlls, as they are referenced from
-        % inside the top level dll.
-        % XXX Do we need to do the same for Java?
-
-        module_name_to_file_name(ModuleName, ".dll", no, DllFileName, !IO),
-        module_name_to_file_name(ModuleName, ".class", no, ClassFileName, !IO),
-        module_name_to_file_name(ModuleName, ".beam", no, BeamFileName, !IO),
-        SubModules = submodules(ModuleName, AllDeps),
-        (
-            Target = target_il,
-            SubModules = [_ | _]
-        ->
-            io.write_strings(DepStream, [DllFileName, " : "], !IO),
-            write_dll_dependencies_list(SubModules, "", DepStream, !IO),
-            io.nl(DepStream, !IO)
-        ;
-            true
-        ),
-
-        (
-            ContainsForeignCode = contains_foreign_code(LangSet),
-            ForeignImports = ForeignImports0
-        ;
-            ContainsForeignCode = unknown,
-            get_item_list_foreign_code(Globals, Items, LangSet,
-                ForeignImports1, _),
-            % If we're generating the `.dep' file, ForeignImports0 will contain
-            % a conservative approximation to the set of foreign imports
-            % needed which will include imports required by imported modules.
-            (
-                ForeignImports0 = [],
-                ForeignImports = ForeignImports1
-            ;
-                ForeignImports0 = [_ | _],
-                ForeignImports = ForeignImports0
-            )
-        ;
-            ContainsForeignCode = no_foreign_code,
-            set.init(LangSet),
-            ForeignImports = ForeignImports0
-        ),
-
-        % Handle dependencies introduced by
-        % `:- pragma foreign_import_module' declarations.
-
-        list.filter_map(
-            (pred(ForeignImportMod::in, Import::out) is semidet :-
-                Import = foreign_import_module_name_from_module(
-                    ForeignImportMod, SourceFileModuleName),
-
-                % XXX We can't include mercury.dll as mmake can't find it,
-                % but we know that it exists.
-                Import \= unqualified("mercury")
-            ), ForeignImports, ForeignImportedModules),
-        (
-            ForeignImportedModules = []
-        ;
-            ForeignImportedModules = [_ | _],
-            (
-                Target = target_il,
-                ForeignImportTargets = [DllFileName],
-                ForeignImportExt = ".dll"
-            ;
-                Target = target_java,
-                ForeignImportTargets = [ClassFileName],
-                ForeignImportExt = ".java"
-            ;
-                Target = target_erlang,
-                ForeignImportTargets = [BeamFileName],
-                ForeignImportExt = ".hrl"
-            ;
-                Target = target_c,
-                % NOTE: for C (and asm) the possible targets might be a .o
-                % file _or_ a .pic_o file.  We need to include dependencies
-                % for the latter otherwise invoking mmake with a <module>.pic_o
-                % target will break.
-                ForeignImportTargets = [ObjFileName, PicObjFileName],
-                ForeignImportExt = ".mh"
-            ;
-                Target = target_asm,
-                ForeignImportTargets = [ObjFileName, PicObjFileName],
-                ForeignImportExt = ".mh"
-            ;
-                % XXX These are just the C ones at the moment.
-                Target = target_x86_64,
-                ForeignImportTargets = [ObjFileName, PicObjFileName],
-                ForeignImportExt = ".mh"
-            ),
-            WriteForeignImportTarget = (pred(ForeignImportTarget::in,
-                    !.IO::di, !:IO::uo) is det :-
-                io.write_string(DepStream, "\n\n", !IO),
-                io.write_string(DepStream, ForeignImportTarget, !IO),
-                io.write_string(DepStream, " : ", !IO),
-                write_dependencies_list(ForeignImportedModules,
-                    ForeignImportExt, DepStream, !IO),
-                io.write_string(DepStream, "\n\n", !IO)
-            ),
-            list.foldl(WriteForeignImportTarget, ForeignImportTargets,
-                !IO)
-        ),
-
-        (
-            Target = target_il,
-            not set.empty(LangSet)
-        ->
-            Langs = set.to_sorted_list(LangSet),
-            list.foldl(write_foreign_dependency_for_il(DepStream,
-                ModuleName, AllDeps, ForeignImports), Langs, !IO)
-        ;
-            true
-        ),
-
-        % If we are signing the assembly, then we will need the strong key
-        % to sign the il file with so add a dependency that the il file
-        % requires the strong name file `mercury.sn'. Also add the variable
-        % ILASM_KEYFLAG-<module> which is used to build the command line
-        % for ilasm.
-        (
-            Target = target_il,
-            SignAssembly = yes
-        ->
-            module_name_to_make_var_name(ModuleName, ModuleNameString),
-            module_name_to_file_name(ModuleName, ".il", no, IlFileName, !IO),
-
-            io.write_strings(DepStream, [
-                "ILASM_KEYFLAG-", ModuleNameString,
-                    " = /keyf=mercury.sn\n",
-                IlFileName, " : mercury.sn\n"], !IO)
-        ;
-            true
-        ),
-
-        module_name_to_file_name(ModuleName, ".int", no, IntFileName, !IO),
-        module_name_to_file_name(ModuleName, ".int2", no, Int2FileName, !IO),
-        module_name_to_file_name(ModuleName, ".int3", no, Int3FileName, !IO),
-        module_name_to_file_name(ModuleName, ".opt", no, OptFileName, !IO),
-        module_name_to_file_name(ModuleName, ".trans_opt", no,
-            TransOptFileName, !IO),
-        module_name_to_file_name(ModuleName, ".date3", no, Date3FileName, !IO),
-
-        % We add some extra dependencies to the generated `.d' files, so that
-        % local `.int', `.opt', etc. files shadow the installed versions
-        % properly (e.g. for when you're trying to build a new version
-        % of an installed library). This saves the user from having to add
-        % these explicitly if they have multiple libraries installed
-        % in the same installation hierarchy which aren't independent (e.g.
-        % one uses another). These extra dependencies are necessary due to
-        % the way the combination of search paths and pattern rules
-        % works in Make.
-        %
-        % Be very careful about changing the following rules. The `@:' is a
-        % silent do-nothing command. It is used to force GNU Make to recheck
-        % the timestamp on the target file.  (It is a pity that GNU Make
-        % doesn't have a way of handling these sorts of rules in a
-        % nicer manner.)
-
-        io.write_strings(DepStream, [
-            "\n",
-            Int0FileName, " : ", Date0FileName, "\n",
-            "\t@:\n",
-            IntFileName, " : ", DateFileName, "\n",
-            "\t@:\n",
-            Int2FileName, " : ", DateFileName, "\n",
-            "\t@:\n",
-            Int3FileName, " : ", Date3FileName, "\n",
-            "\t@:\n",
-            OptFileName, " : ", OptDateFileName, "\n",
-            "\t@:\n",
-            TransOptFileName, " : ", TransOptDateFileName, "\n",
-            "\t@:\n"
-        ], !IO),
-
-        globals.io_lookup_bool_option(use_subdirs, UseSubdirs, !IO),
-        (
-            UseSubdirs = yes,
-            io.nl(DepStream, !IO),
-            list.foldl(write_subdirs_shorthand_rule(DepStream, ModuleName),
-                [".c", ".$O", ".pic_o", ".s", ".pic_s",
-                ".java", ".class", ".il", ".dll"], !IO)
-        ;
-            UseSubdirs = no
-        ),
-
-        ( SourceFileName \= default_source_file(ModuleName) ->
-            % The pattern rules in Mmake.rules won't work, since the source
-            % file name doesn't match the expected source file name for this
-            % module name. This can occur due to just the use of different
-            % source file names, or it can be due to the use of nested modules.
-            % So we need to output hard-coded rules in this case.
-            %
-            % The rules output below won't work in the case of nested modules
-            % with parallel makes, because it will end up invoking the same
-            % command twice (since it produces two output files) at the same
-            % time.
-            %
-            % Any changes here will require corresponding changes to
-            % scripts/Mmake.rules. See that file for documentation
-            % on these rules.
-
-            io.write_strings(DepStream, [
-                "\n",
-                Date0FileName, " : ", SourceFileName, "\n",
-                "\t$(MCPI) $(ALL_GRADEFLAGS) ",
-                    "$(ALL_MCPIFLAGS) ", ModuleArg, "\n",
-                DateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCI) $(ALL_GRADEFLAGS) $(ALL_MCIFLAGS) ",
-                    ModuleArg, "\n",
-                Date3FileName, " : ", SourceFileName, "\n",
-                "\t$(MCSI) $(ALL_GRADEFLAGS) $(ALL_MCSIFLAGS) ",
-                    ModuleArg, "\n",
-                OptDateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCOI) $(ALL_GRADEFLAGS) $(ALL_MCOIFLAGS) ",
-                    ModuleArg, "\n",
-                TransOptDateFileName, " : ", SourceFileName,
-                    "\n",
-                "\t$(MCTOI) $(ALL_GRADEFLAGS) ",
-                    "$(ALL_MCTOIFLAGS) ", ModuleArg, "\n",
-                CDateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
-                    ModuleArg, " $(ERR_REDIRECT)\n",
-                "ifeq ($(TARGET_ASM),yes)\n",
-                AsmDateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
-                    "--target-code-only ", ModuleArg,
-                    " $(ERR_REDIRECT)\n",
-                PicAsmDateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
-                    "--target-code-only --pic ",
-                    "\\\n",
-                "\t\t--cflags ""$(GCCFLAGS_FOR_PIC)"" ",
-                    ModuleArg, " $(ERR_REDIRECT)\n",
-                "endif # TARGET_ASM\n",
-                ILDateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
-                    "--il-only ", ModuleArg,
-                    " $(ERR_REDIRECT)\n",
-                JavaDateFileName, " : ", SourceFileName, "\n",
-                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
-                    "--java-only ", ModuleArg,
-                    " $(ERR_REDIRECT)\n"
-            ], !IO)
-        ;
-            true
-        ),
-
-        io.close_output(DepStream, !IO),
-        io.rename_file(TmpDependencyFileName, DependencyFileName, Result3,
-            !IO),
-        (
-            Result3 = error(_),
-            % On some systems, we need to remove the existing file
-            % first, if any.  So try again that way.
-            io.remove_file(DependencyFileName, Result4, !IO),
-            (
-                Result4 = error(Error4),
-                maybe_write_string(Verbose, " failed.\n", !IO),
-                maybe_flush_output(Verbose, !IO),
-                io.error_message(Error4, ErrorMsg),
-                string.append_list(["can't remove file `", DependencyFileName,
-                    "': ", ErrorMsg], Message),
-                report_error(Message, !IO)
-            ;
-                Result4 = ok,
-                io.rename_file(TmpDependencyFileName, DependencyFileName,
-                    Result5, !IO),
-                (
-                    Result5 = error(Error5),
-                    maybe_write_string(Verbose, " failed.\n", !IO),
-                    maybe_flush_output(Verbose, !IO),
-                    io.error_message(Error5, ErrorMsg),
-                    string.append_list(["can't rename file `",
-                        TmpDependencyFileName, "' as `", DependencyFileName,
-                        "': ", ErrorMsg], Message),
-                    report_error(Message, !IO)
-                ;
-                    Result5 = ok,
-                    maybe_write_string(Verbose, " done.\n", !IO)
-                )
-            )
-        ;
-            Result3 = ok,
-            maybe_write_string(Verbose, " done.\n", !IO)
-        )
-    ).
-
-    % Generate the following dependency.  This dependency is
-    % needed because module__cpp_code.dll might refer to
-    % high level data in any of the mercury modules it
-    % imports plus itself.
-    % We also generate a dependency on the .il file, so that mmake
-    % knows we need to generate the .il file to get the foreign language
-    % source file (e.g. .cpp file).
-    %
-    % For example, for MC++ we generate:
-    %
-    %   <module>__cpp_code.dll : <module>.dll <imports>.dll
-    %   <module>__cpp_code.cpp : <module>.il
-    %
-    % (the rule to generate .dll from .cpp is a pattern rule in
-    % scripts/Mmake.rules).
-    %
-:- pred write_foreign_dependency_for_il(io.output_stream::in,sym_name::in,
-    list(module_name)::in, foreign_import_module_info_list::in,
-    foreign_language::in, io::di, io::uo) is det.
-
-write_foreign_dependency_for_il(DepStream, ModuleName, AllDeps,
-        ForeignImports, ForeignLang, !IO) :-
-    (
-        ForeignModuleName = foreign_language_module_name(ModuleName,
-            ForeignLang),
-        ForeignExt = foreign_language_file_extension(ForeignLang)
-    ->
-        module_name_to_make_var_name(ForeignModuleName,
-            ForeignModuleNameString),
-        module_name_to_file_name(ForeignModuleName, ForeignExt, no,
-            ForeignFileName, !IO),
-        module_name_to_file_name(ModuleName, ".il", no, IlFileName, !IO),
-        module_name_to_file_name(ModuleName, ".dll", no, DllFileName, !IO),
-        module_name_to_file_name(ForeignModuleName, ".dll", no,
-            ForeignDllFileName, !IO),
-
-        io.write_strings(DepStream, [
-            ForeignDllFileName, " : ", DllFileName], !IO),
-            % XXX This change doesn't work correctly because
-            % mmake can't find the dlls which don't reside
-            % in the current directory.
-        % write_dll_dependencies_list(ModuleName, AllDeps, DepStream,
-        %   !IO),
-        io.nl(DepStream, !IO),
-
-        io.write_strings(DepStream, [
-            ForeignFileName, " : ", IlFileName, "\n\n"], !IO),
-
-        (
-            ForeignLang = lang_csharp,
-            % Store in the variable CSHARP_ASSEMBLY_REFS-foreign_code_name
-            % the command line argument to reference all the dlls the
-            % foreign code module references.
-            io.write_strings(DepStream,
-                ["CSHARP_ASSEMBLY_REFS-", ForeignModuleNameString, "="], !IO),
-            (
-                mercury_std_library_module_name(ModuleName)
-            ->
-                Prefix = "/addmodule:"
-            ;
-                Prefix = "/r:"
-            ),
-            ForeignDeps = list.map(
-                (func(M) = foreign_import_module_name_from_module(M,
-                    ModuleName)),
-                ForeignImports),
-            Deps = AllDeps ++ ForeignDeps,
-            write_dll_dependencies_list(referenced_dlls(ModuleName, Deps),
-                Prefix, DepStream, !IO),
-            io.nl(DepStream, !IO)
-        ;
-            ( ForeignLang = lang_c
-            ; ForeignLang = lang_java
-            ; ForeignLang = lang_il
-            ; ForeignLang = lang_erlang
-            )
-        )
-    ;
-        % This foreign language doesn't generate an external file
-        % so there are no dependencies to generate.
-        true
-    ).
-
-    % With `--use-subdirs', allow users to type `mmake module.c'
-    % rather than `mmake Mercury/cs/module.c'.
-    %
-:- pred write_subdirs_shorthand_rule(io.output_stream::in,
-    module_name::in, string::in, io::di, io::uo) is det.
-
-write_subdirs_shorthand_rule(DepStream, ModuleName, Ext, !IO) :-
-    module_name_to_file_name(ModuleName, ModuleStr),
-    module_name_to_file_name(ModuleName, Ext, no, Target, !IO),
-    ShorthandTarget = ModuleStr ++ Ext,
-    io.write_string(DepStream, ".PHONY: ", !IO),
-    io.write_string(DepStream, ShorthandTarget, !IO),
-    io.nl(DepStream, !IO),
-    io.write_string(DepStream, ShorthandTarget, !IO),
-    io.write_string(DepStream, ": ", !IO),
-    io.write_string(DepStream, Target, !IO),
-    io.nl(DepStream, !IO).
-
 maybe_read_dependency_file(ModuleName, MaybeTransOptDeps, !IO) :-
     globals.io_lookup_bool_option(transitive_optimization, TransOpt, !IO),
     (
         TransOpt = yes,
         globals.io_lookup_bool_option(verbose, Verbose, !IO),
-        module_name_to_file_name(ModuleName, ".d", no, DependencyFileName,
-            !IO),
+        module_name_to_file_name(ModuleName, ".d", do_not_create_dirs,
+            DependencyFileName, !IO),
         maybe_write_string(Verbose, "% Reading auto-dependency file `", !IO),
         maybe_write_string(Verbose, DependencyFileName, !IO),
         maybe_write_string(Verbose, "'...", !IO),
@@ -4095,7 +2012,7 @@
             OpenResult = ok(Stream),
             io.set_input_stream(Stream, OldStream, !IO),
             module_name_to_file_name(ModuleName, ".trans_opt_date",
-                no, TransOptDateFileName0, !IO),
+                do_not_create_dirs, TransOptDateFileName0, !IO),
             string.to_char_list(TransOptDateFileName0,
                 TransOptDateFileName),
             list.append(TransOptDateFileName, [' ', ':'], SearchPattern),
@@ -4181,147 +2098,36 @@
         TransOptDeps = []
     ).
 
-    % get_both_opt_deps(Deps, Directories, OptDeps, TransOptDeps):
-    %
-    % For each dependency, search intermod_directories for a .m file.
-    % If it exists, add it to both output lists. Otherwise, if a .opt
-    % file exists, add it to the OptDeps list, and if a .trans_opt
-    % file exists, add it to the TransOptDeps list.
-    % If --use-opt-files is set, don't look for `.m' files, since
-    % we are not building `.opt' files, only using those which
-    % are available.
-    % XXX This won't find nested sub-modules.
-    % XXX Use `mmc --make' if that matters.
-    %
-:- pred get_both_opt_deps(bool::in, list(module_name)::in, list(string)::in,
-    list(module_name)::out, list(module_name)::out, io::di, io::uo) is det.
-
-get_both_opt_deps(_, [], _, [], [], !IO).
-get_both_opt_deps(BuildOptFiles, [Dep | Deps], IntermodDirs,
-        !:OptDeps, !:TransOptDeps, !IO) :-
-    get_both_opt_deps(BuildOptFiles, Deps, IntermodDirs,
-        !:OptDeps, !:TransOptDeps, !IO),
-    (
-        BuildOptFiles = yes,
-        search_for_module_source(IntermodDirs, IntermodDirs,
-            Dep, Result1, !IO),
-        (
-            Result1 = ok(_),
-            !:OptDeps = [Dep | !.OptDeps],
-            !:TransOptDeps = [Dep | !.TransOptDeps],
-            io.seen(!IO),
-            Found = yes
-        ;
-            Result1 = error(_),
-            Found = no
-        )
-    ;
-        BuildOptFiles = no,
-        Found = no
-    ),
-    (
-        Found = no,
-        module_name_to_file_name(Dep, ".opt", no, OptName, !IO),
-        search_for_file(IntermodDirs, OptName, Result2, !IO),
-        (
-            Result2 = ok(_),
-            !:OptDeps = [Dep | !.OptDeps],
-            io.seen(!IO)
-        ;
-            Result2 = error(_)
-        ),
-        module_name_to_file_name(Dep, ".trans_opt", no, TransOptName, !IO),
-        search_for_file(IntermodDirs, TransOptName, Result3, !IO),
-        (
-            Result3 = ok(_),
-            !:TransOptDeps = [Dep | !.TransOptDeps],
-            io.seen(!IO)
-        ;
-            Result3 = error(_)
-        )
-    ;
-        Found = yes
-    ).
-
-    % For each dependency, search intermod_directories for a .Suffix
-    % file or a .m file, filtering out those for which the search fails.
-    % If --use-opt-files is set, only look for `.opt' files,
-    % not `.m' files.
-    % XXX This won't find nested sub-modules.
-    % XXX Use `mmc --make' if that matters.
-:- pred get_opt_deps(bool::in, list(module_name)::in, list(string)::in,
-    string::in, list(module_name)::out, io::di, io::uo) is det.
-
-get_opt_deps(_, [], _, _, [], !IO).
-get_opt_deps(BuildOptFiles, [Dep | Deps], IntermodDirs, Suffix, !:OptDeps,
-        !IO) :-
-    get_opt_deps(BuildOptFiles, Deps, IntermodDirs, Suffix, !:OptDeps, !IO),
-    (
-        BuildOptFiles = yes,
-        search_for_module_source(IntermodDirs, IntermodDirs,
-            Dep, Result1, !IO),
-        (
-            Result1 = ok(_),
-            !:OptDeps = [Dep | !.OptDeps],
-            Found = yes,
-            io.seen(!IO)
-        ;
-            Result1 = error(_),
-            Found = no
-        )
-    ;
-        BuildOptFiles = no,
-        Found = no
-    ),
-    (
-        Found = no,
-        module_name_to_search_file_name(Dep, Suffix, OptName, !IO),
-        search_for_file(IntermodDirs, OptName, Result2, !IO),
-        (
-            Result2 = ok(_),
-            !:OptDeps = [Dep | !.OptDeps],
-            io.seen(!IO)
-        ;
-            Result2 = error(_)
-        )
-    ;
-        Found = yes
-    ).
-
 %-----------------------------------------------------------------------------%
 
 generate_module_dependencies(ModuleName, !IO) :-
     map.init(DepsMap),
-    SearchIncludePath = no,
-    generate_dependencies(output_all_dependencies,
-        SearchIncludePath, ModuleName, DepsMap, !IO).
+    generate_dependencies(output_all_dependencies, do_not_search, ModuleName,
+        DepsMap, !IO).
 
 generate_file_dependencies(FileName, !IO) :-
     build_deps_map(FileName, ModuleName, DepsMap, !IO),
-    SearchIncludePath = no,
-    generate_dependencies(output_all_dependencies,
-        SearchIncludePath, ModuleName, DepsMap, !IO).
+    generate_dependencies(output_all_dependencies, do_not_search, ModuleName,
+        DepsMap, !IO).
 
 generate_module_dependency_file(ModuleName, !IO) :-
     map.init(DepsMap),
-    SearchIncludePath = yes,
-    generate_dependencies(output_d_file_only,
-        SearchIncludePath, ModuleName, DepsMap, !IO).
+    generate_dependencies(output_d_file_only, do_search, ModuleName,
+        DepsMap, !IO).
 
 generate_file_dependency_file(FileName, !IO) :-
     build_deps_map(FileName, ModuleName, DepsMap, !IO),
-    SearchIncludePath = yes,
-    generate_dependencies(output_d_file_only,
-        SearchIncludePath, ModuleName, DepsMap, !IO).
+    generate_dependencies(output_d_file_only, do_search, ModuleName,
+        DepsMap, !IO).
 
 :- pred build_deps_map(file_name::in, module_name::out, deps_map::out,
     io::di, io::uo) is det.
 
 build_deps_map(FileName, ModuleName, DepsMap, !IO) :-
-    % read in the top-level file (to figure out its module name)
-    read_mod_from_file(FileName, ".m", "Reading file", no, no, Items, Error,
-        ModuleName, _, !IO),
-    string.append(FileName, ".m", SourceFileName),
+    % Read in the top-level file (to figure out its module name).
+    read_module_from_file(FileName, ".m", "Reading file", do_not_search,
+        do_not_return_timestamp, Items, Error, ModuleName, _, !IO),
+    SourceFileName = FileName ++ ".m",
     split_into_submodules(ModuleName, Items, SubModuleList, [], Specs),
     globals.io_get_globals(Globals, !IO),
     write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO),
@@ -4335,18 +2141,15 @@
     --->    output_d_file_only
     ;       output_all_dependencies.
 
-:- pred generate_dependencies(generate_dependencies_mode::in, bool::in,
-    module_name::in, deps_map::in,
-    io::di, io::uo) is det.
+:- pred generate_dependencies(generate_dependencies_mode::in, maybe_search::in,
+    module_name::in, deps_map::in, io::di, io::uo) is det.
 
 generate_dependencies(Mode, Search, ModuleName, DepsMap0, !IO) :-
     % First, build up a map of the dependencies.
-    generate_deps_map(set.make_singleton_set(ModuleName), Search,
-        DepsMap0, DepsMap, !IO),
+    generate_deps_map(ModuleName, Search, DepsMap0, DepsMap, !IO),
 
-    %
     % Check whether we could read the main `.m' file.
-    %
+
     map.lookup(DepsMap, ModuleName, ModuleDep),
     ModuleDep = deps(_, ModuleImports),
     module_imports_get_error(ModuleImports, Error),
@@ -4357,8 +2160,7 @@
         report_error(Message, !IO)
     ;
         (
-            Mode = output_d_file_only,
-            true
+            Mode = output_d_file_only
         ;
             Mode = output_all_dependencies,
             module_imports_get_source_file_name(ModuleImports, SourceFileName),
@@ -4368,10 +2170,9 @@
                 DepsMap, !IO)
         ),
 
-        %
         % Compute the interface deps graph and the implementation deps
         % graph from the deps map.
-        %
+
         digraph.init(IntDepsGraph0),
         digraph.init(ImplDepsGraph0),
         map.values(DepsMap, DepsList),
@@ -4380,12 +2181,11 @@
         maybe_output_imports_graph(ModuleName, IntDepsGraph, ImplDepsGraph,
             !IO),
 
-        %
         % Compute the trans-opt deps ordering, by doing an approximate
         % topological sort of the implementation deps, and then finding
         % the subset of those for which of those we have (or can make)
         % trans-opt files.
-        %
+
         digraph.atsort(ImplDepsGraph, ImplDepsOrdering0),
         maybe_output_module_order(ModuleName, ImplDepsOrdering0, !IO),
         list.map(set.to_sorted_list, ImplDepsOrdering0, ImplDepsOrdering),
@@ -4395,21 +2195,23 @@
         get_opt_deps(yes, TransOptDepsOrdering0, IntermodDirs, ".trans_opt",
             TransOptDepsOrdering, !IO),
 
-        % digraph.to_assoc_list(ImplDepsGraph, ImplDepsAL),
-        % print("ImplDepsAL:\n", !IO),
-        % write_list(ImplDepsAL, "\n", print, !IO), nl(!IO),
+        trace [compiletime(flag("deps_graph")), runtime(env("DEPS_GRAPH")),
+                io(!IO)]
+        (
+            digraph.to_assoc_list(ImplDepsGraph, ImplDepsAL),
+            print("ImplDepsAL:\n", !IO),
+            write_list(ImplDepsAL, "\n", print, !IO), nl(!IO)
+        ),
 
-        %
         % Compute the indirect dependencies: they are equal to the composition
         % of the implementation dependencies with the transitive closure of the
         % implementation dependencies.  (We used to take the transitive closure
         % of the interface dependencies, but we now include implementation
         % details in the interface files).
-        %
+
         digraph.tc(ImplDepsGraph, TransImplDepsGraph),
         digraph.compose(ImplDepsGraph, TransImplDepsGraph, IndirectDepsGraph),
 
-        %
         % Compute the indirect optimization dependencies: indirect
         % dependencies including those via `.opt' or `.trans_opt' files.
         % Actually we can't compute that, since we don't know
@@ -4418,7 +2220,7 @@
         % and assume that the each module's `.opt' file might import any
         % of that module's implementation dependencies; in actual fact,
         % it will be some subset of that.
-        %
+
         digraph.tc(ImplDepsGraph, IndirectOptDepsGraph),
 
         (
@@ -4432,13 +2234,13 @@
             ImplDepsGraph, IndirectDepsGraph, IndirectOptDepsGraph,
             TransOptDepsOrdering, DepsMap, !IO)
     ),
-    %
+
     % For Java, the main target is actually a shell script which will
     % set CLASSPATH appropriately and invoke java on the appropriate
     % .class file.  Rather than generating an Mmake rule to build this
     % file when it is needed, we just generate this file "mmake depend"
     % time, since that is simpler and probably more efficient anyway.
-    %
+
     globals.io_get_target(Target, !IO),
     (
         Target = target_java,
@@ -4458,7 +2260,8 @@
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     (
         ImportsGraph = yes,
-        module_name_to_file_name(Module, ".imports_graph", yes, FileName, !IO),
+        module_name_to_file_name(Module, ".imports_graph", do_create_dirs,
+            FileName, !IO),
         maybe_write_string(Verbose, "% Creating imports graph file `", !IO),
         maybe_write_string(Verbose, FileName, !IO),
         maybe_write_string(Verbose, "'...", !IO),
@@ -4493,12 +2296,10 @@
 
 filter_imports_graph(A - B, DepsGraph) =
     (
-        %
         % Don't keep the edge if it points to a builtin-module or if the
         % relationship is between two standard library modules.
         % XXX it would be better to change this to be only keep those
         % edges for which the left-hand side is in the current directory.
-        %
         (
             any_mercury_builtin_module(B)
         ;
@@ -4554,7 +2355,8 @@
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     (
         Order = yes,
-        module_name_to_file_name(Module, ".order", yes, OrdFileName, !IO),
+        module_name_to_file_name(Module, ".order", do_create_dirs,
+            OrdFileName, !IO),
         maybe_write_string(Verbose, "% Creating module order file `", !IO),
         maybe_write_string(Verbose, OrdFileName, !IO),
         maybe_write_string(Verbose, "'...", !IO),
@@ -4585,6 +2387,7 @@
     set.to_sorted_list(SCC0, SCC),
     io.write_list(Stream, SCC, "\n", prog_out.write_sym_name, !IO).
 
+% ZZZ
     % generate_dependencies_write_d_files(Modules, IntDepsRel, ImplDepsRel,
     %   IndirectDepsRel, IndirectOptDepsRel, TransOptOrder, DepsMap, !IO):
     %
@@ -4611,11 +2414,10 @@
     some [!Module] (
         Dep = deps(_, !:Module),
 
-        %
         % Look up the interface/implementation/indirect dependencies
         % for this module from the respective dependency graphs,
         % and save them in the module_imports structure.
-        %
+
         module_imports_get_module_name(!.Module, ModuleName),
         get_dependencies_from_graph(IndirectOptDepsGraph, ModuleName,
             IndirectOptDeps),
@@ -4657,16 +2459,15 @@
         module_imports_set_impl_deps(ImplDeps, !Module),
         module_imports_set_indirect_deps(IndirectDeps, !Module),
 
-        %
         % Compute the trans-opt dependencies for this module. To avoid
         % the possibility of cycles, each module is only allowed to depend
         % on modules that occur later than it in the TransOptOrder.
-        %
+
         FindModule = (pred(OtherModule::in) is semidet :-
             ModuleName \= OtherModule
         ),
         list.takewhile(FindModule, TransOptOrder, _, TransOptDeps0),
-        ( TransOptDeps0 = [ _ | TransOptDeps1 ] ->
+        ( TransOptDeps0 = [_ | TransOptDeps1] ->
             % The module was found in the list.
             TransOptDeps = TransOptDeps1
         ;
@@ -4699,64 +2500,10 @@
             digraph.lookup_vertex(DepsGraph, Key, Dep)
         ), DepsKeysSet, [], Deps).
 
-% This is the data structure we use to record the dependencies.
-% We keep a map from module name to information about the module.
-
-:- type deps_map == map(module_name, deps).
-:- type deps
-    --->    deps(
-                bool,       % have we processed this module yet?
-                module_imports
-            ).
-
     % (Module1 -> Module2) means Module1 is imported by Module2.
 :- type deps_graph == digraph(module_name).
 :- type deps_graph_key == digraph_key(module_name).
 
-:- pred generate_deps_map(set(module_name)::in, bool::in,
-    deps_map::in, deps_map::out, io::di, io::uo) is det.
-
-generate_deps_map(!.Modules, Search, !DepsMap, !IO) :-
-    ( set.remove_least(!.Modules, Module, !:Modules) ->
-        % Look up the module's dependencies, and determine whether
-        % it has been processed yet.
-        lookup_dependencies(Module, Search, Done, !DepsMap, ModuleImports,
-            !IO),
-
-        % If the module hadn't been processed yet, then add its imports,
-        % parents, and public children to the list of dependencies we need
-        % to generate, and mark it as having been processed.
-        (
-            Done = no,
-            map.set(!.DepsMap, Module, deps(yes, ModuleImports), !:DepsMap),
-            ForeignImportedModules =
-                list.map(
-                    (func(foreign_import_module_info(_, ImportedModule, _))
-                        = ImportedModule),
-                    ModuleImports ^ foreign_import_modules),
-            list.condense(
-                [ModuleImports ^ parent_deps,
-                ModuleImports ^ int_deps,
-                ModuleImports ^ impl_deps,
-                ModuleImports ^ public_children, % a.k.a. incl_deps
-                ForeignImportedModules],
-                ModulesToAdd),
-            % We could keep a list of the modules we have already processed
-            % and subtract it from ModulesToAddSet here, but doing that
-            % actually leads to a small slowdown.
-            set.list_to_set(ModulesToAdd, ModulesToAddSet),
-            set.union(ModulesToAddSet, !Modules)
-        ;
-            Done = yes
-        ),
-        % Recursively process the remaining modules.
-        generate_deps_map(!.Modules, Search, !DepsMap, !IO)
-    ;
-        % If we can't remove the smallest, then the set of modules to be
-        % processed is empty.
-        true
-    ).
-
     % Construct a pair of dependency graphs (the interface dependencies
     % and the implementation dependencies) for all the modules in the program.
     %
@@ -4793,23 +2540,20 @@
 
 module_imports_to_deps_graph(ModuleImports, LookupModuleImports,
         !IntDepsGraph, !ImplDepsGraph) :-
-    %
     % Add interface dependencies to the interface deps graph.
     %
-    % Note that we need to do this both for the interface imports
-    % of this module and for the *implementation* imports of
-    % its ancestors.  This is because if this module is defined
-    % in the implementation section of its parent, then the
-    % interface of this module may depend on things
+    % Note that we need to do this both for the interface imports of this
+    % module and for the *implementation* imports of its ancestors.
+    % This is because if this module is defined in the implementation section
+    % of its parent, then the interface of this module may depend on things
     % imported only by its parent's implementation.
     %
-    % If this module was actually defined in the interface
-    % section of one of its ancestors, then it should only
-    % depend on the interface imports of that ancestor,
-    % so the dependencies added here are in fact more
-    % conservative than they need to be in that case.
-    % However, that should not be a major problem.
-    %
+    % If this module was actually defined in the interface section of one
+    % of its ancestors, then it should only depend on the interface imports
+    % of that ancestor, so the dependencies added here are in fact more
+    % conservative than they need to be in that case. However, that should
+    % not be a major problem.
+
     ModuleName = ModuleImports ^ module_name,
     ParentDeps = ModuleImports ^ parent_deps,
     digraph.add_vertex(ModuleName, IntModuleKey, !IntDepsGraph),
@@ -4817,16 +2561,14 @@
     add_parent_impl_deps_list(LookupModuleImports, IntModuleKey, ParentDeps,
         !IntDepsGraph),
 
-    %
     % Add implementation dependencies to the impl. deps graph.
-    % (The implementation dependencies are a superset of the
-    % interface dependencies.)
-    %
-    % Note that we need to do this both for the imports
-    % of this module and for the imports of its parents,
-    % because this module may depend on things imported
-    % only by its parents.
+    % (The implementation dependencies are a superset of the interface
+    % dependencies.)
     %
+    % Note that we need to do this both for the imports of this module
+    % and for the imports of its parents, because this module may depend on
+    % things imported only by its parents.
+
     digraph.add_vertex(ModuleName, ImplModuleKey, !ImplDepsGraph),
     add_impl_deps(ImplModuleKey, ModuleImports, !ImplDepsGraph),
     add_parent_impl_deps_list(LookupModuleImports, ImplModuleKey, ParentDeps,
@@ -4867,2013 +2609,56 @@
     ParentModuleImports = LookupModuleImports(Parent),
     add_impl_deps(ModuleKey, ParentModuleImports, !DepsGraph).
 
-:- pred add_parent_impl_deps_list(lookup_module_imports::lookup_module_imports,
-    deps_graph_key::in, list(module_name)::in, deps_graph::in, deps_graph::out)
-    is det.
-
-add_parent_impl_deps_list(LookupModuleImports, ModuleKey, Parents,
-        !DepsGraph) :-
-    list.foldl(add_parent_impl_deps(LookupModuleImports, ModuleKey), Parents,
-        !DepsGraph).
-
-    % Add a single dependency to a graph.
-    %
-:- pred add_dep(digraph_key(T)::in, T::in, digraph(T)::in, digraph(T)::out)
-    is det.
-
-add_dep(ModuleKey, Dep, !DepsGraph) :-
-    digraph.add_vertex(Dep, DepKey, !DepsGraph),
-    digraph.add_edge(ModuleKey, DepKey, !DepsGraph).
-
-:- type submodule_kind
-    --->    toplevel
-    ;       nested_submodule
-    ;       separate_submodule.
-
-    % Check if a module is a top-level module, a nested sub-module,
-    % or a separate sub-module.
-    %
-:- func get_submodule_kind(module_name, deps_map) = submodule_kind.
-
-get_submodule_kind(ModuleName, DepsMap) = Kind :-
-    Ancestors = get_ancestors(ModuleName),
-    ( list.last(Ancestors, Parent) ->
-        map.lookup(DepsMap, ModuleName, deps(_, ModuleImports)),
-        map.lookup(DepsMap, Parent, deps(_, ParentImports)),
-        ModuleFileName = ModuleImports ^ source_file_name,
-        ParentFileName = ParentImports ^ source_file_name,
-        ( ModuleFileName = ParentFileName ->
-            Kind = nested_submodule
-        ;
-            Kind = separate_submodule
-        )
-    ;
-        Kind = toplevel
-    ).
-
-%-----------------------------------------------------------------------------%
-
-    % Write out the `.dv' file, using the information collected in the
-    % deps_map data structure.
-    %
-:- pred generate_dependencies_write_dv_file(file_name::in, module_name::in,
-    deps_map::in, io::di, io::uo) is det.
-
-generate_dependencies_write_dv_file(SourceFileName, ModuleName, DepsMap,
-        !IO) :-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    module_name_to_file_name(ModuleName, ".dv", yes, DvFileName, !IO),
-    maybe_write_string(Verbose, "% Creating auto-dependency file `", !IO),
-    maybe_write_string(Verbose, DvFileName, !IO),
-    maybe_write_string(Verbose, "'...\n", !IO),
-    io.open_output(DvFileName, DvResult, !IO),
-    (
-        DvResult = ok(DvStream),
-        generate_dv_file(SourceFileName, ModuleName, DepsMap, DvStream, !IO),
-        io.close_output(DvStream, !IO),
-        maybe_write_string(Verbose, "% done.\n", !IO)
-    ;
-        DvResult = error(IOError),
-        maybe_write_string(Verbose, " failed.\n", !IO),
-        maybe_flush_output(Verbose, !IO),
-        io.error_message(IOError, IOErrorMessage),
-        string.append_list(["error opening file `", DvFileName,
-            "' for output: ", IOErrorMessage], DvMessage),
-        report_error(DvMessage, !IO)
-    ).
-
-    % Write out the `.dep' file, using the information collected in the
-    % deps_map data structure.
-    %
-:- pred generate_dependencies_write_dep_file(file_name::in, module_name::in,
-    deps_map::in, io::di, io::uo) is det.
-
-generate_dependencies_write_dep_file(SourceFileName, ModuleName, DepsMap,
-        !IO) :-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    module_name_to_file_name(ModuleName, ".dep", yes, DepFileName, !IO),
-    maybe_write_string(Verbose, "% Creating auto-dependency file `", !IO),
-    maybe_write_string(Verbose, DepFileName, !IO),
-    maybe_write_string(Verbose, "'...\n", !IO),
-    io.open_output(DepFileName, DepResult, !IO),
-    (
-        DepResult = ok(DepStream),
-        generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO),
-        io.close_output(DepStream, !IO),
-        maybe_write_string(Verbose, "% done.\n", !IO)
-    ;
-        DepResult = error(IOError),
-        maybe_write_string(Verbose, " failed.\n", !IO),
-        maybe_flush_output(Verbose, !IO),
-        io.error_message(IOError, IOErrorMessage),
-        string.append_list(["error opening file `", DepFileName,
-            "' for output: ", IOErrorMessage], DepMessage),
-        report_error(DepMessage, !IO)
-    ).
-
-:- pred compare_module_names(module_name::in, module_name::in,
-    comparison_result::out) is det.
-
-compare_module_names(Sym1, Sym2, Result) :-
-    Str1 = sym_name_to_string(Sym1),
-    Str2 = sym_name_to_string(Sym2),
-    compare(Result, Str1, Str2).
-
-:- pred generate_dv_file(file_name::in, module_name::in, deps_map::in,
-    io.output_stream::in, io::di, io::uo) is det.
-
-generate_dv_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO) :-
-    io.write_string(DepStream,
-        "# Automatically generated dependency variables for module `", !IO),
-    ModuleNameString = sym_name_to_string(ModuleName),
-    io.write_string(DepStream, ModuleNameString, !IO),
-    io.write_string(DepStream, "'\n", !IO),
-    io.write_string(DepStream, "# generated from source file `", !IO),
-    io.write_string(DepStream, SourceFileName, !IO),
-    io.write_string(DepStream, "'\n", !IO),
-
-    library.version(Version),
-    io.write_string(DepStream,
-        "# Generated by the Mercury compiler, version ", !IO),
-    io.write_string(DepStream, Version, !IO),
-    io.write_string(DepStream, ".\n\n", !IO),
-
-    map.keys(DepsMap, Modules0),
-    select_ok_modules(Modules0, DepsMap, Modules1),
-    list.sort(compare_module_names, Modules1, Modules),
-
-    module_name_to_make_var_name(ModuleName, MakeVarName),
-    list.map(get_source_file(DepsMap), Modules, SourceFiles0),
-    list.sort_and_remove_dups(SourceFiles0, SourceFiles),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".ms =", !IO),
-    write_file_dependencies_list(SourceFiles, ".m", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".errs =", !IO),
-    write_file_dependencies_list(SourceFiles, ".err", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".mods =", !IO),
-    write_dependencies_list(Modules, "", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    % The modules for which we need to generate .int0 files.
-    ModulesWithSubModules = list.filter(
-      (pred(Module::in) is semidet :-
-          map.lookup(DepsMap, Module, deps(_, ModuleImports)),
-          ModuleImports ^ children = [_ | _]
-      ), Modules),
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".parent_mods =", !IO),
-    write_dependencies_list(ModulesWithSubModules, "", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    globals.io_get_target(Target, !IO),
-    (
-        Target = target_il,
-        ForeignModulesAndExts = foreign_modules(Modules, DepsMap)
-    ;
-        ( Target = target_c
-        ; Target = target_java
-        ; Target = target_asm
-        ; Target = target_x86_64
-        ; Target = target_erlang
-        ),
-        ForeignModulesAndExts = []
-    ),
-    ForeignModules = assoc_list.keys(ForeignModulesAndExts),
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".foreign =", !IO),
-    write_dependencies_list(ForeignModules, "", DepStream, !IO),
-    io.write_string(DepStream, "\n\n", !IO),
-
-    globals.io_lookup_bool_option(assume_gmake, Gmake, !IO),
-    (
-        Gmake = yes,
-        string.append(MakeVarName, ".mods", ModsVarName),
-        Basis = yes(ModsVarName - ""),
-
-        string.append(MakeVarName, ".foreign", ForeignVarName),
-        ForeignBasis = yes(ForeignVarName - ""),
-
-        string.append(MakeVarName, ".parent_mods", ParentModsVarName),
-        ParentBasis = yes(ParentModsVarName - "")
-    ;
-        Gmake = no,
-        Basis = no,
-        ForeignBasis = no,
-        ParentBasis = no
-    ),
-
-    get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs),
-
-    MakeFileName = (pred(M - E::in, F::out, IO0::di, IO::uo) is det :-
-        module_name_to_file_name(M, E, yes, F0, IO0, IO),
-        F = "$(os_subdir)" ++ F0
-    ),
-
-    list.map_foldl(MakeFileName, ForeignModulesAndExts, ForeignFileNames,
-        !IO),
-
-    % .foreign_cs are the source files which have had foreign code placed
-    % in them.
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".foreign_cs = ", !IO),
-    write_file_dependencies_list(ForeignFileNames, "", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    % The dlls that contain the foreign_code.
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".foreign_dlls = ", !IO),
-    write_compact_dependencies_list(ForeignModules, "$(dlls_subdir)",
-        ".dll", ForeignBasis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".init_cs = ", !IO),
-    write_compact_dependencies_list(Modules, "$(cs_subdir)", ".c",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".cs = $(", !IO),
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".init_cs) ", !IO),
-    write_extra_link_dependencies_list(ExtraLinkObjs, ".c", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".dlls = ", !IO),
-    write_compact_dependencies_list(Modules, "$(dlls_subdir)", ".dll",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_ss = ", !IO),
-    write_compact_dependencies_list(Modules, "$(ss_subdir)", ".s",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_pic_ss = ", !IO),
-    write_compact_dependencies_list(Modules, "$(pic_ss_subdir)", ".pic_s",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_s_dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(s_dates_subdir)",
-        ".s_date", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_pic_s_dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(pic_s_dates_subdir)",
-        ".pic_s_date", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_os = ", !IO),
-    write_compact_dependencies_list(Modules, "$(os_subdir)", ".$O",
-        Basis, DepStream, !IO),
-    write_extra_link_dependencies_list(ExtraLinkObjs, ".$O", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_pic_os = ", !IO),
-    write_compact_dependencies_list(Modules, "$(os_subdir)",
-        ".$(EXT_FOR_PIC_OBJECTS)", Basis, DepStream, !IO),
-    write_extra_link_dependencies_list(ExtraLinkObjs,
-        ".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    IsNested = (pred(Mod::in) is semidet :-
-        get_submodule_kind(Mod, DepsMap) = nested_submodule
-    ),
-    (
-        % For --target asm, we only generate separate object files
-        % for top-level modules and separate sub-modules, not for
-        % nested sub-modules.
-        Target = target_asm,
-        list.filter(IsNested, Modules, NestedModules, MainModules),
-        NestedModules = [_ | _]
-    ->
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".ss = ", !IO),
-        write_dependencies_list(MainModules, ".s", DepStream, !IO),
-        io.write_string(DepStream, "\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".pic_ss = ", !IO),
-        write_dependencies_list(MainModules, ".pic_s", DepStream, !IO),
-        io.write_string(DepStream, "\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".s_dates = ", !IO),
-        write_dependencies_list(MainModules, ".s_date", DepStream, !IO),
-        io.write_string(DepStream, "\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".pic_s_dates = ", !IO),
-        write_dependencies_list(MainModules, ".pic_s_date", DepStream, !IO),
-        io.write_string(DepStream, "\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".os = ", !IO),
-        write_dependencies_list(MainModules, ".$O", DepStream, !IO),
-        write_extra_link_dependencies_list(ExtraLinkObjs, ".$O", DepStream,
-            !IO),
-        io.write_string(DepStream, "\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".pic_os = ", !IO),
-        write_dependencies_list(MainModules, ".$(EXT_FOR_PIC_OBJECTS)",
-            DepStream, !IO),
-        write_extra_link_dependencies_list(ExtraLinkObjs,
-            ".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
-        io.write_string(DepStream, "\n", !IO)
-    ;
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".ss = $(", !IO),
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".all_ss)\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".pic_ss = $(", !IO),
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".all_pic_ss)\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".s_dates = $(", !IO),
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".all_s_dates)\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".pic_s_dates = $(", !IO),
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".all_pic_s_dates)\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".os = $(", !IO),
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".all_os)\n", !IO),
-
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".pic_os = $(", !IO),
-        io.write_string(DepStream, MakeVarName, !IO),
-        io.write_string(DepStream, ".all_pic_os)\n", !IO)
-    ),
-
-    %
-    % $(foo.cs_or_ss) contains the names of the generated intermediate
-    % files between `.m' and `.o' files. This is used in foo.dep
-    % to make sure the intermediate files are generated before the
-    % object files, so that errors are reported as soon as possible.
-    %
-    % If TARGET_ASM=yes, we define $(foo.cs_or_ss) to be $(foo.ss),
-    % otherwise it is defined to be $(foo.cs).
-    %
-    io.write_strings(DepStream, [
-        "ifeq ($(TARGET_ASM),yes)\n",
-        MakeVarName, ".cs_or_ss =$(", MakeVarName, ".ss)\n",
-        "else\n",
-        MakeVarName, ".cs_or_ss =$(", MakeVarName, ".cs)\n",
-        "endif\n\n"
-    ], !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".useds = ", !IO),
-    write_compact_dependencies_list(Modules, "$(useds_subdir)", ".used",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".ils = ", !IO),
-    write_compact_dependencies_list(Modules, "$(ils_subdir)", ".il",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".javas = ", !IO),
-    write_compact_dependencies_list(Modules, "$(javas_subdir)", ".java",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".classes = ", !IO),
-    write_compact_dependencies_list(Modules, "$(classes_subdir)", ".class",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, " ", !IO),
-    % The Java compiler creates a .class file for each class
-    % within the original .java file.  The filenames of all
-    % these can be matched with `module\$*.class', hence the
-    % "\\$$*.class" below.
-    % If no such files exist, Make will use the pattern verbatim,
-    % so we enclose the pattern in a `wildcard' function to prevent this.
-    % XXX This relies on GNU Make.
-    io.write_string(DepStream, "$(wildcard ", !IO),
-    write_compact_dependencies_list(Modules, "$(classes_subdir)",
-        "\\$$*.class", Basis, DepStream, !IO),
-    io.write_string(DepStream, ")\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".dirs = ", !IO),
-    write_compact_dependencies_list(Modules, "$(dirs_subdir)", ".dir",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".dir_os = ", !IO),
-    write_compact_dependencies_list(Modules, "$(dirs_subdir)", ".dir/*.$O",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(dates_subdir)", ".date",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".date0s = ", !IO),
-    write_compact_dependencies_list(Modules, "$(date0s_subdir)", ".date0",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".date3s = ", !IO),
-    write_compact_dependencies_list(Modules, "$(date3s_subdir)", ".date3",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".optdates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(optdates_subdir)",
-        ".optdate", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".trans_opt_dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(trans_opt_dates_subdir)",
-        ".trans_opt_date", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".c_dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(c_dates_subdir)",
-        ".c_date", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".il_dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(il_dates_subdir)",
-        ".il_date", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".java_dates = ", !IO),
-    write_compact_dependencies_list(Modules, "$(java_dates_subdir)",
-        ".java_date", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".ds = ", !IO),
-    write_compact_dependencies_list(Modules, "$(ds_subdir)", ".d",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".module_deps = ", !IO),
-    write_compact_dependencies_list(Modules, "$(module_deps_subdir)",
-        make_module_dep_file_extension, Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".mihs = ", !IO),
-    globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
-    (
-        HighLevelCode = yes,
-        (
-            ( Target = target_c
-            ; Target = target_asm
-            ),
-            % For the `--target c' MLDS back-end, we generate `.mih' files
-            % for every module.  Likewise for the `--target asm' back-end.
-            % (For the `--target asm' back-end, we previously used to do
-            % that only for modules that contain C code, but this caused
-            % trouble when trying to interoperate between compiled with
-            % `--target c' and code compiled with `--target asm', so now we
-            % generate them unconditionally.)
-            write_compact_dependencies_list(Modules,
-                "$(mihs_subdir)", ".mih", Basis, DepStream, !IO)
-        ;
-            % For the IL and Java targets, currently we don't generate
-            % `.mih' files at all; although perhaps we should...
-            ( Target = target_il
-            ; Target = target_java
-            ; Target = target_erlang
-            )
-        ;
-            Target = target_x86_64,
-            unexpected(this_file, "--highlevel-code with --target x86_64")
-        )
-    ;
-        % For the LLDS back-end, we don't use `.mih' files at all
-        HighLevelCode = no
-    ),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".mhs = ", !IO),
-    (
-        ( Target = target_c
-        ; Target = target_asm
-        ; Target = target_x86_64
-        ),
-        write_compact_dependencies_list(Modules, "", ".mh", Basis,
-            DepStream, !IO)
-    ;
-        ( Target = target_il
-        ; Target = target_java
-        ; Target = target_erlang
-        )
-    ),
-    io.write_string(DepStream, "\n", !IO),
-
-    % The `<module>.all_mihs' variable is like `<module>.mihs' except
-    % that it contains header files for all the modules, regardless
-    % of the grade or --target option.  It is used by the rule for
-    % `mmake realclean', which should remove anything that could have
-    % been automatically generated, even if the grade or --target option
-    % has changed.
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_mihs = ", !IO),
-    write_compact_dependencies_list(Modules, "$(mihs_subdir)", ".mih",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    % The `<module>.all_mhs' variable is like `<module>.mhs' except
-    % that it contains header files for all the modules, as for
-    % `<module>.all_mihs' above.
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_mhs = ", !IO),
-    write_compact_dependencies_list(Modules, "", ".mh", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".ints = ", !IO),
-    write_compact_dependencies_list(Modules, "$(ints_subdir)", ".int",
-        Basis, DepStream, !IO),
-    write_compact_dependencies_separator(Basis, DepStream, !IO),
-    write_compact_dependencies_list(Modules, "$(int2s_subdir)", ".int2",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    % `.int0' files are only generated for modules with sub-modules.
-    % XXX ... or at least they should be.  Currently we end up generating
-    % .int0 files for nested submodules that don't have any children.
-    % (We do the correct thing for separate sub-modules.)
-    %
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".int0s = ", !IO),
-    write_compact_dependencies_list(ModulesWithSubModules, "$(int0s_subdir)",
-         ".int0", ParentBasis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    % XXX The `<module>.all_int0s' variables is like `<module>.int0s' except
-    % that it contains .int0 files for all modules, regardless of whether
-    % they should have been created or not.  It is used by the rule for
-    % `mmake realclean' to ensure that we clean up all the .int0 files,
-    % including the ones that were accidently created by the bug described
-    % above.
-    %
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".all_int0s = ", !IO),
-    write_compact_dependencies_list(Modules, "$(int0s_subdir)", ".int0",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".int3s = ", !IO),
-    write_compact_dependencies_list(Modules, "$(int3s_subdir)", ".int3",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".opts = ", !IO),
-    write_compact_dependencies_list(Modules, "$(opts_subdir)", ".opt",
-        Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".trans_opts = ", !IO),
-    write_compact_dependencies_list(Modules, "$(trans_opts_subdir)",
-        ".trans_opt", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".analysiss = ", !IO),
-    write_compact_dependencies_list(Modules, "$(analysiss_subdir)",
-        ".analysis", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".requests = ", !IO),
-    write_compact_dependencies_list(Modules, "$(requests_subdir)",
-        ".request", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".imdgs = ", !IO),
-    write_compact_dependencies_list(Modules, "$(imdgs_subdir)",
-        ".imdg", Basis, DepStream, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    io.write_string(DepStream, MakeVarName, !IO),
-    io.write_string(DepStream, ".profs = ", !IO),
-    write_compact_dependencies_list(Modules, "", ".prof", Basis, DepStream,
-        !IO),
-    io.write_string(DepStream, "\n\n", !IO).
-
-:- pred generate_dep_file(file_name::in, module_name::in, deps_map::in,
-    io.output_stream::in, io::di, io::uo) is det.
-
-generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO) :-
-    io.write_string(DepStream,
-        "# Automatically generated dependencies for module `", !IO),
-    ModuleNameString = sym_name_to_string(ModuleName),
-    io.write_string(DepStream, ModuleNameString, !IO),
-    io.write_string(DepStream, "'\n", !IO),
-    io.write_string(DepStream,
-        "# generated from source file `", !IO),
-    io.write_string(DepStream, SourceFileName, !IO),
-    io.write_string(DepStream, "'\n", !IO),
-
-    library.version(Version),
-    io.write_string(DepStream,
-        "# Generated by the Mercury compiler, version ", !IO),
-    io.write_string(DepStream, Version, !IO),
-    io.write_string(DepStream, ".\n\n", !IO),
-
-    module_name_to_make_var_name(ModuleName, MakeVarName),
-
-    module_name_to_file_name(ModuleName, ".init", yes, InitFileName, !IO),
-    module_name_to_file_name(ModuleName, "_init.c", yes, InitCFileName, !IO),
-    module_name_to_file_name(ModuleName, "_init.s", no, InitAsmFileName, !IO),
-    module_name_to_file_name(ModuleName, "_init.$O", yes, InitObjFileName,
-        !IO),
-    module_name_to_file_name(ModuleName, "_init.pic_o", yes,
-        InitPicObjFileName, !IO),
-
-    % Note we have to do some ``interesting'' hacks to get
-    % `$(ALL_MLLIBS_DEP)' to work in the dependency list
-    % (and not complain about undefined variables).
-    % These hacks rely on features of GNU Make, so should not be used
-    % if we cannot assume we are using GNU Make.
-    globals.io_lookup_bool_option(assume_gmake, Gmake, !IO),
-    (
-        Gmake = yes,
-        append_list(["\\\n\t\t$(foreach @,", MakeVarName,
-            ",$(ALL_MLLIBS_DEP))"],
-            All_MLLibsDepString),
-        append_list(["\\\n\t\t$(foreach @,", MakeVarName,
-            ",$(ALL_MLOBJS))"],
-            All_MLObjsString),
-        append_list([
-        "\\\n\t\t$(patsubst %.o,%.$(EXT_FOR_PIC_OBJECTS),$(foreach @,",
-            MakeVarName, ",$(ALL_MLOBJS)))"],
-            All_MLPicObjsString)
-    ;
-        Gmake = no,
-        All_MLLibsDepString = "$(ALL_MLLIBS_DEP)",
-        All_MLObjsString = "$(ALL_MLOBJS)",
-        All_MLPicObjsString = "$(ALL_MLPICOBJS)"
-    ),
-
-    %
-    % When compiling to C, we want to include $(foo.cs) first in
-    % the dependency list, before $(foo.os).
-    % This is not strictly necessary, since the .$O files themselves depend
-    % on the .c files, but want to do it to ensure that Make will try to
-    % create all the C files first, thus detecting errors early,
-    % rather than first spending time compiling C files to .$O,
-    % which could be a waste of time if the program contains errors.
-    %
-    % When compiling to assembler, we want to do the same kind of
-    % thing, for the same reason, but with the `.s' files rather
-    % than the `.c' files.
-    %
-
-    module_name_to_file_name(ModuleName, "", no, ExeFileName, !IO),
-
-    IfIL = ["ifeq ($(findstring il,$(GRADE)),il)\n"],
-    ILMainRule = [ExeFileName, " : ", ExeFileName, ".exe\n",
-        ExeFileName, ".exe : ", "$(", MakeVarName, ".dlls) ",
-        "$(", MakeVarName, ".foreign_dlls)\n"],
-    Else = ["else\n"],
-    IfJava = [" ifeq ($(findstring java,$(GRADE)),java)\n"],
-    JavaMainRule = [ExeFileName, " : $(", MakeVarName, ".classes)\n"],
-    Else2 = [" else\n"],
-    EndIf2 = [" endif\n"],
-
-    % XXX the output here is GNU Make-specific
-    io.write_strings(DepStream, [
-        "ifneq ($(EXT_FOR_EXE),)\n",
-        ".PHONY : ", ExeFileName, "\n",
-        ExeFileName, " : ", ExeFileName, "$(EXT_FOR_EXE)\n",
-        "endif\n"
-    ], !IO),
-
-    MainRule =
-        [ExeFileName, "$(EXT_FOR_EXE) : $(", MakeVarName, ".cs_or_ss) ",
-            "$(", MakeVarName, ".os) ", InitObjFileName, " ",
-            All_MLObjsString, " ", All_MLLibsDepString, "\n",
-        "\t$(ML) $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) -- $(ALL_LDFLAGS) ",
-            "-o ", ExeFileName, "$(EXT_FOR_EXE) ", InitObjFileName, " \\\n",
-        "\t\t$(", MakeVarName, ".os) ", All_MLObjsString, " $(ALL_MLLIBS)\n"],
-    EndIf = ["endif\n"],
-
-    globals.io_get_target(Target, !IO),
-    (
-        Gmake = yes,
-        Rules = IfIL ++ ILMainRule ++ Else ++
-            IfJava ++ JavaMainRule ++ Else2 ++
-            MainRule ++ EndIf2 ++ EndIf
-    ;
-        Gmake = no,
-        (
-            Target = target_il,
-            Rules = ILMainRule
-        ;
-            Target = target_java,
-            Rules = JavaMainRule
-        ;
-            Target = target_erlang,
-            % XXX not yet
-            Rules = []
-        ;
-            ( Target = target_c
-            ; Target = target_asm
-            ; Target = target_x86_64    % XXX this is only provisional.
-            ),
-            Rules = MainRule
-        )
-    ),
-    io.write_strings(DepStream, Rules, !IO),
-
-    globals.io_lookup_bool_option(intermodule_optimization, Intermod, !IO),
-    (
-        Intermod = yes,
-        string.append_list(["$(", MakeVarName, ".opts) "], MaybeOptsVar)
-    ;
-        Intermod = no,
-        MaybeOptsVar = ""
-    ),
-    globals.io_lookup_bool_option(transitive_optimization, TransOpt, !IO),
-    (
-        TransOpt = yes,
-        string.append_list(["$(", MakeVarName, ".trans_opts) "],
-            MaybeTransOptsVar)
-    ;
-        TransOpt = no,
-        MaybeTransOptsVar = ""
-    ),
-    globals.io_lookup_bool_option(generate_mmc_make_module_dependencies,
-        MmcMakeDeps, !IO),
-    (
-        MmcMakeDeps = yes,
-        string.append_list(["$(", MakeVarName, ".module_deps) "],
-            MaybeModuleDepsVar)
-    ;
-        MmcMakeDeps = no,
-        MaybeModuleDepsVar = ""
-    ),
-
-    module_name_to_lib_file_name("lib", ModuleName, "", no, LibTargetName,
-        !IO),
-    module_name_to_lib_file_name("lib", ModuleName, ".$A", yes, LibFileName,
-        !IO),
-    module_name_to_lib_file_name("lib", ModuleName,
-        ".$(EXT_FOR_SHARED_LIB)", yes, SharedLibFileName, !IO),
-    module_name_to_lib_file_name("lib", ModuleName,
-        ".$(EXT_FOR_SHARED_LIB)", no, MaybeSharedLibFileName, !IO),
-    module_name_to_file_name(ModuleName, ".jar", no, JarFileName, !IO),
-
-    %
-    % Set up the installed name for shared libraries.
-    %
-    globals.io_lookup_bool_option(shlib_linker_use_install_name,
-        UseInstallName, !IO),
-    (
-        UseInstallName = yes,
-        get_install_name_option(SharedLibFileName, InstallNameOpt, !IO)
-    ;
-        UseInstallName = no,
-        InstallNameOpt = ""
-    ),
-
-    AllInts = [
-        "$(", MakeVarName, ".ints) ",
-        "$(", MakeVarName, ".int3s) ",
-        MaybeOptsVar, MaybeTransOptsVar,
-        InitFileName, "\n\n"
-    ],
-    ILLibRule = [
-        LibTargetName, " : ", "$(", MakeVarName, ".dlls) ",
-            "$(", MakeVarName, ".foreign_dlls) \\\n\t\t"
-        | AllInts
-    ],
-    JavaLibRule = [
-        LibTargetName, " : ", JarFileName, " \\\n\t\t"
-        | AllInts
-    ],
-    LibRule = [
-        LibTargetName, " : ", LibFileName, " ",
-        MaybeSharedLibFileName, " \\\n\t\t"
-        | AllInts
-    ],
-    (
-        Gmake = yes,
-        LibRules = IfIL ++ ILLibRule ++ Else ++
-            IfJava ++ JavaLibRule ++ Else2 ++
-            LibRule ++ EndIf2 ++ EndIf
-    ;
-        Gmake = no,
-        (
-            Target = target_il,
-            LibRules = ILLibRule
-        ;
-            Target = target_java,
-            LibRules = JavaLibRule
-        ;
-            Target = target_erlang,
-            % XXX not done yet
-            LibRules = []
-        ;
-            ( Target = target_c
-            ; Target = target_asm
-            ; Target = target_x86_64    % XXX This is only provisional.
-            ),
-            LibRules = LibRule
-        )
-    ),
-    io.write_strings(DepStream, [
-        ".PHONY : ", LibTargetName, "\n" |
-        LibRules
-    ], !IO),
-
-    io.write_strings(DepStream, [
-        "ifneq ($(EXT_FOR_SHARED_LIB),$A)\n",
-        SharedLibFileName, " : $(", MakeVarName, ".cs_or_ss) ",
-            "$(", MakeVarName, ".pic_os) ",
-            All_MLPicObjsString, " ", All_MLLibsDepString, "\n",
-        "\t$(ML) --make-shared-lib $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) ",
-            "-- ", InstallNameOpt, " $(ALL_LD_LIBFLAGS) -o ",
-            SharedLibFileName, " \\\n",
-        "\t\t$(", MakeVarName, ".pic_os) ", All_MLPicObjsString,
-            " $(ALL_MLLIBS)\n",
-        "endif\n\n"
-    ], !IO),
-
-    io.write_strings(DepStream, [
-        LibFileName, " : $(", MakeVarName, ".cs_or_ss) ",
-            "$(", MakeVarName, ".os) ", All_MLObjsString, "\n",
-        "\trm -f ", LibFileName, "\n",
-        "\t$(AR) $(ALL_ARFLAGS) $(AR_LIBFILE_OPT)", LibFileName, " ",
-            "$(", MakeVarName, ".os) ", All_MLObjsString, "\n",
-        "\t$(RANLIB) $(ALL_RANLIBFLAGS) ", LibFileName, "\n\n"
-    ], !IO),
-
-    ClassFiles = "$(" ++ MakeVarName ++ ".classes)",
-    list_class_files_for_jar(ModuleName, ClassFiles, ListClassFiles, !IO),
-    io.write_strings(DepStream, [
-        JarFileName, " : ", "$(", MakeVarName, ".classes)\n",
-        "\t$(JAR) $(JAR_CREATE_FLAGS) ", JarFileName, " ",
-        ListClassFiles, "\n\n"
-    ], !IO),
-
-    module_name_to_file_name(ModuleName, ".dep", no, DepFileName, !IO),
-    module_name_to_file_name(ModuleName, ".dv", no, DvFileName, !IO),
-
-    io.write_strings(DepStream, [
-        InitFileName, " : ", DepFileName, " $(", MakeVarName, ".cs)\n",
-        "\techo > ", InitFileName, "\n"
-    ], !IO),
-    io.write_strings(DepStream, [
-        "\t$(MKLIBINIT) ", "$(", MakeVarName, ".cs)", " >> ",
-        InitFileName, "\n"
-    ], !IO),
-
-    % $(EXTRA_INIT_COMMAND) should expand to a command to
-    % generate extra entries in the `.init' file for a library.
-    % It may expand to the empty string.
-    io.write_string(DepStream, "\t$(EXTRA_INIT_COMMAND) >> ", !IO),
-    io.write_string(DepStream, InitFileName, !IO),
-    io.write_string(DepStream, "\n", !IO),
-
-    % The `force-module_init' dependency forces the commands for
-    % the `module_init.c' rule to be run every time the rule
-    % is considered.
-    ModuleFileName = sym_name_to_string(ModuleName),
-    ForceC2InitTarget = "force-" ++ ModuleFileName ++ "_init",
-    TmpInitCFileName = InitCFileName ++ ".tmp",
-    io.write_strings(DepStream, [
-        ForceC2InitTarget, " :\n\n",
-        InitCFileName, " : ", ForceC2InitTarget, " $(", MakeVarName, ".cs)\n",
-        "\t@$(C2INIT) $(ALL_GRADEFLAGS) $(ALL_C2INITFLAGS) ",
-            "--init-c-file ", TmpInitCFileName,
-            " $(", MakeVarName, ".init_cs) $(ALL_C2INITARGS)\n",
-        "\t at mercury_update_interface ", InitCFileName, "\n\n"
-    ], !IO),
-
-    module_name_to_lib_file_name("lib", ModuleName, ".install_ints", no,
-        LibInstallIntsTargetName, !IO),
-    (
-        Intermod = yes,
-        OptStr = " opt"
-    ;
-        Intermod = no,
-        OptStr = ""
-    ),
-    (
-        Intermod = yes,
-        map.member(DepsMap, _, deps(_, Imports)),
-        Imports ^ children = [_ | _]
-    ->
-        % The `.int0' files only need to be installed with
-        % `--intermodule-optimization'.
-        Int0Str = " int0",
-        MaybeInt0sVar = "$(" ++ MakeVarName ++ ".int0s) "
-    ;
-        Int0Str = "",
-        MaybeInt0sVar = ""
-    ),
-    (
-        TransOpt = yes,
-        TransOptStr = " trans_opt"
-    ;
-        TransOpt = no,
-        TransOptStr = ""
-    ),
-    (
-        MmcMakeDeps = yes,
-        DepStr = " module_dep"
-    ;
-        MmcMakeDeps = no,
-        DepStr = ""
-    ),
-
-    io.write_strings(DepStream, [
-        ".PHONY : ", LibInstallIntsTargetName, "\n",
-        LibInstallIntsTargetName, " : $(", MakeVarName, ".ints) $(",
-            MakeVarName, ".int3s) ", MaybeInt0sVar, MaybeOptsVar,
-            MaybeTransOptsVar, MaybeModuleDepsVar,
-            " install_lib_dirs\n",
-        "\tfiles=""$(", MakeVarName, ".ints) $(", MakeVarName,
-            ".int3s) ", MaybeInt0sVar, MaybeOptsVar,
-            MaybeTransOptsVar, MaybeModuleDepsVar, """; \\\n",
-        "\tfor file in $$files; do \\\n",
-        "\t\ttarget=""$(INSTALL_INT_DIR)/`basename $$file`""; \\\n",
-        "\t\tif cmp -s ""$$file"" ""$$target""; then \\\n",
-        "\t\t\techo \"$$target unchanged\"; \\\n",
-        "\t\telse \\\n",
-        "\t\t\techo \"installing $$target\"; \\\n",
-        "\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
-        "\t\tfi; \\\n",
-        "\tdone\n",
-        "\t# The following is needed to support the `--use-subdirs' option\n",
-        "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
-        "\t# `$(INSTALL)'.\n",
-        "\tfor ext in int int2 int3",
-        Int0Str, OptStr, TransOptStr, DepStr,
-        "; do \\\n",
-        "\t\tdir=""$(INSTALL_INT_DIR)/Mercury/$${ext}s""; \\\n",
-        "\t\trm -rf ""$$dir""; \\\n",
-        "\t\t$(LN_S) .. ""$$dir"" || { \\\n",
-        "\t\t\t{ [ -d ""$$dir"" ] || \\\n",
-        "\t\t\t$(INSTALL_MKDIR) ""$$dir""; } && \\\n",
-        "\t\t\t$(INSTALL) ""$(INSTALL_INT_DIR)""/*.$$ext ""$$dir""; \\\n",
-        "\t\t} || exit 1; \\\n",
-        "\tdone\n\n"
-    ], !IO),
-
-    %
-    % XXX  Note that we install the `.opt' and `.trans_opt' files
-    % in two places: in the `lib/$(GRADE)/opts' directory, so
-    % that mmc will find them, and also in the `ints' directory,
-    % so that Mmake will find them.  That's not ideal, but it works.
-    %
-    module_name_to_lib_file_name("lib", ModuleName,
-        ".install_opts", no, LibInstallOptsTargetName, !IO),
-    io.write_strings(DepStream,
-        [".PHONY : ", LibInstallOptsTargetName, "\n",
-        LibInstallOptsTargetName, " : "], !IO),
-    (
-        Intermod = no,
-        TransOpt = no
-    ->
-        io.write_string(DepStream, "\n\t@:\n\n", !IO)
-    ;
-        io.write_strings(DepStream, [
-        MaybeOptsVar, MaybeTransOptsVar, "install_grade_dirs\n",
-        "\tfiles=""", MaybeOptsVar, MaybeTransOptsVar, """; \\\n",
-        "\tfor file in $$files; do \\\n",
-        "\t\ttarget=""$(INSTALL_GRADE_INT_DIR)/`basename $$file`"";\\\n",
-        "\t\tif cmp -s ""$$file"" ""$$target""; then \\\n",
-        "\t\t\techo \"$$target unchanged\"; \\\n",
-        "\t\telse \\\n",
-        "\t\t\techo \"installing $$target\"; \\\n",
-        "\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
-        "\t\tfi; \\\n",
-        "\tdone\n",
-        "\t# The following is needed to support the `--use-subdirs' option\n",
-        "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
-        "\t# `$(INSTALL)'.\n",
-        "\tfor ext in ",
-        OptStr, TransOptStr,
-        "; do \\\n",
-        "\t\tdir=""$(INSTALL_GRADE_INT_DIR)/Mercury/$${ext}s""; \\\n",
-        "\t\trm -rf ""$$dir""; \\\n",
-        "\t\t$(LN_S) .. ""$$dir"" || { \\\n",
-        "\t\t\t{ [ -d ""$$dir"" ] || \\\n",
-        "\t\t\t\t$(INSTALL_MKDIR) ""$$dir""; } && \\\n",
-        "\t\t\t$(INSTALL) ""$(INSTALL_GRADE_INT_DIR)""/*.$$ext \\\n",
-        "\t\t\t\t""$$dir""; \\\n",
-        "\t\t} || exit 1; \\\n",
-        "\tdone\n\n"
-        ], !IO)
-    ),
-
-    %
-    % XXX  Note that we install the header files in two places:
-    % in the `lib/inc' or `lib/$(GRADE)/$(FULLARCH)/inc' directory,
-    % so that the C compiler will find them, and also in the `ints'
-    % directory, so that Mmake will find them.  That's not ideal,
-    % but it works.
-    %
-    % (A better fix would be to change the VPATH setting
-    % in scripts/Mmake.vars.in so that Mmake also searches
-    % the `lib/$(GRADE)/$(FULLARCH)/inc' directory, but doing
-    % that properly is non-trivial.)
-    %
-    module_name_to_lib_file_name("lib", ModuleName,
-        ".install_hdrs", no, LibInstallHdrsTargetName, !IO),
-    io.write_strings(DepStream, [
-        ".PHONY : ", LibInstallHdrsTargetName, "\n",
-        LibInstallHdrsTargetName, " : ",
-            "$(", MakeVarName, ".mhs) ",
-            "install_lib_dirs\n",
-        "ifeq ($(", MakeVarName, ".mhs),)\n",
-        "\t@:\n",
-        "else\n",
-        "\tfor hdr in $(", MakeVarName, ".mhs); do \\\n",
-        "\t\t$(INSTALL) $$hdr $(INSTALL_INT_DIR); \\\n",
-        "\t\t$(INSTALL) $$hdr $(INSTALL_INC_DIR); \\\n",
-        "\tdone\n",
-        "endif\n\n"], !IO),
-
-    module_name_to_lib_file_name("lib", ModuleName,
-        ".install_grade_hdrs", no, LibInstallGradeHdrsTargetName, !IO),
-    io.write_strings(DepStream, [
-        ".PHONY : ", LibInstallGradeHdrsTargetName, "\n",
-        LibInstallGradeHdrsTargetName, " : ",
-            "$(", MakeVarName, ".mihs) ",
-            "install_grade_dirs\n",
-    "ifeq ($(", MakeVarName, ".mihs),)\n",
-    "\t@:\n",
-    "else\n",
-    "\tfor hdr in $(", MakeVarName, ".mihs); do \\\n",
-    "\t\t$(INSTALL) $$hdr $(INSTALL_INT_DIR); \\\n",
-    "\t\t$(INSTALL) $$hdr $(INSTALL_GRADE_INC_DIR); \\\n",
-    "\tdone\n",
-    "\t# The following is needed to support the `--use-subdirs' option\n",
-    "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
-    "\t# `$(INSTALL)'.\n",
-    "\trm -rf $(INSTALL_GRADE_INC_SUBDIR)\n",
-    "\t$(LN_S) .. $(INSTALL_GRADE_INC_SUBDIR) || { \\\n",
-    "\t\t{ [ -d $(INSTALL_GRADE_INC_SUBDIR) ] || \\\n",
-    "\t\t\t$(INSTALL_MKDIR) $(INSTALL_GRADE_INC_SUBDIR); \\\n",
-    "\t\t} && \\\n",
-    "\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
-    "\t\t\t$(INSTALL_GRADE_INC_SUBDIR); \\\n",
-    "\t} || exit 1\n",
-    "\trm -rf $(INSTALL_INT_DIR)/Mercury/mihs\n",
-    "\t$(LN_S) .. $(INSTALL_INT_DIR)/Mercury/mihs || { \\\n",
-    "\t\t{ [ -d $(INSTALL_INT_DIR)/Mercury/mihs ] || \\\n",
-    "\t\t\t$(INSTALL_MKDIR) \\\n",
-    "\t\t\t$(INSTALL_INT_DIR)/Mercury/mihs; \\\n",
-    "\t\t} && \\\n",
-    "\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
-    "\t\t\t$(INSTALL_INT_DIR); \\\n",
-    "\t} || exit 1\n",
-    "endif\n\n"], !IO),
-
-    module_name_to_file_name(ModuleName, ".check", no, CheckTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".ints", no, IntsTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".int3s", no, Int3sTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".opts", no, OptsTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".trans_opts", no,
-        TransOptsTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".ss", no, SsTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".pic_ss", no, PicSsTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".ils", no, ILsTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".javas", no, JavasTargetName, !IO),
-    module_name_to_file_name(ModuleName, ".classes", no, ClassesTargetName,
-        !IO),
-
-    % We need to explicitly mention
-    % $(foo.pic_ss) somewhere in the Mmakefile, otherwise it
-    % won't build properly with --target asm: GNU Make's pattern rule
-    % algorithm will try to use the .m -> .c_date -> .c -> .pic_o rule chain
-    % rather than the .m -> .pic_s_date -> .pic_s -> .pic_o chain.
-    % So don't remove the pic_ss target here.
-
-    io.write_strings(DepStream, [
-        ".PHONY : ", CheckTargetName, "\n",
-        CheckTargetName, " : $(", MakeVarName, ".errs)\n\n",
-        ".PHONY : ", IntsTargetName, "\n",
-        IntsTargetName, " : $(", MakeVarName, ".dates)\n\n",
-        ".PHONY : ", Int3sTargetName, "\n",
-        Int3sTargetName, " : $(", MakeVarName, ".date3s)\n\n",
-        ".PHONY : ", OptsTargetName, "\n",
-        OptsTargetName, " : $(", MakeVarName, ".optdates)\n\n",
-        ".PHONY : ", TransOptsTargetName, "\n",
-        TransOptsTargetName, " : $(", MakeVarName,
-            ".trans_opt_dates)\n\n",
-        ".PHONY : ", SsTargetName, "\n",
-        SsTargetName, " : $(", MakeVarName, ".ss)\n\n",
-        ".PHONY : ", PicSsTargetName, "\n",
-        PicSsTargetName, " : $(", MakeVarName, ".pic_ss)\n\n",
-        ".PHONY : ", ILsTargetName, "\n",
-        ILsTargetName, " : $(", MakeVarName, ".ils)\n\n",
-        ".PHONY : ", JavasTargetName, "\n",
-        JavasTargetName, " : $(", MakeVarName, ".javas)\n\n",
-        ".PHONY : ", ClassesTargetName, "\n",
-        ClassesTargetName, " : $(", MakeVarName, ".classes)\n\n"
-    ], !IO),
-
-    %
-    % If you change the clean targets below, please also update the
-    % documentation in doc/user_guide.texi.
-    %
-    % XXX The use of xargs in the clean targets doesn't handle
-    % special characters in the file names correctly.  This is
-    % currently not a problem in practice as we never generate
-    % names containing special characters, any fix for this problem
-    % will also require a fix in `mmake.in'.
-    %
-
-    module_name_to_file_name(ModuleName, ".clean", no, CleanTargetName, !IO),
-    io.write_strings(DepStream, [
-        "clean_local : ", CleanTargetName, "\n"
-    ], !IO),
-    io.write_strings(DepStream, [
-        ".PHONY : ", CleanTargetName, "\n",
-        CleanTargetName, " :\n",
-        "\t-echo $(", MakeVarName, ".dirs) | xargs rm -rf \n",
-        "\t-echo $(", MakeVarName, ".cs) ", InitCFileName,
-            " | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".mihs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_ss) ", InitAsmFileName,
-            " | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_pic_ss) ",
-            InitAsmFileName, " | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_os) ", InitObjFileName,
-            " | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_pic_os) ",
-            InitPicObjFileName, " | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".c_dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".il_dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".java_dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_s_dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_pic_s_dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".useds) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".ils) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".javas) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".profs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".errs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".foreign_cs) | xargs rm -f\n"
-    ], !IO),
-
-    io.write_string(DepStream, "\n", !IO),
-
-    module_name_to_file_name(ModuleName, ".realclean", no,
-        RealCleanTargetName, !IO),
-    io.write_strings(DepStream, [
-        "realclean_local : ", RealCleanTargetName, "\n"
-    ], !IO),
-    io.write_strings(DepStream, [
-        ".PHONY : ", RealCleanTargetName, "\n",
-        RealCleanTargetName, " : ", CleanTargetName, "\n",
-        "\t-echo $(", MakeVarName, ".dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".date0s) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".date3s) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".optdates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".trans_opt_dates) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".ints) | xargs rm -f\n",
-        % XXX This should acutally be .int0s but we need to make sure that
-        % we delete any spurious .int0 files created for nested sub-modules.
-        % For further details see the XXX comments above.
-        "\t-echo $(", MakeVarName, ".all_int0s) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".int3s) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".opts) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".trans_opts) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".analysiss) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".requests) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".imdgs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".ds) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".module_deps) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_mhs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".all_mihs) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".dlls) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".foreign_dlls) | xargs rm -f\n",
-        "\t-echo $(", MakeVarName, ".classes) | xargs rm -f\n"
-    ], !IO),
-    io.write_strings(DepStream, [
-        "\t-rm -f ",
-            ExeFileName, "$(EXT_FOR_EXE) ",
-            InitFileName, " ",
-            LibFileName, " ",
-            SharedLibFileName, " ",
-            JarFileName, " ",
-            DepFileName, " ",
-            DvFileName, "\n\n"
-    ], !IO).
-
-:- pred get_source_file(deps_map::in, module_name::in, file_name::out) is det.
-
-get_source_file(DepsMap, ModuleName, FileName) :-
-    map.lookup(DepsMap, ModuleName, Deps),
-    Deps = deps(_, ModuleImports),
-    module_imports_get_source_file_name(ModuleImports, SourceFileName),
-    ( string.remove_suffix(SourceFileName, ".m", SourceFileBase) ->
-        FileName = SourceFileBase
-    ;
-        unexpected(this_file, "source file name doesn't end in `.m'")
-    ).
-
-:- pred append_to_init_list(io.output_stream::in, file_name::in,
-    module_name::in, io::di, io::uo) is det.
-
-append_to_init_list(DepStream, InitFileName, Module, !IO) :-
-    InitFuncName0 = make_init_name(Module),
-    string.append(InitFuncName0, "init", InitFuncName),
-    io.write_strings(DepStream, [
-        "\techo ""INIT ", InitFuncName, """ >> ", InitFileName, "\n"
-    ], !IO).
-
-%-----------------------------------------------------------------------------%
-
-    % Find out which modules we need to generate C header files for,
-    % assuming we're compiling with `--target asm'.
-    %
-:- func modules_that_need_headers(list(module_name), deps_map)
-    = list(module_name).
-
-modules_that_need_headers(Modules, DepsMap) =
-    list.filter(module_needs_header(DepsMap), Modules).
-
-    % Find out which modules will generate as external foreign
-    % language files.
-    % We return the module names and file extensions.
-    %
-:- func foreign_modules(list(module_name), deps_map)
-    = assoc_list(module_name, string).
-
-foreign_modules(Modules, DepsMap) = ForeignModules :-
-    P = (pred(M::in, FMs::out) is semidet :-
-        module_has_foreign(DepsMap, M, LangList),
-        FMs = list.filter_map((func(L) = (NewM - Ext) is semidet :-
-            NewM = foreign_language_module_name(M, L),
-            Ext = foreign_language_file_extension(L)
-        ), LangList)
-    ),
-    list.filter_map(P, Modules, ForeignModulesList),
-    ForeignModules = list.condense(ForeignModulesList).
-
-    % Succeed iff we need to generate a C header file for the specified
-    % module, assuming we're compiling with `--target asm'.
-    %
-:- pred module_needs_header(deps_map::in, module_name::in) is semidet.
-
-module_needs_header(DepsMap, Module) :-
-    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
-    ModuleImports ^ has_foreign_code = contains_foreign_code(Langs),
-    set.member(lang_c, Langs).
-
-    % Succeed iff we need to generate a foreign language output file
-    % for the specified module.
-    %
-:- pred module_has_foreign(deps_map::in, module_name::in,
-    list(foreign_language)::out) is semidet.
-
-module_has_foreign(DepsMap, Module, LangList) :-
-    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
-    ModuleImports ^ has_foreign_code = contains_foreign_code(Langs),
-    LangList = set.to_sorted_list(Langs).
-
-    % get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs):
-    %
-    % Find any extra .$O files that should be linked into the executable.
-    % These include fact table object files and object files for foreign
-    % code that can't be generated inline for this target.
-    %
-:- pred get_extra_link_objects(list(module_name)::in, deps_map::in,
-    compilation_target::in, assoc_list(file_name, module_name)::out)
-    is det.
-
-get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs) :-
-    get_extra_link_objects_2(Modules, DepsMap, Target, [], ExtraLinkObjs0),
-    list.reverse(ExtraLinkObjs0, ExtraLinkObjs).
-
-:- pred get_extra_link_objects_2(list(module_name)::in, deps_map::in,
-    compilation_target::in,
-    assoc_list(file_name, module_name)::in,
-    assoc_list(file_name, module_name)::out) is det.
-
-get_extra_link_objects_2([], _DepsMap, _Target, !ExtraLinkObjs).
-get_extra_link_objects_2([Module | Modules], DepsMap, Target,
-        !ExtraLinkObjs) :-
-    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
-    %
-    % Handle object files for fact tables
-    %
-    FactDeps = ModuleImports ^ fact_table_deps,
-    list.length(FactDeps, NumFactDeps),
-    list.duplicate(NumFactDeps, Module, ModuleList),
-    assoc_list.from_corresponding_lists(FactDeps, ModuleList, FactTableObjs),
-    %
-    % Handle object files for foreign code.
-    % XXX currently we only support `C' foreign code.
-    %
-    (
-        Target = target_asm,
-        ModuleImports ^ has_foreign_code = contains_foreign_code(Langs),
-        set.member(lang_c, Langs)
-    ->
-        FileName = sym_name_to_string(Module),
-        NewLinkObjs = [(FileName ++ "__c_code") - Module | FactTableObjs]
-    ;
-        NewLinkObjs = FactTableObjs
-    ),
-    list.append(NewLinkObjs, !ExtraLinkObjs),
-    get_extra_link_objects_2(Modules, DepsMap, Target, !ExtraLinkObjs).
-
-:- type module_foreign_info --->
-    module_foreign_info(
-        used_foreign_languages          :: set(foreign_language),
-        foreign_proc_languages          :: map(sym_name, foreign_language),
-        all_foreign_import_module_info  :: foreign_import_module_info_list,
-        module_contains_foreign_export  :: contains_foreign_export
-    ).
-
-:- pred get_item_list_foreign_code(globals::in, list(item)::in,
-    set(foreign_language)::out, foreign_import_module_info_list::out,
-    contains_foreign_export::out) is det.
-
-get_item_list_foreign_code(Globals, Items, LangSet, ForeignImports,
-        ContainsPragmaExport) :-
-    Info0 = module_foreign_info(set.init, map.init, [], no_foreign_export),
-    list.foldl(get_item_foreign_code(Globals), Items, Info0, Info),
-    Info = module_foreign_info(LangSet0, LangMap, ForeignImports,
-        ContainsPragmaExport),
-    ForeignProcLangs = map.values(LangMap),
-    LangSet = set.insert_list(LangSet0, ForeignProcLangs).
-
-:- pred get_item_foreign_code(globals::in, item::in,
-    module_foreign_info::in, module_foreign_info::out) is det.
-
-get_item_foreign_code(Globals, Item, !Info) :-
-    ( Item = item_pragma(ItemPragma) ->
-        ItemPragma = item_pragma_info(_, Pragma, Context),
-        do_get_item_foreign_code(Globals, Pragma, Context, !Info)
-    ; Item = item_mutable(_) ->
-        % Mutables introduce foreign_procs, but mutable declarations
-        % won't have been expanded by the time we get here so we need
-        % to handle them separately.
-        % XXX mutables are currently only implemented for the C backends
-        % but we should handle the Java/IL backends here as well.
-        % (See do_get_item_foreign_code for details/5).
-        !:Info = !.Info ^ used_foreign_languages :=
-            set.insert(!.Info ^ used_foreign_languages, lang_c)
-    ; ( Item = item_initialise(_) ; Item = item_finalise(_) ) ->
-        % Intialise/finalise declarations introduce export pragmas, but
-        % again they won't have been expanded by the time we get here.
-        % XXX we don't currently support these on non-C backends.
-        !:Info = !.Info ^ used_foreign_languages :=
-            set.insert(!.Info ^ used_foreign_languages, lang_c),
-        !:Info = !.Info ^ module_contains_foreign_export :=
-            contains_foreign_export
-    ;
-        true
-    ).
-
-:- pred do_get_item_foreign_code(globals::in, pragma_type::in,
-    prog_context::in, module_foreign_info::in, module_foreign_info::out)
-    is det.
-
-do_get_item_foreign_code(Globals, Pragma, Context, Info0, Info) :-
-    globals.get_backend_foreign_languages(Globals, BackendLangs),
-    globals.get_target(Globals, Target),
-
-    % The code here should match the way that mlds_to_gcc.m decides whether
-    % or not to call mlds_to_c.m.  XXX Note that we do NOT count foreign_decls
-    % here. We only link in a foreign object file if mlds_to_gcc called
-    % mlds_to_c.m to generate it, which it will only do if there is some
-    % foreign_code, not just foreign_decls. Counting foreign_decls here
-    % causes problems with intermodule optimization.
-    (
-        Pragma = pragma_foreign_code(Lang, _),
-        list.member(Lang, BackendLangs)
-    ->
-        Info = Info0 ^ used_foreign_languages :=
-            set.insert(Info0 ^ used_foreign_languages, Lang)
-    ;
-        Pragma = pragma_foreign_proc(Attrs, Name, _, _, _, _, _)
-    ->
-        NewLang = get_foreign_language(Attrs),
-        ( OldLang = Info0 ^ foreign_proc_languages ^ elem(Name) ->
-            % is it better than an existing one?
-            (
-                yes = prefer_foreign_language(Globals, Target,
-                    OldLang, NewLang)
-            ->
-                Info = Info0 ^ foreign_proc_languages ^ elem(Name) := NewLang
-            ;
-                Info = Info0
-            )
-        ;
-            % is it one of the languages we support?
-            ( list.member(NewLang, BackendLangs) ->
-                Info = Info0 ^ foreign_proc_languages ^ elem(Name) := NewLang
-            ;
-                Info = Info0
-            )
-        )
-    ;
-        % XXX `pragma export' should not be treated as foreign, but currently
-        % mlds_to_gcc.m doesn't handle that declaration, and instead just
-        % punts it on to mlds_to_c.m, thus generating C code for it,
-        % rather than assembler code. So we need to treat `pragma export'
-        % like the other pragmas for foreign code.
-        Pragma = pragma_foreign_export(Lang, _, _, _, _),
-        list.member(Lang, BackendLangs)
-    ->
-        Info1 = Info0 ^ used_foreign_languages :=
-            set.insert(Info0 ^ used_foreign_languages, Lang),
-        Info = Info1 ^ module_contains_foreign_export :=
-            contains_foreign_export
-    ;
-        Pragma = pragma_foreign_import_module(Lang, Import),
-        list.member(Lang, BackendLangs)
-    ->
-        Info = Info0 ^ all_foreign_import_module_info :=
-            [foreign_import_module_info(Lang, Import, Context) |
-                Info0 ^ all_foreign_import_module_info]
-    ;
-        % We generate some C code for fact tables,
-        % so we need to treat modules containing
-        % fact tables as if they contain foreign
-        % code.
-        ( Target = target_asm
-        ; Target = target_c
-        ),
-        Pragma = pragma_fact_table(_, _, _)
-    ->
-        Info = Info0 ^ used_foreign_languages :=
-            set.insert(Info0 ^ used_foreign_languages, lang_c)
-    ;
-        Info = Info0
-    ).
-
-%-----------------------------------------------------------------------------%
-
-:- pred select_ok_modules(list(module_name)::in, deps_map::in,
-    list(module_name)::out) is det.
-
-select_ok_modules([], _, []).
-select_ok_modules([Module | Modules0], DepsMap, Modules) :-
-    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
-    module_imports_get_error(ModuleImports, Error),
-    ( Error = fatal_module_errors ->
-        Modules = Modules1
-    ;
-        Modules = [Module | Modules1]
-    ),
-    select_ok_modules(Modules0, DepsMap, Modules1).
-
-%-----------------------------------------------------------------------------%
-
-:- pred write_dependencies_list(list(module_name)::in, string::in,
-    io.output_stream::in, io::di, io::uo) is det.
-
-write_dependencies_list([], _, _, !IO).
-write_dependencies_list([Module | Modules], Suffix, DepStream, !IO) :-
-    module_name_to_file_name(Module, Suffix, no, FileName, !IO),
-    io.write_string(DepStream, " \\\n\t", !IO),
-    io.write_string(DepStream, FileName, !IO),
-    write_dependencies_list(Modules, Suffix, DepStream, !IO).
-
-referenced_dlls(Module, DepModules0) = Modules :-
-    DepModules = [Module | DepModules0],
-
-        % If we are not compiling a module in the mercury
-        % std library then replace all the std library dlls with
-        % one reference to mercury.dll.
-    (
-        mercury_std_library_module_name(Module)
-    ->
-            % In the standard library we need to add the
-            % runtime dlls.
-        Modules = list.remove_dups(
-            [unqualified("mercury_dotnet"), unqualified("mercury_il")
-                | DepModules])
-    ;
-        F = (func(M) =
-            (
-                mercury_std_library_module_name(M)
-            ->
-                unqualified("mercury")
-            ;
-                    % A sub module is located in the top level assembly.
-                unqualified(outermost_qualifier(M))
-            )
-        ),
-        Modules = list.remove_dups(list.map(F, DepModules))
-    ).
-
-    % submodules(Module, Imports):
-    %
-    % Returns the list of submodules from Imports which are sub-modules of
-    % Module, if Module is a top level module and not in the std library.
-    % Otherwise it returns the empty list.
-    %
-:- func submodules(module_name, list(module_name)) = list(module_name).
-
-submodules(Module, Modules0) = Modules :-
-    (
-        Module = unqualified(Str),
-        \+ mercury_std_library_module_name(Module)
-    ->
-        P = (pred(M::in) is semidet :-
-            Str = outermost_qualifier(M),
-            M \= Module
-        ),
-        list.filter(P, Modules0, Modules)
-    ;
-        Modules = []
-    ).
-
-:- pred write_dll_dependencies_list(list(module_name)::in,
-    string::in, io.output_stream::in, io::di, io::uo) is det.
-
-write_dll_dependencies_list(Modules, Prefix, DepStream, !IO) :-
-    list.foldl(write_dll_dependency(DepStream, Prefix), Modules, !IO).
-
-:- pred write_dll_dependency(io.output_stream::in, string::in,
-    module_name::in, io::di, io::uo) is det.
-
-write_dll_dependency(DepStream, Prefix, Module, !IO) :-
-    module_name_to_file_name(Module, ".dll", no, FileName, !IO),
-    io.write_string(DepStream, " \\\n\t", !IO),
-    io.write_string(DepStream, Prefix, !IO),
-    io.write_string(DepStream, FileName, !IO).
-
-:- pred write_fact_table_dependencies_list(module_name::in,
-    list(file_name)::in, string::in, io.output_stream::in,
-    io::di, io::uo) is det.
-
-write_fact_table_dependencies_list(_, [], _, _, !IO).
-write_fact_table_dependencies_list(Module, [FactTable | FactTables], Suffix,
-        DepStream, !IO) :-
-    fact_table_file_name(Module, FactTable, Suffix, no, FileName, !IO),
-    io.write_string(DepStream, " \\\n\t", !IO),
-    io.write_string(DepStream, FileName, !IO),
-    write_fact_table_dependencies_list(Module, FactTables, Suffix,
-        DepStream, !IO).
-
-:- pred write_extra_link_dependencies_list(
-    assoc_list(file_name, module_name)::in, string::in,
-    io.output_stream::in, io::di, io::uo) is det.
-
-write_extra_link_dependencies_list([], _, _, !IO).
-write_extra_link_dependencies_list([ExtraLink - Module | ExtraLinks], Suffix,
-        DepStream, !IO) :-
-    extra_link_obj_file_name(Module, ExtraLink, Suffix, no, FileName, !IO),
-    io.write_string(DepStream, " \\\n\t", !IO),
-    io.write_string(DepStream, FileName, !IO),
-    write_extra_link_dependencies_list(ExtraLinks, Suffix, DepStream, !IO).
-
-:- pred write_file_dependencies_list(list(string)::in, string::in,
-    io.output_stream::in, io::di, io::uo) is det.
-
-write_file_dependencies_list([], _, _, !IO).
-write_file_dependencies_list([FileName | FileNames], Suffix, DepStream, !IO) :-
-    io.write_string(DepStream, " \\\n\t", !IO),
-    io.write_string(DepStream, FileName, !IO),
-    io.write_string(DepStream, Suffix, !IO),
-    write_file_dependencies_list(FileNames, Suffix, DepStream, !IO).
-
-%-----------------------------------------------------------------------------%
-
-:- pred write_compact_dependencies_list(list(module_name)::in, string::in,
-    string::in, maybe(pair(string))::in, io.output_stream::in,
-    io::di, io::uo) is det.
-
-write_compact_dependencies_list(Modules, Prefix, Suffix, Basis, DepStream,
-        !IO) :-
-    (
-        Basis = yes(VarName - OldSuffix),
-        io.write_string(DepStream, "$(", !IO),
-        io.write_string(DepStream, VarName, !IO),
-        io.write_string(DepStream, ":%", !IO),
-        io.write_string(DepStream, OldSuffix, !IO),
-        io.write_string(DepStream, "=", !IO),
-        io.write_string(DepStream, Prefix, !IO),
-        io.write_string(DepStream, "%", !IO),
-        io.write_string(DepStream, Suffix, !IO),
-        io.write_string(DepStream, ")", !IO)
-    ;
-        Basis = no,
-        write_dependencies_list(Modules, Suffix, DepStream, !IO)
-    ).
-
-:- pred write_compact_dependencies_separator(maybe(pair(string))::in,
-    io.output_stream::in, io::di, io::uo) is det.
-
-write_compact_dependencies_separator(no, _DepStream, !IO).
-write_compact_dependencies_separator(yes(_), DepStream, !IO) :-
-    io.write_string(DepStream, " ", !IO).
-
-%-----------------------------------------------------------------------------%
-
-    % Look up a module in the dependency map.
-    % If we don't know its dependencies, read the module and
-    % save the dependencies in the dependency map.
-    %
-:- pred lookup_dependencies(module_name::in, bool::in, bool::out,
-    deps_map::in, deps_map::out, module_imports::out, io::di, io::uo) is det.
-
-lookup_dependencies(Module, Search, Done, !DepsMap, ModuleImports, !IO) :-
-    ( map.search(!.DepsMap, Module, deps(DonePrime, ModuleImportsPrime)) ->
-        Done = DonePrime,
-        ModuleImports = ModuleImportsPrime
-    ;
-        read_dependencies(Module, Search, ModuleImportsList, !IO),
-        list.foldl(insert_into_deps_map, ModuleImportsList, !DepsMap),
-        map.lookup(!.DepsMap, Module, deps(Done, ModuleImports))
-    ).
-
-    % insert_into_deps_map/3:
-    %
-    % Insert a new entry into the deps_map. If the module already occurred
-    % in the deps_map, then we just replace the old entry (presumed to be
-    % a dummy entry) with the new one.
-    %
-    % This can only occur for sub-modules which have been imported before
-    % their parent module was imported: before reading a module and
-    % inserting it into the deps map, we check if it was already there,
-    % but when we read in the module, we try to insert not just that module
-    % but also all the nested sub-modules inside that module. If a sub-module
-    % was previously imported, then it may already have an entry in the
-    % deps_map. However, unless the sub-module is defined both as a separate
-    % sub-module and also as a nested sub-module, the previous entry will be
-    % a dummy entry that we inserted after trying to read the source file
-    % and failing.
-    %
-    % Note that the case where a module is defined as both a separate
-    % sub-module and also as a nested sub-module is caught in
-    % split_into_submodules.
-    %
-:- pred insert_into_deps_map(module_imports::in, deps_map::in, deps_map::out)
-    is det.
-
-insert_into_deps_map(ModuleImports, DepsMap0, DepsMap) :-
-    module_imports_get_module_name(ModuleImports, ModuleName),
-    map.set(DepsMap0, ModuleName, deps(no, ModuleImports), DepsMap).
-
-    % Read a module to determine the (direct) dependencies of that module
-    % and any nested sub-modules it contains.
-    %
-:- pred read_dependencies(module_name::in, bool::in, list(module_imports)::out,
-    io::di, io::uo) is det.
-
-read_dependencies(ModuleName, Search, ModuleImportsList, !IO) :-
-    read_mod_ignore_errors(ModuleName, ".m",
-        "Getting dependencies for module", Search, no, Items0, Error,
-        FileName0, _, !IO),
-    globals.io_get_globals(Globals, !IO),
-    (
-        Items0 = [],
-        Error = fatal_module_errors
-    ->
-        read_mod_ignore_errors(ModuleName, ".int",
-            "Getting dependencies for module interface", Search,
-            no, Items, _Error, FileName, _, !IO),
-        SubModuleList = [ModuleName - Items]
-    ;
-        FileName = FileName0,
-        Items = Items0,
-        split_into_submodules(ModuleName, Items, SubModuleList, [], Specs),
-        write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO)
-    ),
-    assoc_list.keys(SubModuleList, SubModuleNames),
-    list.map(init_dependencies(FileName, ModuleName, SubModuleNames,
-        Error, Globals), SubModuleList, ModuleImportsList).
-
-init_dependencies(FileName, SourceFileModuleName, NestedModuleNames,
-        Error, Globals, ModuleName - Items, ModuleImports) :-
-    ParentDeps = get_ancestors(ModuleName),
-
-    get_dependencies(Items, ImplImportDeps0, ImplUseDeps0),
-    add_implicit_imports(Items, Globals,
-        ImplImportDeps0, ImplImportDeps,
-        ImplUseDeps0, ImplUseDeps),
-    list.append(ImplImportDeps, ImplUseDeps, ImplementationDeps),
-
-    get_interface(ModuleName, no, Items, InterfaceItems),
-    get_dependencies(InterfaceItems,
-        InterfaceImportDeps0, InterfaceUseDeps0),
-    add_implicit_imports(InterfaceItems, Globals,
-        InterfaceImportDeps0, InterfaceImportDeps,
-        InterfaceUseDeps0, InterfaceUseDeps),
-    list.append(InterfaceImportDeps, InterfaceUseDeps, InterfaceDeps),
-
-    % We don't fill in the indirect dependencies yet.
-    IndirectDeps = [],
-
-    get_children(Items, IncludeDeps),
-    get_children(InterfaceItems, InterfaceIncludeDeps),
-
-    ( ModuleName = SourceFileModuleName ->
-        list.delete_all(NestedModuleNames, ModuleName, NestedDeps)
-    ;
-        NestedDeps = []
-    ),
-
-    get_fact_table_dependencies(Items, FactTableDeps),
-
-    % Figure out whether the items contain foreign code.
-    get_item_list_foreign_code(Globals, Items, LangSet,
-        ForeignImports0, ContainsPragmaExport),
-    ( set.empty(LangSet) ->
-        ContainsForeignCode = no_foreign_code
-    ;
-        ContainsForeignCode = contains_foreign_code(LangSet)
-    ),
-
-    % If this module contains `:- pragma foreign_export' or
-    % `:- pragma foreign_type' declarations, importing modules
-    % may need to import its `.mh' file.
-    get_foreign_self_imports(Items, SelfImportLangs),
-    ForeignSelfImports = list.map(
-        (func(Lang) = foreign_import_module_info(Lang, ModuleName,
-            term.context_init)),
-        SelfImportLangs),
-    ForeignImports = ForeignSelfImports ++ ForeignImports0,
-
-    % Work out whether the items contain main/2.
-    (
-        list.member(Item, Items),
-        Item = item_pred_decl(ItemPredDecl),
-        ItemPredDecl = item_pred_decl_info(_, _, _, _, pf_predicate, Name,
-            [_, _], WithType, _, _, _, _, _, _),
-        unqualify_name(Name) = "main",
-
-        % XXX We should allow `main/2' to be declared using
-        % `with_type`, but equivalences haven't been expanded
-        % at this point. The `has_main' field is only used for
-        % some special case handling of the module containing
-        % main for the IL backend (we generate a `.exe' file
-        % rather than a `.dll' file). This would arguably be
-        % better done by generating a `.dll' file as normal,
-        % and a separate `.exe' file containing initialization
-        % code and a call to `main/2', as we do with the `_init.c'
-        % file in the C backend.
-        WithType = no
-    ->
-        HasMain = has_main
-    ;
-        HasMain = no_main
-    ),
-
-    ModuleImports = module_imports(FileName, SourceFileModuleName,
-        ModuleName, ParentDeps, InterfaceDeps,
-        ImplementationDeps, IndirectDeps, IncludeDeps,
-        InterfaceIncludeDeps, NestedDeps, FactTableDeps,
-        ContainsForeignCode, ForeignImports, ContainsPragmaExport,
-        [], Error, no, HasMain, dir.this_directory).
+:- pred add_parent_impl_deps_list(lookup_module_imports::lookup_module_imports,
+    deps_graph_key::in, list(module_name)::in, deps_graph::in, deps_graph::out)
+    is det.
 
-%-----------------------------------------------------------------------------%
+add_parent_impl_deps_list(LookupModuleImports, ModuleKey, Parents,
+        !DepsGraph) :-
+    list.foldl(add_parent_impl_deps(LookupModuleImports, ModuleKey), Parents,
+        !DepsGraph).
 
-:- pred read_mod(read_modules::in, module_name::in, string::in, string::in,
-    bool::in, bool::in, list(item)::out, module_error::out, file_name::out,
-    maybe(timestamp)::out, io::di, io::uo) is det.
+    % Add a single dependency to a graph.
+    %
+:- pred add_dep(digraph_key(T)::in, T::in, digraph(T)::in, digraph(T)::out)
+    is det.
 
-read_mod(ReadModules, ModuleName, Extension, Descr, Search, ReturnTimestamp,
-        Items, Error, FileName, MaybeTimestamp, !IO) :-
-    (
-        find_read_module(ReadModules, ModuleName, Extension, ReturnTimestamp,
-            Items0, MaybeTimestamp0, Error0, FileName0)
-    ->
-        Error = Error0,
-        Items = Items0,
-        MaybeTimestamp = MaybeTimestamp0,
-        FileName = FileName0
-    ;
-        read_mod(ModuleName, Extension, Descr, Search, ReturnTimestamp,
-            Items, Error, FileName, MaybeTimestamp, !IO)
-    ).
-
-read_mod(ModuleName, Extension, Descr, Search, ReturnTimestamp,
-        Items, Error, FileName, MaybeTimestamp, !IO) :-
-    read_mod_2(no, ModuleName, Extension, Descr, Search,
-        no, ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO).
-
-read_mod_if_changed(ModuleName, Extension, Descr, Search, OldTimestamp,
-        Items, Error, FileName, MaybeTimestamp, !IO) :-
-    read_mod_2(no, ModuleName, Extension, Descr, Search,
-        yes(OldTimestamp), yes, Items, Error,
-        FileName, MaybeTimestamp, !IO).
-
-read_mod_ignore_errors(ModuleName, Extension, Descr, Search, ReturnTimestamp,
-        Items, Error, FileName, MaybeTimestamp, !IO) :-
-    read_mod_2(yes, ModuleName, Extension, Descr, Search,
-        no, ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO).
-
-:- pred read_mod_2(bool::in, module_name::in, string::in, string::in,
-    bool::in, maybe(timestamp)::in, bool::in, list(item)::out,
-    module_error::out, file_name::out, maybe(timestamp)::out,
-    io::di, io::uo) is det.
+add_dep(ModuleKey, Dep, !DepsGraph) :-
+    digraph.add_vertex(Dep, DepKey, !DepsGraph),
+    digraph.add_edge(ModuleKey, DepKey, !DepsGraph).
 
-read_mod_2(IgnoreErrors, ModuleName, Extension, Descr, Search,
-        MaybeOldTimestamp, ReturnTimestamp, Items, Error, FileName,
-        MaybeTimestamp, !IO) :-
-    (
-        Search = yes,
-        module_name_to_search_file_name(ModuleName, Extension, FileName0, !IO)
-    ;
-        Search = no,
-        module_name_to_file_name(ModuleName, Extension, no, FileName0, !IO)
-    ),
-    globals.io_lookup_bool_option(very_verbose, VeryVerbose, !IO),
-    maybe_write_string(VeryVerbose, "% ", !IO),
-    maybe_write_string(VeryVerbose, Descr, !IO),
-    maybe_write_string(VeryVerbose, " `", !IO),
-    maybe_write_string(VeryVerbose, FileName0, !IO),
-    maybe_write_string(VeryVerbose, "'... ", !IO),
-    maybe_flush_output(VeryVerbose, !IO),
+%-----------------------------------------------------------------------------%
 
-    globals.io_lookup_accumulating_option(search_directories,
-        InterfaceSearchDirs, !IO),
-    (
-        Search = yes,
-        SearchDirs = InterfaceSearchDirs
-    ;
-        Search = no,
-        SearchDirs = [dir.this_directory]
-    ),
-    ( Extension = ".m" ->
-        % For `.m' files we need to deal with the case where
-        % the module name does not match the file name, or where
-        % a partial match occurs in the current directory but the
-        % full match occurs in a search directory.
-        %
-        OpenFile = search_for_module_source(SearchDirs,
-                        InterfaceSearchDirs, ModuleName)
-    ;
-        OpenFile = search_for_file(SearchDirs, FileName0)
-    ),
-    (
-        MaybeOldTimestamp = yes(OldTimestamp),
-        prog_io.read_module_if_changed(OpenFile, ModuleName, OldTimestamp,
-            MaybeFileName, ActualModuleName, Items, Specs, Error,
-            MaybeTimestamp0, !IO)
-    ;
-        MaybeOldTimestamp = no,
-        prog_io.read_module(OpenFile, ModuleName, ReturnTimestamp,
-            MaybeFileName, ActualModuleName, Items, Specs, Error,
-            MaybeTimestamp0, !IO)
-    ),
+:- pred append_to_init_list(io.output_stream::in, file_name::in,
+    module_name::in, io::di, io::uo) is det.
 
-    (
-        MaybeFileName = yes(FileName)
-    ;
-        MaybeFileName = no,
-        FileName = FileName0
-    ),
-    check_module_has_expected_name(FileName, ModuleName, ActualModuleName,
-        !IO),
+append_to_init_list(DepStream, InitFileName, Module, !IO) :-
+    InitFuncName0 = make_init_name(Module),
+    string.append(InitFuncName0, "init", InitFuncName),
+    io.write_strings(DepStream, [
+        "\techo ""INIT ", InitFuncName, """ >> ", InitFileName, "\n"
+    ], !IO).
 
-    check_timestamp(FileName0, MaybeTimestamp0, MaybeTimestamp, !IO),
-    (
-        IgnoreErrors = yes,
-        (
-            Error = fatal_module_errors,
-            Items = []
-        ->
-            maybe_write_string(VeryVerbose, "not found.\n", !IO)
-        ;
-            maybe_write_string(VeryVerbose, "done.\n", !IO)
-        )
-    ;
-        IgnoreErrors = no,
-        (
-            Error = fatal_module_errors,
-            maybe_write_string(VeryVerbose, "fatal error(s).\n", !IO),
-            io.set_exit_status(1, !IO)
-        ;
-            Error = some_module_errors,
-            maybe_write_string(VeryVerbose, "parse error(s).\n", !IO),
-            io.set_exit_status(1, !IO)
-        ;
-            Error = no_module_errors,
-            maybe_write_string(VeryVerbose, "successful parse.\n", !IO)
-        ),
-        globals.io_get_globals(Globals, !IO),
-        % XXX _NumWarnings _NumErrors
-        write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO)
-    ).
+%-----------------------------------------------------------------------------%
 
-read_mod_from_file(FileName, Extension, Descr, Search, ReturnTimestamp,
-        Items, Error, ModuleName, MaybeTimestamp, !IO) :-
-    globals.io_lookup_bool_option(very_verbose, VeryVerbose, !IO),
-    maybe_write_string(VeryVerbose, "% ", !IO),
-    maybe_write_string(VeryVerbose, Descr, !IO),
-    maybe_write_string(VeryVerbose, " `", !IO),
-    maybe_write_string(VeryVerbose, FileName, !IO),
-    maybe_write_string(VeryVerbose, "'... ", !IO),
-    maybe_flush_output(VeryVerbose, !IO),
-    string.append(FileName, Extension, FullFileName),
-    ( dir.basename(FileName, BaseFileNamePrime) ->
-        BaseFileName = BaseFileNamePrime
-    ;
-        BaseFileName = ""
-    ),
-    file_name_to_module_name(BaseFileName, DefaultModuleName),
-    (
-        Search = yes,
-        globals.io_lookup_accumulating_option(search_directories,
-            SearchDirs, !IO)
-    ;
-        Search = no,
-        SearchDirs = [dir.this_directory]
-    ),
-    OpenFile = search_for_file(SearchDirs, FullFileName),
-    prog_io.read_module(OpenFile, DefaultModuleName, ReturnTimestamp,
-        _, ModuleName, Items, Specs, Error, MaybeTimestamp0, !IO),
-    check_timestamp(FullFileName, MaybeTimestamp0, MaybeTimestamp, !IO),
-    (
-        Error = fatal_module_errors,
-        maybe_write_string(VeryVerbose, "fatal error(s).\n", !IO),
-        io.set_exit_status(1, !IO)
-    ;
-        Error = some_module_errors,
-        maybe_write_string(VeryVerbose, "parse error(s).\n", !IO),
-        io.set_exit_status(1, !IO)
-    ;
-        Error = no_module_errors,
-        maybe_write_string(VeryVerbose, "successful parse.\n", !IO)
-    ),
-    globals.io_get_globals(Globals, !IO),
-    % XXX _NumWarnings _NumErrors
-    write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO).
+    % Find out which modules we need to generate C header files for,
+    % assuming we're compiling with `--target asm'.
+    %
+:- func modules_that_need_headers(list(module_name), deps_map)
+    = list(module_name).
 
-:- pred check_timestamp(file_name::in, maybe(io.res(timestamp))::in,
-    maybe(timestamp)::out, io::di, io::uo) is det.
+modules_that_need_headers(Modules, DepsMap) =
+    list.filter(module_needs_header(DepsMap), Modules).
 
-check_timestamp(FileName, MaybeTimestamp0, MaybeTimestamp, !IO) :-
-    (
-        MaybeTimestamp0 = yes(ok(Timestamp)),
-        MaybeTimestamp = yes(Timestamp)
-    ;
-        MaybeTimestamp0 = yes(error(IOError)),
-        MaybeTimestamp = no,
-        globals.io_lookup_bool_option(smart_recompilation, SmartRecompilation,
-            !IO),
-        (
-            SmartRecompilation = yes,
-            report_modification_time_warning(FileName, IOError, !IO)
-        ;
-            SmartRecompilation = no
-        )
-    ;
-        MaybeTimestamp0 = no,
-        MaybeTimestamp = no
-    ).
+    % Succeed iff we need to generate a C header file for the specified
+    % module, assuming we're compiling with `--target asm'.
+    %
+:- pred module_needs_header(deps_map::in, module_name::in) is semidet.
 
-% :- pred combine_module_errors(module_error, module_error, module_error).
-% :- mode combine_module_errors(in, in, out) is det.
-%
-% combine_module_errors(fatal, _, fatal).
-% combine_module_errors(yes, fatal, fatal).
-% combine_module_errors(yes, yes, yes).
-% combine_module_errors(yes, no, yes).
-% combine_module_errors(no, Error, Error).
+module_needs_header(DepsMap, Module) :-
+    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
+    ModuleImports ^ has_foreign_code = contains_foreign_code(Langs),
+    set.member(lang_c, Langs).
 
 %-----------------------------------------------------------------------------%
 
@@ -6895,9 +2680,9 @@
     ;
         ModItems0 = !.Module ^ items,
         ModError0 = !.Module ^ error,
-        maybe_to_bool(!.Module ^ maybe_timestamps, ReturnTimestamp),
-        read_mod(ReadModules, Ancestor, ".int0",
-            "Reading private interface for module", yes,
+        maybe_return_timestamp(!.Module ^ maybe_timestamps, ReturnTimestamp),
+        maybe_read_module(ReadModules, Ancestor, ".int0",
+            "Reading private interface for module", do_search,
             ReturnTimestamp, PrivateIntItems, PrivateIntError,
             _AncestorFileName, MaybeTimestamp, !IO),
 
@@ -6938,7 +2723,7 @@
     ModuleName = !.Module ^ module_name,
     ModImplementationImports0 = !.Module ^ impl_deps,
     (
-        % have we already read it?
+        % Have we already read it?
         ( Import = ModuleName
         ; list.member(Import, !.Module ^ parent_deps)
         ; list.member(Import, !.Module ^ int_deps)
@@ -6951,13 +2736,13 @@
     ;
         ModItems0 = !.Module ^ items,
         ModError0 = !.Module ^ error,
-        maybe_to_bool(!.Module ^ maybe_timestamps, ReturnTimestamp),
-        read_mod(ReadModules, Import, Ext,
-            "Reading interface for module", yes, ReturnTimestamp,
+        maybe_return_timestamp(!.Module ^ maybe_timestamps, ReturnTimestamp),
+        maybe_read_module(ReadModules, Import, Ext,
+            "Reading interface for module", do_search, ReturnTimestamp,
             LongIntItems, LongIntError, _LongIntFileName,
             MaybeTimestamp, !IO),
 
-        get_dependencies(LongIntItems,
+        get_dependencies_int_imp(LongIntItems,
             IndirectImports1, IndirectUses1,
             ImplIndirectImports1, ImplIndirectUses1),
         replace_section_decls(IntStatusItem, ImpStatusItem,
@@ -7133,15 +2918,15 @@
     ;
         ModItems0 = !.Module ^ items,
         ModError0 = !.Module ^ error,
-        maybe_to_bool(!.Module ^ maybe_timestamps, ReturnTimestamp),
-        read_mod(ReadModules, Import, Ext,
-            "Reading short interface for module", yes,
+        maybe_return_timestamp(!.Module ^ maybe_timestamps, ReturnTimestamp),
+        maybe_read_module(ReadModules, Import, Ext,
+            "Reading short interface for module", do_search,
             ReturnTimestamp, ShortIntItems, ShortIntError,
             _ImportFileName, MaybeTimestamp, !IO),
         maybe_record_timestamp(Import, Ext, must_be_qualified,
             MaybeTimestamp, !Module),
 
-        get_dependencies(ShortIntItems, IntImports1, IntUses1,
+        get_dependencies_int_imp(ShortIntItems, IntImports1, IntUses1,
             ImpImports1, ImpUses1),
         replace_section_decls(IntStatusItem, ImpStatusItem,
             ShortIntItems, Items),
@@ -7196,23 +2981,6 @@
 
 %-----------------------------------------------------------------------------%
 
-get_ancestors(ModuleName) = get_ancestors_2(ModuleName, []).
-
-:- func get_ancestors_2(module_name, list(module_name)) = list(module_name).
-
-get_ancestors_2(unqualified(_), Ancestors) = Ancestors.
-get_ancestors_2(qualified(Parent, _), Ancestors0) =
-    get_ancestors_2(Parent, [Parent | Ancestors0]).
-
-%-----------------------------------------------------------------------------%
-
-    % get_children(Items, IncludeDeps):
-    %
-    % IncludeDeps is the list of sub-modules declared with `:- include_module'
-    % in Items.
-    %
-:- pred get_children(list(item)::in, list(module_name)::out) is det.
-
 get_children(Items, IncludeDeps) :-
     get_children_2(Items, [], IncludeDeps).
 
@@ -7289,131 +3057,6 @@
 
 %-----------------------------------------------------------------------------%
 
-get_dependencies(Items, ImportDeps, UseDeps) :-
-    get_dependencies_implementation(Items,
-        [], IntImportDeps, [], IntUseDeps, [], ImpImportDeps, [], ImpUseDeps),
-    ImportDeps = IntImportDeps ++ ImpImportDeps,
-    UseDeps = IntUseDeps ++ ImpUseDeps.
-
-    % get_dependencies(Items, IntImportDeps, IntUseDeps,
-    %   ImpImportDeps, ImpUseDeps):
-    %
-    % Get the list of modules that a list of items (explicitly) depends on.
-    %
-    % IntImportDeps is the list of modules imported using `:- import_module'
-    % in the interface, and ImpImportDeps those modules imported in the
-    % implementation. IntUseDeps is the list of modules imported using
-    % `:- use_module' in the interface, and ImpUseDeps those modules imported
-    % in the implementation.
-    %
-    % N.B. Typically you also need to consider the module's implicit
-    % dependencies (see get_implicit_dependencies/3), its parent modules
-    % (see get_ancestors/1) and possibly also the module's child modules
-    % (see get_children/2). You may also need to consider indirect
-    % dependencies.
-    %
-    % N.B This predicate assumes that any declarations between the `:- module'
-    % and the first `:- interface' or `:- implementation' are in the
-    % implementation.
-    %
-:- pred get_dependencies(list(item)::in,
-    list(module_name)::out, list(module_name)::out,
-    list(module_name)::out, list(module_name)::out) is det.
-
-get_dependencies(Items, IntImportDeps, IntUseDeps,
-        ImpImportDeps, ImpUseDeps) :-
-    get_dependencies_implementation(Items,
-        [], IntImportDeps, [], IntUseDeps, [], ImpImportDeps, [], ImpUseDeps).
-
-:- pred get_dependencies_implementation(list(item)::in,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out) is det.
-
-get_dependencies_implementation([],
-        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps).
-get_dependencies_implementation([Item | Items],
-        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps) :-
-    ( Item = item_module_defn(ItemModuleDefn) ->
-        ItemModuleDefn = item_module_defn_info(ModuleDefn, _),
-        ( ModuleDefn = md_interface ->
-            get_dependencies_interface(Items,
-                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
-        ;
-            ( ModuleDefn = md_import(Modules) ->
-                !:ImpImportDeps = !.ImpImportDeps ++ Modules
-            ; ModuleDefn = md_use(Modules) ->
-                !:ImpUseDeps = !.ImpUseDeps ++ Modules
-            ;
-                true
-            ),
-            get_dependencies_implementation(Items,
-                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
-        )
-    ;
-        get_dependencies_implementation(Items,
-            !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
-    ).
-
-:- pred get_dependencies_interface(list(item)::in,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out,
-    list(module_name)::in, list(module_name)::out) is det.
-
-get_dependencies_interface([],
-        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps).
-get_dependencies_interface([Item | Items],
-        !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps) :-
-    ( Item = item_module_defn(ItemModuleDefn) ->
-        ItemModuleDefn = item_module_defn_info(ModuleDefn, _),
-        ( ModuleDefn = md_implementation ->
-            get_dependencies_implementation(Items,
-                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
-        ;
-            ( ModuleDefn = md_import(Modules) ->
-                !:IntImportDeps = !.IntImportDeps ++ Modules
-            ; ModuleDefn = md_use(Modules) ->
-                !:IntUseDeps = !.IntUseDeps ++ Modules
-            ;
-                true
-            ),
-            get_dependencies_interface(Items,
-                !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
-        )
-    ;
-        get_dependencies_interface(Items,
-            !IntImportDeps, !IntUseDeps, !ImpImportDeps, !ImpUseDeps)
-    ).
-
-%-----------------------------------------------------------------------------%
-
-    % Get the fact table dependencies for a module.
-    %
-:- pred get_fact_table_dependencies(list(item)::in, list(string)::out) is det.
-
-get_fact_table_dependencies(Items, Deps) :-
-    get_fact_table_dependencies_2(Items, [], Deps).
-
-:- pred get_fact_table_dependencies_2(list(item)::in, list(string)::in,
-    list(string)::out) is det.
-
-get_fact_table_dependencies_2([], !Deps).
-get_fact_table_dependencies_2([Item | Items], !Deps) :-
-    (
-        Item = item_pragma(ItemPragma),
-        ItemPragma = item_pragma_info(_, Pragma, _),
-        Pragma = pragma_fact_table(_SymName, _Arity, FileName)
-    ->
-        !:Deps = [FileName | !.Deps]
-    ;
-        true
-    ),
-    get_fact_table_dependencies_2(Items, !Deps).
-
-%-----------------------------------------------------------------------------%
-
 :- type submodule_map == map(module_name, list(item)).
 
     % Given a module (well, a list of items), split it into
@@ -7651,15 +3294,6 @@
     Spec = error_spec(severity_error, phase_parse_tree_to_hlds, [Msg]),
     !:Specs = [Spec | !.Specs].
 
-    % Given a module (well, a list of items), extract the interface
-    % part of that module, i.e. all the items between `:- interface'
-    % and `:- implementation'.
-    % The bodies of instance definitions are removed because
-    % the instance methods have not yet been module qualified.
-    %
-:- pred get_interface(module_name::in, bool::in,
-    list(item)::in, list(item)::out) is det.
-
 get_interface(ModuleName, IncludeImplTypes, Items0, Items) :-
     AddToImpl = (func(_, ImplItems) = ImplItems),
     get_interface_and_implementation_2(IncludeImplTypes, Items0, no,
@@ -7681,6 +3315,24 @@
     maybe_add_foreign_import_module(ModuleName,
         InterfaceItems0, InterfaceItems).
 
+:- pred init_module_imports(file_name::in, module_name::in, module_name::in,
+    list(item)::in, list(module_name)::in, list(module_name)::in,
+    list(string)::in, maybe(module_timestamps)::in, module_imports::out)
+    is det.
+
+init_module_imports(SourceFileName, SourceFileModuleName, ModuleName,
+        Items0, PublicChildren, NestedChildren, FactDeps,
+        MaybeTimestamps, Module) :-
+    % XXX The reason why init_module_imports is here and not in
+    % module_imports.m is this call. This should be fixed, preferably
+    % by changing the module_imports structure.
+    maybe_add_foreign_import_module(ModuleName, Items0, Items),
+    Module = module_imports(SourceFileName, SourceFileModuleName,
+        ModuleName, [], [], [], [], [], PublicChildren,
+        NestedChildren, FactDeps, contains_foreign_code_unknown, [],
+        contains_no_foreign_export, Items, no_module_errors,
+        MaybeTimestamps, no_main, dir.this_directory).
+
 :- pred maybe_add_foreign_import_module(module_name::in,
     list(item)::in, list(item)::out) is det.
 
@@ -7697,9 +3349,6 @@
     ItemPragma = item_pragma_info(Origin, Pragma, term.context_init),
     Item = item_pragma(ItemPragma).
 
-:- pred get_foreign_self_imports(list(item)::in, list(foreign_language)::out)
-    is det.
-
 get_foreign_self_imports(Items, Langs) :-
     list.foldl(accumulate_item_foreign_import_langs, Items, set.init, LangSet),
     set.to_sorted_list(LangSet, Langs).
@@ -8595,10 +4244,11 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred maybe_to_bool(maybe(T)::in, bool::out) is det.
+:- pred maybe_return_timestamp(maybe(T)::in, maybe_return_timestamp::out)
+    is det.
 
-maybe_to_bool(yes(_), yes).
-maybe_to_bool(no, no).
+maybe_return_timestamp(yes(_), do_return_timestamp).
+maybe_return_timestamp(no, do_not_return_timestamp).
 
 :- pred maybe_record_timestamp(module_name::in, string::in, need_qualifier::in,
     maybe(timestamp)::in, module_imports::in, module_imports::out) is det.
@@ -8619,299 +4269,6 @@
         !.Module ^ maybe_timestamps = no
     ).
 
-:- pred report_modification_time_warning(file_name::in, io.error::in,
-    io::di, io::uo) is det.
-
-report_modification_time_warning(SourceFileName, Error, !IO) :-
-    globals.io_set_option(smart_recompilation, bool(no), !IO),
-    globals.io_set_option(generate_item_version_numbers, bool(no), !IO),
-    globals.io_lookup_bool_option(warn_smart_recompilation, Warn, !IO),
-    (
-        Warn = yes,
-        io.write_string("Warning: cannot find modification time for ", !IO),
-        io.write_string(SourceFileName, !IO),
-        io.write_string(":\n", !IO),
-        io.error_message(Error, Msg),
-        io.write_string("  ", !IO),
-        io.write_string(Msg, !IO),
-        io.write_string(".\n", !IO),
-        io.write_string("  Smart recompilation will not work.\n", !IO),
-        globals.io_lookup_bool_option(halt_at_warn, HaltAtWarn, !IO),
-        (
-            HaltAtWarn = yes,
-            io.set_exit_status(1, !IO)
-        ;
-            HaltAtWarn = no
-        )
-    ;
-        Warn = no
-    ).
-
-%-----------------------------------------------------------------------------%
-%
-% Java command-line utilities.
-%
-
-create_java_shell_script(MainModuleName, Succeeded, !IO) :-
-    % XXX Extension should be ".bat" on Windows
-    Extension = "",
-    module_name_to_file_name(MainModuleName, Extension, no, FileName, !IO),
-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    maybe_write_string(Verbose, "% Generating shell script `" ++
-        FileName ++ "'...\n", !IO),
-
-    module_name_to_file_name(MainModuleName, ".class", no, ClassFileName, !IO),
-    DirName = dir.dirname(ClassFileName),
-
-    % XXX PathSeparator should be ";" on Windows
-    PathSeparator = ":",
-    globals.io_lookup_accumulating_option(java_classpath, Java_Incl_Dirs0,
-        !IO),
-    % We prepend the .class files' directory and the current CLASSPATH.
-    Java_Incl_Dirs = [DirName, "$CLASSPATH" | Java_Incl_Dirs0],
-    ClassPath = string.join_list(PathSeparator, Java_Incl_Dirs),
-
-    globals.io_lookup_string_option(java_interpreter, Java, !IO),
-    module_name_to_file_name(MainModuleName, "", no, Name_No_Extn, !IO),
-
-    io.open_output(FileName, OpenResult, !IO),
-    (
-        OpenResult = ok(ShellScript),
-        % XXX On Windows we should output a .bat file instead
-        io.write_string(ShellScript, "#!/bin/sh\n", !IO),
-        io.write_string(ShellScript, "CLASSPATH=" ++ ClassPath ++ " ", !IO),
-        io.write_string(ShellScript, Java ++ " ", !IO),
-        io.write_string(ShellScript, Name_No_Extn ++ "\n", !IO),
-        io.close_output(ShellScript, !IO),
-        io.call_system("chmod a+x " ++ FileName, ChmodResult, !IO),
-        (
-            ChmodResult = ok(Status),
-            ( Status = 0 ->
-                Succeeded = yes,
-                maybe_write_string(Verbose, "% done.\n", !IO)
-            ;
-                unexpected(this_file, "chmod exit status != 0"),
-                Succeeded = no
-            )
-        ;
-            ChmodResult = error(Message),
-            unexpected(this_file, io.error_message(Message)),
-            Succeeded = no
-        )
-    ;
-        OpenResult = error(Message),
-        unexpected(this_file, io.error_message(Message)),
-        Succeeded = no
-    ).
-
-list_class_files_for_jar(ModuleName, ClassFiles, ListClassFiles, !IO) :-
-    globals.io_lookup_bool_option(use_subdirs, UseSubdirs, !IO),
-    globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
-    AnySubdirs = UseSubdirs `or` UseGradeSubdirs,
-    (
-        AnySubdirs = yes,
-        module_name_to_file_name(ModuleName, ".class", no, ClassFile, !IO),
-        ClassSubdir = dir.dirname(ClassFile),
-        % Here we use the `-C' option of jar to change directory during
-        % execution, then use sed to strip away the Mercury/classs/
-        % prefix to the class files.
-        % Otherwise, the class files would be stored as
-        %   Mercury/classs/*.class
-        % within the jar file, which is not what we want.
-        % XXX It would be nice to avoid this dependency on sed.
-        ListClassFiles = "-C " ++ ClassSubdir ++ " \\\n" ++
-            "\t\t`echo "" " ++ ClassFiles ++ """" ++
-            " | sed 's| '" ++ ClassSubdir ++ "/| |'`"
-    ;
-        AnySubdirs = no,
-        ListClassFiles = ClassFiles
-    ).
-
-get_env_classpath(Classpath, !IO) :-
-    io.get_environment_var("CLASSPATH", MaybeCP, !IO),
-    (
-        MaybeCP = yes(Classpath)
-    ;
-        MaybeCP = no,
-        io.get_environment_var("java.class.path", MaybeJCP, !IO),
-        (
-            MaybeJCP = yes(Classpath)
-        ;
-            MaybeJCP = no,
-            Classpath = ""
-        )
-    ).
-
-%-----------------------------------------------------------------------------%
-%
-% Erlang utilities
-%
-
-erlang_module_name(ModuleName) =
-    (if mercury_std_library_module_name(ModuleName) then
-        add_outermost_qualifier("mercury", ModuleName)
-    else
-        ModuleName
-    ).
-
-create_erlang_shell_script(MainModuleName, Succeeded, !IO) :-
-    Extension = "",
-    module_name_to_file_name(MainModuleName, Extension, no, ScriptFileName,
-        !IO),
-    globals.io_get_globals(Globals, !IO),
-    grade_directory_component(Globals, GradeDir),
-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    maybe_write_string(Verbose, "% Generating shell script `" ++
-        ScriptFileName ++ "'...\n", !IO),
-
-    globals.io_lookup_string_option(erlang_object_file_extension, BeamExt,
-        !IO),
-    module_name_to_file_name(MainModuleName, BeamExt, no, BeamFileName, !IO),
-    BeamDirName = dir.dirname(BeamFileName),
-    module_name_to_file_name(MainModuleName, BeamBaseNameNoExt),
-
-    % Add `-pa <dir>' option to find the standard library.
-    % (-pa adds the directory to the beginning of the list of paths to search
-    % for .beam files)
-    globals.io_lookup_maybe_string_option(
-        mercury_standard_library_directory, MaybeStdLibDir, !IO),
-    (
-        MaybeStdLibDir = yes(StdLibDir),
-        StdLibBeamsPath = StdLibDir/"lib"/GradeDir/"libmer_std.beams",
-        SearchStdLib = pa_option(yes, StdLibBeamsPath),
-        % Added by elds_to_erlang.m
-        MainFunc = "mercury__main_wrapper"
-    ;
-        MaybeStdLibDir = no,
-        SearchStdLib = "",
-        MainFunc = "main_2_p_0"
-    ),
-
-    % Add `-pa <dir>' options to find any other libraries specified by the user.
-    globals.io_lookup_accumulating_option(
-        mercury_library_directories, MercuryLibDirs0, !IO),
-    MercuryLibDirs = list.map((func(LibDir) = LibDir/"lib"/GradeDir),
-        MercuryLibDirs0),
-    globals.io_lookup_accumulating_option(link_libraries,
-        LinkLibrariesList0, !IO),
-    list.map_foldl2(find_erlang_library_path(MercuryLibDirs),
-        LinkLibrariesList0, LinkLibrariesList, yes, LibrariesSucceeded,
-        !IO),
-    (
-        LibrariesSucceeded = yes,
-        % Remove symlink in the way, if any.
-        io.remove_file(ScriptFileName, _, !IO),
-        io.open_output(ScriptFileName, OpenResult, !IO),
-        (
-            OpenResult = ok(ShellScript),
-
-            globals.io_lookup_string_option(erlang_interpreter, Erlang, !IO),
-            SearchLibs = string.append_list(list.map(pa_option(yes),
-                list.sort_and_remove_dups(LinkLibrariesList))),
-
-            % XXX main_2_p_0 is not necessarily in the main module itself and
-            % could be in a submodule.  We don't handle that yet.
-            SearchProg = pa_option(no, """$DIR""/" ++ quote_arg(BeamDirName)),
-
-            % Write the shell script.
-            % Note we need to use '-extra' instead of '--' for "-flag" and
-            % "+flag" arguments to be pass through to the Mercury program.
-            io.write_strings(ShellScript, [
-                "#!/bin/sh\n",
-                "# Generated by the Mercury compiler.\n",
-                "DIR=`dirname ""$0""`\n",
-                "exec ", Erlang, " -noshell \\\n",
-                SearchStdLib, SearchLibs, SearchProg,
-                " -s ", BeamBaseNameNoExt, " ", MainFunc,
-                " -s init stop -extra ""$@""\n"
-            ], !IO),
-            io.close_output(ShellScript, !IO),
-
-            % Set executable bit.
-            io.call_system("chmod a+x " ++ ScriptFileName, ChmodResult, !IO),
-            (
-                ChmodResult = ok(Status),
-                ( Status = 0 ->
-                    Succeeded = yes,
-                    maybe_write_string(Verbose, "% done.\n", !IO)
-                ;
-                    unexpected(this_file, "chmod exit status != 0"),
-                    Succeeded = no
-                )
-            ;
-                ChmodResult = error(Message),
-                unexpected(this_file, io.error_message(Message)),
-                Succeeded = no
-            )
-        ;
-            OpenResult = error(Message),
-            unexpected(this_file, io.error_message(Message)),
-            Succeeded = no
-        )
-    ;
-        LibrariesSucceeded = no,
-        Succeeded = no
-    ).
-
-:- pred find_erlang_library_path(list(dir_name)::in, string::in, string::out,
-    bool::in, bool::out, io::di, io::uo) is det.
-
-find_erlang_library_path(MercuryLibDirs, LibName, LibPath, !Succeeded, !IO) :-
-    globals.io_lookup_bool_option(use_grade_subdirs, UseGradeSubdirs, !IO),
-    file_name_to_module_name(LibName, LibModuleName),
-    globals.io_set_option(use_grade_subdirs, bool(no), !IO),
-    module_name_to_lib_file_name("lib", LibModuleName, ".beams", no,
-        LibFileName, !IO),
-    globals.io_set_option(use_grade_subdirs, bool(UseGradeSubdirs), !IO),
-
-    io.input_stream(InputStream, !IO),
-    search_for_file_returning_dir(MercuryLibDirs, LibFileName,
-        SearchResult, !IO),
-    (
-        SearchResult = ok(DirName),
-        LibPath = DirName/LibFileName,
-        io.set_input_stream(InputStream, LibInputStream, !IO),
-        io.close_input(LibInputStream, !IO)
-    ;
-        SearchResult = error(Error),
-        LibPath = "",
-        write_error_pieces_maybe_with_context(no, 0, [words(Error)], !IO),
-        !:Succeeded = no
-    ).
-
-:- func pa_option(bool, dir_name) = string.
-
-pa_option(Quote, Dir0) = " -pa " ++ Dir ++ " \\\n" :-
-    (
-        Quote = yes,
-        Dir = quote_arg(Dir0)
-    ;
-        Quote = no,
-        Dir = Dir0
-    ).
-
-%-----------------------------------------------------------------------------%
-
-% Changes to the following predicate may require similar changes to
-% make.program_target.install_library_grade_files/9.
-
-get_install_name_option(OutputFileName, InstallNameOpt, !IO) :-
-    globals.io_get_globals(Globals, !IO),
-    globals.lookup_string_option(Globals, shlib_linker_install_name_flag,
-        InstallNameFlag),
-    globals.lookup_string_option(Globals, shlib_linker_install_name_path,
-        InstallNamePath0),
-    ( InstallNamePath0 = "" ->
-        globals.lookup_string_option(Globals, install_prefix, InstallPrefix),
-        grade_directory_component(Globals, GradeDir),
-        InstallNamePath = InstallPrefix / "lib" / "mercury" / "lib" / GradeDir
-    ;
-        InstallNamePath = InstallNamePath0
-    ),
-    InstallNameOpt = InstallNameFlag ++ InstallNamePath / OutputFileName.
-
 %-----------------------------------------------------------------------------%
 
 :- func this_file = string.
Index: compiler/optimize.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/optimize.m,v
retrieving revision 1.64
diff -u -b -r1.64 optimize.m
--- compiler/optimize.m	23 Nov 2007 07:35:17 -0000	1.64
+++ compiler/optimize.m	18 Jul 2008 10:11:38 -0000
@@ -38,6 +38,7 @@
 :- import_module hlds.code_model.
 :- import_module hlds.hlds_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module ll_backend.continuation_info.
@@ -54,7 +55,6 @@
 :- import_module ll_backend.use_local_vars.
 :- import_module ll_backend.wrap_blocks.
 :- import_module mdbcomp.prim_data.
-:- import_module parse_tree.prog_out.
 
 :- import_module bool.
 :- import_module char.
Index: compiler/parse_tree.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/parse_tree.m,v
retrieving revision 1.17
diff -u -b -r1.17 parse_tree.m
--- compiler/parse_tree.m	19 Jan 2007 07:04:25 -0000	1.17
+++ compiler/parse_tree.m	19 Jul 2008 06:25:30 -0000
@@ -53,10 +53,16 @@
 
 % Transformations that act on the parse tree,
 % and stuff relating to the module system.
+:- include_module deps_map.
 :- include_module equiv_type.
-:- include_module modules.
+:- include_module file_names.
+:- include_module module_cmds.
+:- include_module module_imports.
 :- include_module module_qual.
+:- include_module modules.
+:- include_module read_modules.
 :- include_module source_file_map.
+:- include_module write_deps_file.
 
 % (Note that intermod and trans_opt also contain routines that
 % act on the parse tree, but those modules are considered part
Index: compiler/passes_aux.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/passes_aux.m,v
retrieving revision 1.89
diff -u -b -r1.89 passes_aux.m
--- compiler/passes_aux.m	9 Feb 2007 04:05:17 -0000	1.89
+++ compiler/passes_aux.m	18 Jul 2008 16:21:17 -0000
@@ -23,7 +23,6 @@
 :- import_module parse_tree.error_util.
 :- import_module parse_tree.prog_data.
 
-:- import_module bool.
 :- import_module io.
 :- import_module list.
 :- import_module maybe.
@@ -157,60 +156,6 @@
 :- pred report_pred_name_mode(pred_or_func::in, string::in, list(mer_mode)::in,
     io::di, io::uo) is det.
 
-    % Write to a given filename, giving appropriate status messages
-    % and error messages if the file cannot be opened.
-    %
-:- pred output_to_file(string::in, pred(io, io)::in(pred(di, uo) is det),
-    io::di, io::uo) is det.
-
-    % Same as output_to_file/4 above, but allow the writing predicate
-    % to generate some output.
-    %
-:- pred output_to_file(string::in,
-    pred(T, io, io)::in(pred(out, di, uo) is det),
-    maybe(T)::out, io::di, io::uo) is det.
-
-%-----------------------------------------------------------------------------%
-
-:- type quote_char
-    --->    forward     % '
-    ;       double.     % "
-
-:- type command_verbosity
-    --->    cmd_verbose
-            % Output the command line only with `--verbose'.
-
-    ;       cmd_verbose_commands.
-            % Output the command line with `--verbose-commands'. This should be
-            % used for commands that may be of interest to the user.
-
-    % invoke_system_command(ErrorStream, Verbosity, Command, Succeeded)
-    %
-    % Invoke an executable. Both standard and error output will go to the
-    % specified output stream.
-    %
-:- pred invoke_system_command(io.output_stream::in,
-    command_verbosity::in, string::in, bool::out, io::di, io::uo) is det.
-
-    % invoke_system_command_maybe_filter_output(ErrorStream, Verbosity,
-    %   Command, MaybeProcessOutput, Succeeded)
-    %
-    % Invoke an executable. Both standard and error output will go to the
-    % specified output stream after being piped through `ProcessOutput'
-    % if MaybeProcessOutput is yes(ProcessOutput).
-    %
-:- pred invoke_system_command_maybe_filter_output(io.output_stream::in,
-    command_verbosity::in, string::in, maybe(string)::in, bool::out,
-    io::di, io::uo) is det.
-
-    % Make a command string, which needs to be invoked in a shell environment.
-    %
-:- pred make_command_string(string::in, quote_char::in, string::out) is det.
-
-    % If the bool is `no', set the exit status to 1.
-    %
-:- pred maybe_set_exit_status(bool::in, io::di, io::uo) is det.
-
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
@@ -218,6 +163,7 @@
 
 :- import_module hlds.hlds_out.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module libs.process_util.
@@ -226,6 +172,7 @@
 :- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_util.
 
+:- import_module bool.
 :- import_module int.
 :- import_module map.
 :- import_module string.
@@ -422,203 +369,6 @@
         true
     ).
 
-maybe_set_exit_status(yes, !IO).
-maybe_set_exit_status(no, !IO) :- io.set_exit_status(1, !IO).
-
-invoke_system_command(ErrorStream, Verbosity, Command, Succeeded, !IO) :-
-    invoke_system_command_maybe_filter_output(ErrorStream, Verbosity, Command,
-        no, Succeeded, !IO).
-
-invoke_system_command_maybe_filter_output(ErrorStream, Verbosity, Command,
-        MaybeProcessOutput, Succeeded, !IO) :-
-    % This predicate shouldn't alter the exit status of mercury_compile.
-    io.get_exit_status(OldStatus, !IO),
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    (
-        Verbosity = cmd_verbose,
-        PrintCommand = Verbose
-    ;
-        Verbosity = cmd_verbose_commands,
-        globals.io_lookup_bool_option(verbose_commands, PrintCommand, !IO)
-    ),
-    (
-        PrintCommand = yes,
-        io.write_string("% Invoking system command `", !IO),
-        io.write_string(Command, !IO),
-        io.write_string("'...\n", !IO),
-        io.flush_output(!IO)
-    ;
-        PrintCommand = no
-    ),
-
-    %
-    % The output from the command is written to a temporary file,
-    % which is then written to the output stream. Without this,
-    % the output from the command would go to the current C output
-    % and error streams.
-    %
-    io.make_temp(TmpFile, !IO),
-    ( use_dotnet ->
-        % XXX can't use Bourne shell syntax to redirect on .NET
-        % XXX the output will go to the wrong place!
-        CommandRedirected = Command
-    ; use_win32 ->
-        % On windows we can't in general redirect standard error in the
-        % shell.
-        CommandRedirected = Command ++ " > " ++ TmpFile
-    ;
-        CommandRedirected =
-            string.append_list([Command, " > ", TmpFile, " 2>&1"])
-    ),
-    io.call_system_return_signal(CommandRedirected, Result, !IO),
-    (
-        Result = ok(exited(Status)),
-        maybe_write_string(PrintCommand, "% done.\n", !IO),
-        ( Status = 0 ->
-            CommandSucceeded = yes
-        ;
-            % The command should have produced output describing the error.
-            CommandSucceeded = no
-        )
-    ;
-        Result = ok(signalled(Signal)),
-        % Make sure the current process gets the signal. Some systems (e.g.
-        % Linux) ignore SIGINT during a call to system().
-        raise_signal(Signal, !IO),
-        report_error(ErrorStream, "system command received signal "
-            ++ int_to_string(Signal) ++ ".", !IO),
-        CommandSucceeded = no
-    ;
-        Result = error(Error),
-        report_error(ErrorStream, io.error_message(Error), !IO),
-        CommandSucceeded = no
-    ),
-
-    (
-        % We can't do bash style redirection on .NET.
-        not use_dotnet,
-        MaybeProcessOutput = yes(ProcessOutput)
-    ->
-        io.make_temp(ProcessedTmpFile, !IO),
-        
-        ( use_win32 ->
-            % On windows we can't in general redirect standard
-            % error in the shell.
-            ProcessOutputRedirected = string.append_list(
-                [ProcessOutput, " < ", TmpFile, " > ",
-                    ProcessedTmpFile])
-        ;
-            ProcessOutputRedirected = string.append_list(
-                [ProcessOutput, " < ", TmpFile, " > ",
-                    ProcessedTmpFile, " 2>&1"])
-        ),
-        io.call_system_return_signal(ProcessOutputRedirected,
-            ProcessOutputResult, !IO),
-        io.remove_file(TmpFile, _, !IO),
-        (
-            ProcessOutputResult = ok(exited(ProcessOutputStatus)),
-            maybe_write_string(PrintCommand, "% done.\n", !IO),
-            ( ProcessOutputStatus = 0 ->
-                ProcessOutputSucceeded = yes
-            ;
-                % The command should have produced output
-                % describing the error.
-                ProcessOutputSucceeded = no
-            )
-        ;
-            ProcessOutputResult = ok(signalled(ProcessOutputSignal)),
-            % Make sure the current process gets the signal. Some
-            % systems (e.g. Linux) ignore SIGINT during a call to
-            % system().
-            raise_signal(ProcessOutputSignal, !IO),
-            report_error(ErrorStream, "system command received signal "
-                ++ int_to_string(ProcessOutputSignal) ++ ".", !IO),
-            ProcessOutputSucceeded = no
-        ;
-            ProcessOutputResult = error(ProcessOutputError),
-            report_error(ErrorStream, io.error_message(ProcessOutputError),
-                !IO),
-            ProcessOutputSucceeded = no
-        )
-    ;
-        ProcessOutputSucceeded = yes,
-        ProcessedTmpFile = TmpFile
-    ),
-    Succeeded = CommandSucceeded `and` ProcessOutputSucceeded,
-
-    %
-    % Write the output to the error stream.
-    %
-    io.open_input(ProcessedTmpFile, TmpFileRes, !IO),
-    (
-        TmpFileRes = ok(TmpFileStream),
-        io.input_stream_foldl_io(TmpFileStream, io.write_char(ErrorStream),
-            Res, !IO),
-        (
-            Res = ok
-        ;
-            Res = error(TmpFileReadError),
-            report_error(ErrorStream, "error reading command output: "
-                ++ io.error_message(TmpFileReadError), !IO)
-        ),
-        io.close_input(TmpFileStream, !IO)
-    ;
-        TmpFileRes = error(TmpFileError),
-        report_error(ErrorStream, "error opening command output: "
-                ++ io.error_message(TmpFileError), !IO)
-    ),
-    io.remove_file(ProcessedTmpFile, _, !IO),
-    io.set_exit_status(OldStatus, !IO).
-
-make_command_string(String0, QuoteType, String) :-
-    ( use_win32 ->
-        (
-            QuoteType = forward,
-            Quote = " '"
-        ;
-            QuoteType = double,
-            Quote = " """
-        ),
-        string.append_list(["sh -c ", Quote, String0, Quote], String)
-    ;
-        String = String0
-    ).
-
-    % Are we compiling in a .NET environment?
-    %
-:- pred use_dotnet is semidet.
-:- pragma foreign_proc("C#",
-    use_dotnet,
-    [will_not_call_mercury, promise_pure, thread_safe],
-"
-    SUCCESS_INDICATOR = true;
-").
-% The following clause is only used if there is no matching foreign_proc.
-use_dotnet :- semidet_fail.
-
-    % Are we compiling in a win32 environment?
-    %
-    % If in doubt, use_win32 should succeed.  This is only used to decide
-    % whether to invoke Bourne shell command and shell scripts directly,
-    % or whether to invoke them via `sh -c ...'. The latter should work
-    % correctly in a Unix environment too, but is a little less efficient
-    % since it invokes another process.
-    %
-:- pred use_win32 is semidet.
-:- pragma foreign_proc("C",
-    use_win32,
-    [will_not_call_mercury, promise_pure, thread_safe],
-"
-#ifdef MR_WIN32
-    SUCCESS_INDICATOR = 1;
-#else
-    SUCCESS_INDICATOR = 0;
-#endif
-").
-% The following clause is only used if there is no matching foreign_proc.
-% See comment above for why it is OK to just succeed here.
-use_win32 :- semidet_succeed.
-
 maybe_report_sizes(HLDS, !IO) :-
     globals.io_lookup_bool_option(statistics, Statistics, !IO),
     (
@@ -709,38 +459,6 @@
 
 %-----------------------------------------------------------------------------%
 
-output_to_file(FileName, Action, !IO) :-
-    NewAction = (pred(0::out, di, uo) is det --> Action),
-    output_to_file(FileName, NewAction, _Result, !IO).
-
-output_to_file(FileName, Action, Result, !IO) :-
-    globals.io_lookup_bool_option(verbose, Verbose, !IO),
-    globals.io_lookup_bool_option(statistics, Stats, !IO),
-    maybe_write_string(Verbose, "% Writing to file `", !IO),
-    maybe_write_string(Verbose, FileName, !IO),
-    maybe_write_string(Verbose, "'...\n", !IO),
-    maybe_flush_output(Verbose, !IO),
-    io.open_output(FileName, Res, !IO),
-    (
-        Res = ok(FileStream),
-        io.set_output_stream(FileStream, OutputStream, !IO),
-        Action(ActionResult, !IO),
-        io.set_output_stream(OutputStream, _, !IO),
-        io.close_output(FileStream, !IO),
-        maybe_write_string(Verbose, "% done.\n", !IO),
-        maybe_report_stats(Stats, !IO),
-        Result = yes(ActionResult)
-    ;
-        Res = error(_),
-        maybe_write_string(Verbose, "\n", !IO),
-        string.append_list(["can't open file `", FileName, "' for output."],
-            ErrorMessage),
-        report_error(ErrorMessage, !IO),
-        Result = no
-    ).
-
-%-----------------------------------------------------------------------------%
-
 :- func this_file = string.
 
 this_file = "passes_aux.m".
Index: compiler/proc_gen.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/proc_gen.m,v
retrieving revision 1.26
diff -u -b -r1.26 proc_gen.m
--- compiler/proc_gen.m	2 Jun 2008 02:33:35 -0000	1.26
+++ compiler/proc_gen.m	18 Jul 2008 16:39:50 -0000
@@ -83,6 +83,7 @@
 :- import_module hlds.hlds_rtti.
 :- import_module hlds.instmap.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module libs.trace_params.
Index: compiler/prog_foreign.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_foreign.m,v
retrieving revision 1.15
diff -u -b -r1.15 prog_foreign.m
--- compiler/prog_foreign.m	15 Feb 2008 02:26:57 -0000	1.15
+++ compiler/prog_foreign.m	18 Jul 2008 07:59:30 -0000
@@ -186,7 +186,7 @@
 
 :- implementation.
 
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 
 :- import_module char.
 :- import_module int.
Index: compiler/prog_io.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_io.m,v
retrieving revision 1.291
diff -u -b -r1.291 prog_io.m
--- compiler/prog_io.m	16 Jul 2008 03:30:30 -0000	1.291
+++ compiler/prog_io.m	18 Jul 2008 15:00:11 -0000
@@ -56,6 +56,7 @@
 :- module parse_tree.prog_io.
 :- interface.
 
+:- import_module libs.file_util.
 :- import_module libs.timestamp.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
@@ -63,7 +64,6 @@
 :- import_module parse_tree.prog_item.
 :- import_module parse_tree.prog_io_util.
 
-:- import_module bool.
 :- import_module io.
 :- import_module list.
 :- import_module maybe.
@@ -74,20 +74,15 @@
 
 % This module (prog_io) exports the following predicates:
 
-:- type file_name == string.
-:- type dir_name == string.
-
-    % Open a source or interface file, returning `ok(FileInfo)' on success
-    % (where FileInfo is information about the file such as the file name
-    % or the directory in which it was found), or `error(Message)' on failure.
-:- type open_file(FileInfo) == pred(maybe_error(FileInfo), io, io).
-:- inst open_file == (pred(out, di, uo) is det).
-
 :- type module_error
     --->    no_module_errors        % no errors
     ;       some_module_errors      % some syntax errors
     ;       fatal_module_errors.    % couldn't open the file
 
+:- type maybe_return_timestamp
+    --->    do_return_timestamp
+    ;       do_not_return_timestamp.
+
     % read_module(OpenFile, FileName, DefaultModuleName, ReturnTimestamp,
     %   MaybeFileInfo, ActualModuleName, Program, Specs, Error,
     %   MaybeModuleTimestamp, !IO):
@@ -104,9 +99,9 @@
     % Specs is a list of warning/error messages. Program is the parse tree.
     %
 :- pred read_module(open_file(FileInfo)::in(open_file),
-    module_name::in, bool::in, maybe(FileInfo)::out, module_name::out,
-    list(item)::out, list(error_spec)::out, module_error::out,
-    maybe(io.res(timestamp))::out, io::di, io::uo) is det.
+    module_name::in, maybe_return_timestamp::in, maybe(FileInfo)::out,
+    module_name::out, list(item)::out, list(error_spec)::out,
+    module_error::out, maybe(io.res(timestamp))::out, io::di, io::uo) is det.
 
 :- pred read_module_if_changed(open_file(FileInfo)::in(open_file),
     module_name::in, timestamp::in, maybe(FileInfo)::out, module_name::out,
@@ -129,22 +124,6 @@
 :- pred check_module_has_expected_name(file_name::in, module_name::in,
     module_name::in, io::di, io::uo) is det.
 
-    % search_for_file(Dirs, FileName, FoundFileName, !IO):
-    %
-    % Search Dirs for FileName, opening the file if it is found,
-    % and returning the path name of the file that was found.
-    %
-:- pred search_for_file(list(dir_name)::in, file_name::in,
-    maybe_error(file_name)::out, io::di, io::uo) is det.
-
-    % search_for_file_returning_dir(Dirs, FileName, FoundDirName, !IO):
-    %
-    % Search Dirs for FileName, opening the file if it is found, and returning
-    % the name of the directory in which the file was found.
-    %
-:- pred search_for_file_returning_dir(list(dir_name)::in, file_name::in,
-    maybe_error(dir_name)::out, io::di, io::uo) is det.
-
     % search_for_module_source(Dirs, InterfaceDirs, ModuleName,
     %   FoundSourceFileName, !IO):
     %
@@ -287,7 +266,7 @@
 :- import_module libs.compiler_util.
 :- import_module libs.globals.
 :- import_module libs.options.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_io_dcg.
 :- import_module parse_tree.prog_io_goal.
@@ -302,6 +281,7 @@
 :- import_module recompilation.version.
 
 :- import_module assoc_list.
+:- import_module bool.
 :- import_module dir.
 :- import_module int.
 :- import_module map.
@@ -314,19 +294,21 @@
 
 %-----------------------------------------------------------------------------%
 
-read_module(OpenFile, DefaultModuleName, ReturnTimestamp, FileData, ModuleName,
-        Items, Specs, Error, MaybeModuleTimestamp, !IO) :-
+read_module(OpenFile, DefaultModuleName, ReturnTimestamp, FileData,
+        ModuleName, Items, Specs, Error, MaybeModuleTimestamp, !IO) :-
     read_module_2(OpenFile, DefaultModuleName, no, ReturnTimestamp,
         FileData, ModuleName, Items, Specs, Error, MaybeModuleTimestamp, !IO).
 
-read_module_if_changed(OpenFile, DefaultModuleName, OldTimestamp, FileData, ModuleName, Items, Specs, Error, MaybeModuleTimestamp, !IO) :-
-    read_module_2(OpenFile, DefaultModuleName, yes(OldTimestamp), yes,
+read_module_if_changed(OpenFile, DefaultModuleName, OldTimestamp, FileData,
+        ModuleName, Items, Specs, Error, MaybeModuleTimestamp, !IO) :-
+    read_module_2(OpenFile, DefaultModuleName, yes(OldTimestamp),
+        do_return_timestamp,
         FileData, ModuleName, Items, Specs, Error,MaybeModuleTimestamp, !IO).
 
 read_opt_file(FileName, DefaultModuleName, Items, Specs, Error, !IO) :-
     globals.io_lookup_accumulating_option(intermod_directories, Dirs, !IO),
-    read_module_2(search_for_file(Dirs, FileName), DefaultModuleName, no, no,
-        _, ModuleName, Items, Specs, Error, _, !IO),
+    read_module_2(search_for_file(Dirs, FileName), DefaultModuleName, no,
+        do_not_return_timestamp, _, ModuleName, Items, Specs, Error, _, !IO),
     check_module_has_expected_name(FileName, DefaultModuleName, ModuleName,
         !IO).
 
@@ -350,9 +332,9 @@
     % late-input modes.)
     %
 :- pred read_module_2(open_file(T)::in(open_file), module_name::in,
-    maybe(timestamp)::in, bool::in, maybe(T)::out, module_name::out,
-    list(item)::out, list(error_spec)::out, module_error::out,
-    maybe(io.res(timestamp))::out, io::di, io::uo) is det.
+    maybe(timestamp)::in, maybe_return_timestamp::in, maybe(T)::out,
+    module_name::out, list(item)::out, list(error_spec)::out,
+    module_error::out, maybe(io.res(timestamp))::out, io::di, io::uo) is det.
 
 read_module_2(OpenFile, DefaultModuleName, MaybeOldTimestamp, ReturnTimestamp,
         MaybeFileData, ModuleName, Items, Specs, Error,
@@ -363,7 +345,7 @@
         OpenResult = ok(FileData),
         MaybeFileData = yes(FileData),
         (
-            ReturnTimestamp = yes,
+            ReturnTimestamp = do_return_timestamp,
             io.input_stream_name(InputStreamName, !IO),
             io.file_modification_time(InputStreamName, TimestampResult, !IO),
             (
@@ -374,7 +356,7 @@
                 MaybeModuleTimestamp = yes(error(IOError))
             )
         ;
-            ReturnTimestamp = no,
+            ReturnTimestamp = do_not_return_timestamp,
             MaybeModuleTimestamp = no
         ),
         (
@@ -411,52 +393,6 @@
         Error = fatal_module_errors
     ).
 
-search_for_file(Dirs, FileName, Result, !IO) :-
-    search_for_file_returning_dir(Dirs, FileName, Result0, !IO),
-    (
-        Result0 = ok(Dir),
-        ( dir.this_directory(Dir) ->
-            PathName = FileName
-        ;
-            PathName = dir.make_path_name(Dir, FileName)
-        ),
-        Result = ok(PathName)
-    ;
-        Result0 = error(Message),
-        Result = error(Message)
-    ).
-
-search_for_file_returning_dir(Dirs, FileName, Result, !IO) :-
-    search_for_file_returning_dir_2(Dirs, FileName, MaybeDir, !IO),
-    (
-        MaybeDir = yes(Dir),
-        Result = ok(Dir)
-    ;
-        MaybeDir = no,
-        Msg = "cannot find `" ++ FileName ++ "' in directories " ++
-            string.join_list(", ", Dirs),
-        Result = error(Msg)
-    ).
-
-:- pred search_for_file_returning_dir_2(list(dir_name)::in,
-    file_name::in, maybe(dir_name)::out, io::di, io::uo) is det.
-
-search_for_file_returning_dir_2([], _FileName, no, !IO).
-search_for_file_returning_dir_2([Dir | Dirs], FileName, MaybeDir, !IO) :-
-    ( dir.this_directory(Dir) ->
-        ThisFileName = FileName
-    ;
-        ThisFileName = dir.make_path_name(Dir, FileName)
-    ),
-    io.see(ThisFileName, SeeResult0, !IO),
-    (
-        SeeResult0 = ok,
-        MaybeDir = yes(Dir)
-    ;
-        SeeResult0 = error(_),
-        search_for_file_returning_dir_2(Dirs, FileName, MaybeDir, !IO)
-    ).
-
 search_for_module_source(Dirs, InterfaceDirs,
         ModuleName, MaybeFileName, !IO) :-
     search_for_module_source_2(Dirs, ModuleName, ModuleName,
@@ -496,7 +432,8 @@
                 MaybeFileName = error(find_source_error(ModuleName,
                                     Dirs, yes(SourceFileName2)))
             ;
-                module_name_to_file_name(ModuleName, ".int", no, IntFile, !IO),
+                module_name_to_file_name(ModuleName, ".int",
+                    do_not_create_dirs, IntFile, !IO),
                 search_for_file_returning_dir(InterfaceDirs, IntFile,
                     MaybeIntDir, !IO),
                 ( MaybeIntDir = ok(_) ->
@@ -543,16 +480,15 @@
     module_name::in, maybe_error(file_name)::out, io::di, io::uo) is det.
 
 search_for_module_source_2(Dirs, ModuleName, PartialModuleName, Result, !IO) :-
-    module_name_to_file_name(PartialModuleName, ".m", no, FileName, !IO),
+    module_name_to_file_name(PartialModuleName, ".m", do_not_create_dirs,
+        FileName, !IO),
     search_for_file(Dirs, FileName, Result0, !IO),
     (
         Result0 = ok(_),
         Result = Result0
     ;
         Result0 = error(_),
-        (
-            PartialModuleName1 = drop_one_qualifier(PartialModuleName)
-        ->
+        ( PartialModuleName1 = drop_one_qualifier(PartialModuleName) ->
             search_for_module_source_2(Dirs, ModuleName, PartialModuleName1,
                 Result, !IO)
         ;
@@ -974,7 +910,7 @@
             !:Items = [Item | !.Items]
         ; ModuleDefn = md_end_module(NestedModuleName) ->
             root_module_name(RootModuleName),
-            sym_name_get_module_name(NestedModuleName, RootModuleName,
+            sym_name_get_module_name_default(NestedModuleName, RootModuleName,
                 ParentModuleName),
             !:ModuleName = ParentModuleName,
             !:Items = [Item | !.Items]
@@ -1333,7 +1269,7 @@
     % of the previous default module name.
 
     root_module_name(RootModuleName),
-    sym_name_get_module_name(DefaultModuleName, RootModuleName,
+    sym_name_get_module_name_default(DefaultModuleName, RootModuleName,
         ParentOfDefaultModuleName),
     parse_module_name(ParentOfDefaultModuleName, VarSet, ModuleName, Result0),
     (
Index: compiler/prog_io_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_io_util.m,v
retrieving revision 1.61
diff -u -b -r1.61 prog_io_util.m
--- compiler/prog_io_util.m	16 Jul 2008 03:30:30 -0000	1.61
+++ compiler/prog_io_util.m	18 Jul 2008 15:00:22 -0000
@@ -676,7 +676,7 @@
         sym_name_and_args(Term, QualifiedName, Args1),
         (
             BuiltinModule = mercury_public_builtin_module,
-            sym_name_get_module_name(QualifiedName, unqualified(""),
+            sym_name_get_module_name_default(QualifiedName, unqualified(""),
                 BuiltinModule),
             % If the term is qualified with the `builtin' module
             % then it may be one of the simple builtin insts.
Index: compiler/prog_item.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_item.m,v
retrieving revision 1.34
diff -u -b -r1.34 prog_item.m
--- compiler/prog_item.m	16 Jul 2008 03:30:30 -0000	1.34
+++ compiler/prog_item.m	19 Jul 2008 05:18:09 -0000
@@ -879,10 +879,29 @@
             % interface file for use in smart recompilation.
 
 %-----------------------------------------------------------------------------%
+
+:- type contains_foreign_code
+    --->    contains_foreign_code(set(foreign_language))
+    ;       contains_no_foreign_code
+    ;       contains_foreign_code_unknown.
+
+:- type contains_foreign_export
+    --->    contains_foreign_export
+    ;       contains_no_foreign_export.
+
+:- pred get_item_list_foreign_code(globals::in, list(item)::in,
+    set(foreign_language)::out, foreign_import_module_info_list::out,
+    contains_foreign_export::out) is det.
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
 
+:- import_module parse_tree.prog_foreign.
+
+:- import_module map.
+
 %-----------------------------------------------------------------------------%
 
 get_item_context(Item) = Context :-
@@ -982,4 +1001,127 @@
     !:Attributes = !.Attributes ^ mutable_thread_local := ThreadLocal.
 
 %-----------------------------------------------------------------------------%
+
+:- type module_foreign_info
+    --->    module_foreign_info(
+                used_foreign_languages      :: set(foreign_language),
+                foreign_proc_languages      :: map(sym_name, foreign_language),
+                all_foreign_import_modules  :: foreign_import_module_info_list,
+                module_has_foreign_export   :: contains_foreign_export
+            ).
+
+get_item_list_foreign_code(Globals, Items, LangSet, ForeignImports,
+        ContainsPragmaExport) :-
+    Info0 = module_foreign_info(set.init, map.init, [],
+        contains_no_foreign_export),
+    list.foldl(get_item_foreign_code(Globals), Items, Info0, Info),
+    Info = module_foreign_info(LangSet0, LangMap, ForeignImports,
+        ContainsPragmaExport),
+    ForeignProcLangs = map.values(LangMap),
+    LangSet = set.insert_list(LangSet0, ForeignProcLangs).
+
+:- pred get_item_foreign_code(globals::in, item::in,
+    module_foreign_info::in, module_foreign_info::out) is det.
+
+get_item_foreign_code(Globals, Item, !Info) :-
+    ( Item = item_pragma(ItemPragma) ->
+        ItemPragma = item_pragma_info(_, Pragma, Context),
+        do_get_item_foreign_code(Globals, Pragma, Context, !Info)
+    ; Item = item_mutable(_) ->
+        % Mutables introduce foreign_procs, but mutable declarations
+        % won't have been expanded by the time we get here so we need
+        % to handle them separately.
+        % XXX mutables are currently only implemented for the C backends
+        % but we should handle the Java/IL backends here as well.
+        % (See do_get_item_foreign_code for details/5).
+        !:Info = !.Info ^ used_foreign_languages :=
+            set.insert(!.Info ^ used_foreign_languages, lang_c)
+    ; ( Item = item_initialise(_) ; Item = item_finalise(_) ) ->
+        % Intialise/finalise declarations introduce export pragmas, but
+        % again they won't have been expanded by the time we get here.
+        % XXX we don't currently support these on non-C backends.
+        !:Info = !.Info ^ used_foreign_languages :=
+            set.insert(!.Info ^ used_foreign_languages, lang_c),
+        !:Info = !.Info ^ module_has_foreign_export := contains_foreign_export
+    ;
+        true
+    ).
+
+:- pred do_get_item_foreign_code(globals::in, pragma_type::in,
+    prog_context::in, module_foreign_info::in, module_foreign_info::out)
+    is det.
+
+do_get_item_foreign_code(Globals, Pragma, Context, Info0, Info) :-
+    globals.get_backend_foreign_languages(Globals, BackendLangs),
+    globals.get_target(Globals, Target),
+
+    % The code here should match the way that mlds_to_gcc.m decides whether
+    % or not to call mlds_to_c.m.  XXX Note that we do NOT count foreign_decls
+    % here. We only link in a foreign object file if mlds_to_gcc called
+    % mlds_to_c.m to generate it, which it will only do if there is some
+    % foreign_code, not just foreign_decls. Counting foreign_decls here
+    % causes problems with intermodule optimization.
+    (
+        Pragma = pragma_foreign_code(Lang, _),
+        list.member(Lang, BackendLangs)
+    ->
+        Info = Info0 ^ used_foreign_languages :=
+            set.insert(Info0 ^ used_foreign_languages, Lang)
+    ;
+        Pragma = pragma_foreign_proc(Attrs, Name, _, _, _, _, _)
+    ->
+        NewLang = get_foreign_language(Attrs),
+        ( OldLang = Info0 ^ foreign_proc_languages ^ elem(Name) ->
+            % is it better than an existing one?
+            (
+                yes = prefer_foreign_language(Globals, Target,
+                    OldLang, NewLang)
+            ->
+                Info = Info0 ^ foreign_proc_languages ^ elem(Name) := NewLang
+            ;
+                Info = Info0
+            )
+        ;
+            % is it one of the languages we support?
+            ( list.member(NewLang, BackendLangs) ->
+                Info = Info0 ^ foreign_proc_languages ^ elem(Name) := NewLang
+            ;
+                Info = Info0
+            )
+        )
+    ;
+        % XXX `pragma export' should not be treated as foreign, but currently
+        % mlds_to_gcc.m doesn't handle that declaration, and instead just
+        % punts it on to mlds_to_c.m, thus generating C code for it,
+        % rather than assembler code. So we need to treat `pragma export'
+        % like the other pragmas for foreign code.
+        Pragma = pragma_foreign_export(Lang, _, _, _, _),
+        list.member(Lang, BackendLangs)
+    ->
+        Info1 = Info0 ^ used_foreign_languages :=
+            set.insert(Info0 ^ used_foreign_languages, Lang),
+        Info = Info1 ^ module_has_foreign_export :=
+            contains_foreign_export
+    ;
+        Pragma = pragma_foreign_import_module(Lang, Import),
+        list.member(Lang, BackendLangs)
+    ->
+        Info = Info0 ^ all_foreign_import_modules :=
+            [foreign_import_module_info(Lang, Import, Context) |
+                Info0 ^ all_foreign_import_modules]
+    ;
+        % We generate some C code for fact tables, so we need to treat modules
+        % containing fact tables as if they contain foreign code.
+        ( Target = target_asm
+        ; Target = target_c
+        ),
+        Pragma = pragma_fact_table(_, _, _)
+    ->
+        Info = Info0 ^ used_foreign_languages :=
+            set.insert(Info0 ^ used_foreign_languages, lang_c)
+    ;
+        Info = Info0
+    ).
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
Index: compiler/prog_mutable.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_mutable.m,v
retrieving revision 1.24
diff -u -b -r1.24 prog_mutable.m
--- compiler/prog_mutable.m	15 Feb 2008 02:26:58 -0000	1.24
+++ compiler/prog_mutable.m	18 Jul 2008 08:00:38 -0000
@@ -418,7 +418,7 @@
 
 :- implementation.
 
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_foreign.
 :- import_module parse_tree.prog_mode.
 :- import_module parse_tree.prog_type.
Index: compiler/prog_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_out.m,v
retrieving revision 1.84
diff -u -b -r1.84 prog_out.m
--- compiler/prog_out.m	16 Jul 2008 03:30:31 -0000	1.84
+++ compiler/prog_out.m	18 Jul 2008 09:33:31 -0000
@@ -23,18 +23,10 @@
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.prog_data.
 
-:- import_module bool.
 :- import_module io.
 :- import_module list.
 :- import_module maybe.
 
-:- pred maybe_report_stats(bool::in, io::di, io::uo) is det.
-:- pred maybe_write_string(bool::in, string::in, io::di, io::uo) is det.
-:- pred maybe_flush_output(bool::in, io::di, io::uo) is det.
-
-:- pred report_error(string::in, io::di, io::uo) is det.
-:- pred report_error(io.output_stream::in, string::in, io::di, io::uo) is det.
-
     % Write out the information in term context (at the moment, just
     % the line number) in a form suitable for the beginning of an
     % error message.
@@ -165,31 +157,6 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-maybe_report_stats(yes, !IO) :-
-    io.report_stats(!IO).
-maybe_report_stats(no, !IO).
-
-maybe_write_string(yes, String, !IO) :-
-    io.write_string(String, !IO).
-maybe_write_string(no, _, !IO).
-
-maybe_flush_output(yes, !IO) :-
-    io.flush_output(!IO).
-maybe_flush_output(no, !IO).
-
-report_error(ErrorMessage, !IO) :-
-    io.write_string("Error: ", !IO),
-    io.write_string(ErrorMessage, !IO),
-    io.write_string("\n", !IO),
-    io.set_exit_status(1, !IO).
-
-report_error(Stream, ErrorMessage, !IO) :-
-    io.set_output_stream(Stream, OldStream, !IO),
-    report_error(ErrorMessage, !IO),
-    io.set_output_stream(OldStream, _, !IO).
-
-%-----------------------------------------------------------------------------%
-
 write_context(Context, !IO) :-
     context_to_string(Context, ContextMessage),
     io.write_string(ContextMessage, !IO).
Index: compiler/prog_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/prog_util.m,v
retrieving revision 1.105
diff -u -b -r1.105 prog_util.m
--- compiler/prog_util.m	28 May 2008 00:52:29 -0000	1.105
+++ compiler/prog_util.m	18 Jul 2008 14:48:57 -0000
@@ -28,70 +28,6 @@
 
 %-----------------------------------------------------------------------------%
 
-    % Given a symbol name, return its unqualified name.
-    %
-:- func unqualify_name(sym_name) = string.
-
-    % sym_name_get_module_name(SymName) = ModName:
-    %
-    % Given a symbol name, return the module qualifiers(s).
-    % Fails if the symbol is unqualified.
-    %
-:- pred sym_name_get_module_name(sym_name::in, module_name::out) is semidet.
-
-    % sym_name_get_module_name(SymName, DefaultModName, ModName):
-    %
-    % Given a symbol name, return the module qualifier(s).
-    % If the symbol is unqualified, then return the specified default
-    % module name.
-    %
-:- pred sym_name_get_module_name(sym_name::in, module_name::in,
-    module_name::out) is det.
-
-    % match_sym_name(PartialSymName, CompleteSymName):
-    %
-    % Succeeds iff there is some sequence of module qualifiers
-    % which when prefixed to PartialSymName gives CompleteSymName.
-    %
-:- pred match_sym_name(sym_name::in, sym_name::in) is semidet.
-
-    % remove_sym_name_prefix(SymName0, Prefix, SymName)
-    % succeeds iff
-    %   SymName and SymName0 have the same module qualifier
-    %   and the unqualified part of SymName0 has the given prefix
-    %   and the unqualified part of SymName is the unqualified
-    %       part of SymName0 with the prefix removed.
-    %
-:- pred remove_sym_name_prefix(sym_name, string, sym_name).
-:- mode remove_sym_name_prefix(in, in, out) is semidet.
-:- mode remove_sym_name_prefix(out, in, in) is det.
-
-    % remove_sym_name_suffix(SymName0, Suffix, SymName)
-    % succeeds iff
-    %   SymName and SymName0 have the same module qualifier
-    %   and the unqualified part of SymName0 has the given suffix
-    %   and the unqualified part of SymName is the unqualified
-    %       part of SymName0 with the suffix removed.
-    %
-:- pred remove_sym_name_suffix(sym_name::in, string::in, sym_name::out)
-    is semidet.
-
-    % add_sym_name_suffix(SymName0, Suffix, SymName)
-    % succeeds iff
-    %   SymName and SymName0 have the same module qualifier
-    %   and the unqualified part of SymName is the unqualified
-    %       part of SymName0 with the suffix added.
-    %
-:- pred add_sym_name_suffix(sym_name::in, string::in, sym_name::out) is det.
-
-    % transform_sym_base_name(TransformFunc, SymName0) = SymName
-    % succeeds iff
-    %   SymName and SymName0 have the same module qualifier
-    %   and the unqualified part of SymName is the result of applying
-    %   TransformFunc to the unqualified part of SymName0.
-    %
-:- func transform_sym_base_name(func(string) = string, sym_name) = sym_name.
-
     % Given a possible module qualified sym_name and a list of
     % argument types and a context, construct a term. This is
     % used to construct types.
@@ -102,17 +38,6 @@
 :- pred construct_qualified_term(sym_name::in, list(term(T))::in,
     prog_context::in, term(T)::out) is det.
 
-    % Given a sym_name return the top level qualifier of that name.
-    %
-:- func outermost_qualifier(sym_name) = string.
-
-:- func add_outermost_qualifier(string, sym_name) = sym_name.
-
-    % Remove and return the top level qualifier of a sym_name.
-    %
-:- pred strip_outermost_qualifier(sym_name::in,
-    string::out, sym_name::out) is semidet.
-
 %-----------------------------------------------------------------------------%
 
     % adjust_func_arity(PredOrFunc, FuncArity, PredArity).
@@ -295,15 +220,6 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
-unqualify_name(unqualified(Name)) = Name.
-unqualify_name(qualified(_ModuleName, Name)) = Name.
-
-sym_name_get_module_name(unqualified(_), _) :- fail.
-sym_name_get_module_name(qualified(ModuleName, _), ModuleName).
-
-sym_name_get_module_name(unqualified(_), ModuleName, ModuleName).
-sym_name_get_module_name(qualified(ModuleName, _PredName), _, ModuleName).
-
 construct_qualified_term(qualified(Module, Name), Args, Context, Term) :-
     construct_qualified_term(Module, [], Context, ModuleTerm),
     UnqualifiedTerm = term.functor(term.atom(Name), Args, Context),
@@ -316,20 +232,6 @@
     term.context_init(Context),
     construct_qualified_term(SymName, Args, Context, Term).
 
-outermost_qualifier(unqualified(Name)) = Name.
-outermost_qualifier(qualified(Module, _Name)) = outermost_qualifier(Module).
-
-add_outermost_qualifier(Qual, unqualified(Name)) =
-        qualified(unqualified(Qual), Name).
-add_outermost_qualifier(Qual, qualified(Module, Name)) =
-        qualified(add_outermost_qualifier(Qual, Module), Name).
-
-strip_outermost_qualifier(qualified(unqualified(OuterQual), Name),
-        OuterQual, unqualified(Name)).
-strip_outermost_qualifier(qualified(Module @ qualified(_, _), Name),
-        OuterQual, qualified(RemainingQual, Name)) :-
-    strip_outermost_qualifier(Module, OuterQual, RemainingQual).
-
 %-----------------------------------------------------------------------------%
 
 adjust_func_arity(pf_predicate, Arity, Arity).
@@ -553,43 +455,6 @@
 
 %-----------------------------------------------------------------------------%
 
-    % match_sym_name(PartialSymName, CompleteSymName):
-    %
-    % Succeeds iff there is some sequence of module qualifiers
-    % which when prefixed to PartialSymName gives CompleteSymName.
-    %
-match_sym_name(qualified(Module1, Name), qualified(Module2, Name)) :-
-    match_sym_name(Module1, Module2).
-match_sym_name(unqualified(Name), unqualified(Name)).
-match_sym_name(unqualified(Name), qualified(_, Name)).
-
-%-----------------------------------------------------------------------------%
-
-remove_sym_name_prefix(qualified(Module, Name0), Prefix,
-        qualified(Module, Name)) :-
-    string.append(Prefix, Name, Name0).
-remove_sym_name_prefix(unqualified(Name0), Prefix, unqualified(Name)) :-
-    string.append(Prefix, Name, Name0).
-
-remove_sym_name_suffix(qualified(Module, Name0), Suffix,
-        qualified(Module, Name)) :-
-    string.remove_suffix(Name0, Suffix, Name).
-remove_sym_name_suffix(unqualified(Name0), Suffix, unqualified(Name)) :-
-    string.remove_suffix(Name0, Suffix, Name).
-
-add_sym_name_suffix(qualified(Module, Name0), Suffix,
-        qualified(Module, Name)) :-
-    string.append(Name0, Suffix, Name).
-add_sym_name_suffix(unqualified(Name0), Suffix, unqualified(Name)) :-
-    string.append(Name0, Suffix, Name).
-
-transform_sym_base_name(TransformFunc, qualified(Module, Name0)) =
-        qualified(Module, TransformFunc(Name0)).
-transform_sym_base_name(TransformFunc, unqualified(Name0)) =
-        unqualified(TransformFunc(Name0)).
-
-%-----------------------------------------------------------------------------%
-
 make_pred_name_with_context(ModuleName, Prefix,
         PredOrFunc, PredName, Line, Counter, SymName) :-
     make_pred_name(ModuleName, Prefix, yes(PredOrFunc), PredName,
Index: compiler/pseudo_type_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/pseudo_type_info.m,v
retrieving revision 1.30
diff -u -b -r1.30 pseudo_type_info.m
--- compiler/pseudo_type_info.m	23 Nov 2007 07:35:22 -0000	1.30
+++ compiler/pseudo_type_info.m	18 Jul 2008 14:48:57 -0000
@@ -68,7 +68,6 @@
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.prog_type.
-:- import_module parse_tree.prog_util.
 
 :- import_module int.
 :- import_module list.
@@ -107,8 +106,8 @@
         ;
             TypeCtor = type_ctor(QualTypeName, Arity),
             TypeName = unqualify_name(QualTypeName),
-            sym_name_get_module_name(QualTypeName, unqualified("builtin"),
-                TypeModule),
+            sym_name_get_module_name_default(QualTypeName,
+                unqualified("builtin"), TypeModule),
             RttiTypeCtor = rtti_type_ctor(TypeModule, TypeName, Arity),
             generate_pseudo_args(TypeArgs, NumUnivQTvars, ExistQTvars,
                 PseudoArgs),
@@ -171,8 +170,8 @@
         ;
             TypeCtor = type_ctor(QualTypeName, Arity),
             TypeName = unqualify_name(QualTypeName),
-            sym_name_get_module_name(QualTypeName, unqualified("builtin"),
-                TypeModule),
+            sym_name_get_module_name_default(QualTypeName,
+                unqualified("builtin"), TypeModule),
             RttiTypeCtor = rtti_type_ctor(TypeModule, TypeName, Arity),
             generate_plain_args(TypeArgs, TypeInfoArgs),
             expect(check_arity(TypeInfoArgs, Arity),
Index: compiler/purity.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/purity.m,v
retrieving revision 1.120
diff -u -b -r1.120 purity.m
--- compiler/purity.m	16 Jul 2008 03:30:31 -0000	1.120
+++ compiler/purity.m	18 Jul 2008 16:41:38 -0000
@@ -180,6 +180,7 @@
 :- import_module hlds.quantification.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.
Index: compiler/read_modules.m
===================================================================
RCS file: compiler/read_modules.m
diff -N compiler/read_modules.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/read_modules.m	19 Jul 2008 07:12:41 -0000
@@ -0,0 +1,382 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 1996-2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: read_modules.m.
+%
+%-----------------------------------------------------------------------------%
+
+:- module parse_tree.read_modules.
+:- interface.
+
+:- import_module libs.file_util.
+:- import_module libs.timestamp.
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_imports.
+:- import_module parse_tree.prog_item.
+:- import_module parse_tree.prog_io.
+
+:- import_module io.
+:- import_module list.
+:- import_module map.
+:- import_module maybe.
+:- import_module pair.
+
+%-----------------------------------------------------------------------------%
+
+    % recompilation_check.m records each file read to avoid reading it again.
+    % The string is the suffix of the file name.
+    %
+:- type read_modules == map(pair(module_name, string), read_module).
+
+:- type read_module
+    --->    read_module(
+                module_timestamp,
+                list(item),
+                module_error,
+                file_name
+            ).
+
+    % read_module(ModuleName, Extension, Descr, Search, ReturnTimestamp,
+    %       Items, Error, SourceFileName, MaybeTimestamp):
+    %
+    % Given a module name and a file extension (e.g. `.m', `.int', or `int2'),
+    % read in the list of items in that file.
+    %
+    % If Extension is ".m", and ModuleName is a nested module, then try
+    % searching for different filenames: for modules such as `foo.bar.baz.m'
+    % search first for `foo.bar.baz.m', then `bar.baz.m', then `baz.m'.
+    % If Search is do_search, search all directories given by the option
+    % search_directories for the module.
+    % If ReturnTimestamp is do_return_timestamp, attempt to return the
+    % modification time of the file in MaybeTimestamp.
+    % If the actual module name (as determined by the `:- module' declaration)
+    % does not match the specified module name, then report an error message.
+    % Return the actual source file name found (excluding the directory part).
+    %
+    % N.B. This reads a module given the module name. If you want to read
+    % a module given the file name, use `read_module_from_file'.
+    %
+:- pred read_module(module_name::in, string::in, string::in, maybe_search::in,
+    maybe_return_timestamp::in, list(item)::out, module_error::out,
+    file_name::out, maybe(timestamp)::out, io::di, io::uo) is det.
+
+    % read_module_if_changed(ModuleName, Extension, Descr, Search,
+    %   OldTimestamp, Items, Error, SourceFileName, MaybeTimestamp):
+    %
+    % If the timestamp of the file specified by the given module name and
+    % file extension is newer than OldTimestamp, read the file, returning
+    % the new timestamp.
+    %
+    % If the file was read, MaybeTimestamp will contain the new timestamp.
+    % If the timestamp was unchanged, MaybeTimestamp will be
+    % `yes(OldTimestamp)'. If the file could not be read, MaybeTimestamp
+    % will be `no'.
+    %
+:- pred read_module_if_changed(module_name::in, string::in, string::in,
+    maybe_search::in, timestamp::in, list(item)::out, module_error::out,
+    file_name::out, maybe(timestamp)::out, io::di, io::uo) is det.
+
+    % Similar to read_mod, but doesn't return error messages.
+    %
+:- pred read_module_ignore_errors(module_name::in, string::in, string::in,
+    maybe_search::in, maybe_return_timestamp::in, list(item)::out,
+    module_error::out, file_name::out, maybe(timestamp)::out, io::di, io::uo)
+    is det.
+
+    % read_module_from_file(SourceFileName, Extension, Descr, Search,
+    %   ReturnTimestamp, Items, Error, ModuleName, MaybeTimestamp):
+    %
+    % Given a file name and a file extension (e.g. `.m', `.int', or `int2'),
+    % read in the list of items in that file.
+    % If Search is do_search, search all directories given by the option
+    % search_directories for the module.
+    % If ReturnTimestamp is do_return_timestamp, attempt to return the
+    % modification time of the file in MaybeTimestamp. Return the module name
+    % (as determined by the `:- module' declaration, if any).
+    %
+    % N.B.  This reads a module given the file name. If you want to read a
+    % module given the module name, use `read_mod'.
+    %
+:- pred read_module_from_file(file_name::in, string::in, string::in,
+    maybe_search::in, maybe_return_timestamp::in, list(item)::out,
+    module_error::out, module_name::out, maybe(timestamp)::out, io::di, io::uo)
+    is det.
+
+%-----------------------------------------------------------------------------%
+
+:- pred maybe_read_module(read_modules::in, module_name::in, string::in,
+    string::in, maybe_search::in, maybe_return_timestamp::in, list(item)::out,
+    module_error::out, file_name::out, maybe(timestamp)::out, io::di, io::uo)
+    is det.
+
+    % find_read_module(ReadModules, ModuleName, Suffix, ReturnTimestamp,
+    %   Items, MaybeTimestamp, Error, FileName)
+    %
+    % Check whether a file was read during recompilation checking.
+    %
+:- pred find_read_module(read_modules::in, module_name::in, string::in,
+    maybe_return_timestamp::in, list(item)::out, maybe(timestamp)::out,
+    module_error::out, file_name::out) is semidet.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.globals.
+:- import_module libs.options.
+:- import_module parse_tree.error_util.
+
+:- import_module bool.
+:- import_module dir.
+:- import_module getopt_io.
+:- import_module string.
+
+%-----------------------------------------------------------------------------%
+
+:- type maybe_ignore_errors
+    --->    ignore_errors
+    ;       do_not_ignore_errors.
+
+read_module(ModuleName, Extension, Descr, Search, ReturnTimestamp,
+        Items, Error, FileName, MaybeTimestamp, !IO) :-
+    do_read_module(do_not_ignore_errors, ModuleName, Extension, Descr, Search,
+        no, ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO).
+
+read_module_if_changed(ModuleName, Extension, Descr, Search, OldTimestamp,
+        Items, Error, FileName, MaybeTimestamp, !IO) :-
+    do_read_module(do_not_ignore_errors, ModuleName, Extension, Descr, Search,
+        yes(OldTimestamp), do_return_timestamp, Items, Error,
+        FileName, MaybeTimestamp, !IO).
+
+read_module_ignore_errors(ModuleName, Extension, Descr, Search,
+        ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO) :-
+    do_read_module(ignore_errors, ModuleName, Extension, Descr, Search,
+        no, ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO).
+
+:- pred do_read_module(maybe_ignore_errors::in, module_name::in,
+    string::in, string::in, maybe_search::in, maybe(timestamp)::in,
+    maybe_return_timestamp::in, list(item)::out, module_error::out,
+    file_name::out, maybe(timestamp)::out, io::di, io::uo) is det.
+
+do_read_module(IgnoreErrors, ModuleName, Extension, Descr, Search,
+        MaybeOldTimestamp, ReturnTimestamp, Items, Error, FileName,
+        MaybeTimestamp, !IO) :-
+    (
+        Search = do_search,
+        module_name_to_search_file_name(ModuleName, Extension, FileName0, !IO)
+    ;
+        Search = do_not_search,
+        module_name_to_file_name(ModuleName, Extension, do_not_create_dirs,
+            FileName0, !IO)
+    ),
+    globals.io_lookup_bool_option(very_verbose, VeryVerbose, !IO),
+    Msg = "% " ++ Descr ++ " `" ++ FileName0 ++ "'... ",
+    maybe_write_string(VeryVerbose, Msg, !IO),
+    maybe_flush_output(VeryVerbose, !IO),
+
+    globals.io_lookup_accumulating_option(search_directories,
+        InterfaceSearchDirs, !IO),
+    (
+        Search = do_search,
+        SearchDirs = InterfaceSearchDirs
+    ;
+        Search = do_not_search,
+        SearchDirs = [dir.this_directory]
+    ),
+    ( Extension = ".m" ->
+        % For `.m' files we need to deal with the case where the module name
+        % does not match the file name, or where a partial match occurs
+        % in the current directory but the full match occurs in a
+        % search directory.
+
+        OpenFile = search_for_module_source(SearchDirs,
+            InterfaceSearchDirs, ModuleName)
+    ;
+        OpenFile = search_for_file(SearchDirs, FileName0)
+    ),
+    (
+        MaybeOldTimestamp = yes(OldTimestamp),
+        prog_io.read_module_if_changed(OpenFile, ModuleName, OldTimestamp,
+            MaybeFileName, ActualModuleName, Items, Specs, Error,
+            MaybeTimestamp0, !IO)
+    ;
+        MaybeOldTimestamp = no,
+        prog_io.read_module(OpenFile, ModuleName, ReturnTimestamp,
+            MaybeFileName, ActualModuleName, Items, Specs, Error,
+            MaybeTimestamp0, !IO)
+    ),
+
+    (
+        MaybeFileName = yes(FileName)
+    ;
+        MaybeFileName = no,
+        FileName = FileName0
+    ),
+    check_module_has_expected_name(FileName, ModuleName, ActualModuleName,
+        !IO),
+
+    check_timestamp(FileName0, MaybeTimestamp0, MaybeTimestamp, !IO),
+    (
+        IgnoreErrors = ignore_errors,
+        (
+            Error = fatal_module_errors,
+            Items = []
+        ->
+            maybe_write_string(VeryVerbose, "not found.\n", !IO)
+        ;
+            maybe_write_string(VeryVerbose, "done.\n", !IO)
+        )
+    ;
+        IgnoreErrors = do_not_ignore_errors,
+        (
+            Error = fatal_module_errors,
+            maybe_write_string(VeryVerbose, "fatal error(s).\n", !IO),
+            io.set_exit_status(1, !IO)
+        ;
+            Error = some_module_errors,
+            maybe_write_string(VeryVerbose, "parse error(s).\n", !IO),
+            io.set_exit_status(1, !IO)
+        ;
+            Error = no_module_errors,
+            maybe_write_string(VeryVerbose, "successful parse.\n", !IO)
+        ),
+        globals.io_get_globals(Globals, !IO),
+        % XXX _NumWarnings _NumErrors
+        write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO)
+    ).
+
+read_module_from_file(FileName, Extension, Descr, Search, ReturnTimestamp,
+        Items, Error, ModuleName, MaybeTimestamp, !IO) :-
+    globals.io_lookup_bool_option(very_verbose, VeryVerbose, !IO),
+    maybe_write_string(VeryVerbose, "% ", !IO),
+    maybe_write_string(VeryVerbose, Descr, !IO),
+    maybe_write_string(VeryVerbose, " `", !IO),
+    maybe_write_string(VeryVerbose, FileName, !IO),
+    maybe_write_string(VeryVerbose, "'... ", !IO),
+    maybe_flush_output(VeryVerbose, !IO),
+    string.append(FileName, Extension, FullFileName),
+    ( dir.basename(FileName, BaseFileNamePrime) ->
+        BaseFileName = BaseFileNamePrime
+    ;
+        BaseFileName = ""
+    ),
+    file_name_to_module_name(BaseFileName, DefaultModuleName),
+    (
+        Search = do_search,
+        globals.io_lookup_accumulating_option(search_directories,
+            SearchDirs, !IO)
+    ;
+        Search = do_not_search,
+        SearchDirs = [dir.this_directory]
+    ),
+    OpenFile = search_for_file(SearchDirs, FullFileName),
+    prog_io.read_module(OpenFile, DefaultModuleName, ReturnTimestamp,
+        _, ModuleName, Items, Specs, Error, MaybeTimestamp0, !IO),
+    check_timestamp(FullFileName, MaybeTimestamp0, MaybeTimestamp, !IO),
+    (
+        Error = fatal_module_errors,
+        maybe_write_string(VeryVerbose, "fatal error(s).\n", !IO),
+        io.set_exit_status(1, !IO)
+    ;
+        Error = some_module_errors,
+        maybe_write_string(VeryVerbose, "parse error(s).\n", !IO),
+        io.set_exit_status(1, !IO)
+    ;
+        Error = no_module_errors,
+        maybe_write_string(VeryVerbose, "successful parse.\n", !IO)
+    ),
+    globals.io_get_globals(Globals, !IO),
+    % XXX _NumWarnings _NumErrors
+    write_error_specs(Specs, Globals, 0, _NumWarnings, 0, _NumErrors, !IO).
+
+:- pred check_timestamp(file_name::in, maybe(io.res(timestamp))::in,
+    maybe(timestamp)::out, io::di, io::uo) is det.
+
+check_timestamp(FileName, MaybeTimestamp0, MaybeTimestamp, !IO) :-
+    (
+        MaybeTimestamp0 = yes(ok(Timestamp)),
+        MaybeTimestamp = yes(Timestamp)
+    ;
+        MaybeTimestamp0 = yes(error(IOError)),
+        MaybeTimestamp = no,
+        globals.io_lookup_bool_option(smart_recompilation, SmartRecompilation,
+            !IO),
+        (
+            SmartRecompilation = yes,
+            report_modification_time_warning(FileName, IOError, !IO)
+        ;
+            SmartRecompilation = no
+        )
+    ;
+        MaybeTimestamp0 = no,
+        MaybeTimestamp = no
+    ).
+
+%-----------------------------------------------------------------------------%
+
+maybe_read_module(ReadModules, ModuleName, Extension, Descr, Search,
+        ReturnTimestamp, Items, Error, FileName, MaybeTimestamp, !IO) :-
+    (
+        find_read_module(ReadModules, ModuleName, Extension, ReturnTimestamp,
+            ItemsPrime, MaybeTimestampPrime, ErrorPrime, FileNamePrime)
+    ->
+        Error = ErrorPrime,
+        Items = ItemsPrime,
+        MaybeTimestamp = MaybeTimestampPrime,
+        FileName = FileNamePrime
+    ;
+        read_module(ModuleName, Extension, Descr, Search, ReturnTimestamp,
+            Items, Error, FileName, MaybeTimestamp, !IO)
+    ).
+
+find_read_module(ReadModules, ModuleName, Suffix, ReturnTimestamp, Items,
+        MaybeTimestamp, Error, FileName) :-
+    map.search(ReadModules, ModuleName - Suffix, ReadModule),
+    ReadModule = read_module(ModuleTimestamp, Items, Error, FileName),
+    (
+        ReturnTimestamp = do_return_timestamp,
+        ModuleTimestamp = module_timestamp(_, Timestamp, _),
+        MaybeTimestamp = yes(Timestamp)
+    ;
+        ReturnTimestamp = do_not_return_timestamp,
+        MaybeTimestamp = no
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred report_modification_time_warning(file_name::in, io.error::in,
+    io::di, io::uo) is det.
+
+report_modification_time_warning(SourceFileName, Error, !IO) :-
+    globals.io_set_option(smart_recompilation, bool(no), !IO),
+    globals.io_set_option(generate_item_version_numbers, bool(no), !IO),
+    globals.io_lookup_bool_option(warn_smart_recompilation, Warn, !IO),
+    (
+        Warn = yes,
+        io.write_string("Warning: cannot find modification time for ", !IO),
+        io.write_string(SourceFileName, !IO),
+        io.write_string(":\n", !IO),
+        io.error_message(Error, Msg),
+        io.write_string("  ", !IO),
+        io.write_string(Msg, !IO),
+        io.write_string(".\n", !IO),
+        io.write_string("  Smart recompilation will not work.\n", !IO),
+        globals.io_lookup_bool_option(halt_at_warn, HaltAtWarn, !IO),
+        (
+            HaltAtWarn = yes,
+            io.set_exit_status(1, !IO)
+        ;
+            HaltAtWarn = no
+        )
+    ;
+        Warn = no
+    ).
+
+%-----------------------------------------------------------------------------%
Index: compiler/recompilation.check.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/recompilation.check.m,v
retrieving revision 1.43
diff -u -b -r1.43 recompilation.check.m
--- compiler/recompilation.check.m	16 Jul 2008 03:30:31 -0000	1.43
+++ compiler/recompilation.check.m	19 Jul 2008 08:04:09 -0000
@@ -16,9 +16,9 @@
 :- module recompilation.check.
 :- interface.
 
+:- import_module libs.file_util.
 :- import_module mdbcomp.prim_data.
-:- import_module parse_tree.modules.
-:- import_module parse_tree.prog_io.
+:- import_module parse_tree.read_modules.
 
 :- import_module io.
 :- import_module list.
@@ -69,7 +69,11 @@
 :- import_module libs.options.
 :- import_module libs.timestamp.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
+:- import_module parse_tree.module_imports.
 :- import_module parse_tree.prog_item.
+:- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_io_util.
 :- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_util.
@@ -111,7 +115,8 @@
 should_recompile_2(IsSubModule, FindTargetFiles, FindTimestampFiles,
         ModuleName, !Info, !IO) :-
     !:Info = (!.Info ^ module_name := ModuleName) ^ sub_modules := [],
-    module_name_to_file_name(ModuleName, ".used", no, UsageFileName, !IO),
+    module_name_to_file_name(ModuleName, ".used", do_not_create_dirs,
+        UsageFileName, !IO),
     io.open_input(UsageFileName, MaybeVersionStream, !IO),
     (
         MaybeVersionStream = ok(VersionStream0),
@@ -246,7 +251,7 @@
         IsSubModule = no,
         % If the module has changed, recompile.
         ModuleName = !.Info ^ module_name,
-        read_mod_if_changed(ModuleName, ".m", "Reading module", yes,
+        read_module_if_changed(ModuleName, ".m", "Reading module", do_search,
             RecordedTimestamp, Items, Error, FileName, MaybeNewTimestamp, !IO),
         (
             MaybeNewTimestamp = yes(NewTimestamp),
@@ -663,18 +668,19 @@
         % If we're checking a sub-module, don't re-read interface files
         % read for other modules checked during this compilation.
         !.Info ^ is_inline_sub_module = yes,
-        find_read_module(!.Info ^ read_modules, ImportedModuleName,
-            Suffix, yes, Items0, MaybeNewTimestamp0, Error0, FileName0)
-    ->
-        Items = Items0,
-        MaybeNewTimestamp = MaybeNewTimestamp0,
-        Error = Error0,
-        FileName = FileName0,
+        find_read_module(!.Info ^ read_modules, ImportedModuleName, Suffix,
+            do_return_timestamp, ItemsPrime, MaybeNewTimestampPrime,
+            ErrorPrime, FileNamePrime)
+    ->
+        Items = ItemsPrime,
+        MaybeNewTimestamp = MaybeNewTimestampPrime,
+        Error = ErrorPrime,
+        FileName = FileNamePrime,
         Recorded = bool.yes
     ;
         Recorded = bool.no,
-        read_mod_if_changed(ImportedModuleName, Suffix,
-            "Reading interface file for module", yes, RecordedTimestamp,
+        read_module_if_changed(ImportedModuleName, Suffix,
+            "Reading interface file for module", do_search, RecordedTimestamp,
             Items, Error, FileName, MaybeNewTimestamp, !IO)
     ),
     (
Index: compiler/recompilation.usage.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/recompilation.usage.m,v
retrieving revision 1.47
diff -u -b -r1.47 recompilation.usage.m
--- compiler/recompilation.usage.m	22 Jan 2008 15:06:16 -0000	1.47
+++ compiler/recompilation.usage.m	19 Jul 2008 02:09:05 -0000
@@ -18,8 +18,8 @@
 
 :- import_module hlds.hlds_module.
 :- import_module hlds.hlds_pred.
-:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
+:- import_module parse_tree.module_imports.
 
 :- import_module assoc_list.
 :- import_module io.
@@ -87,10 +87,12 @@
 :- import_module hlds.passes_aux.
 :- import_module hlds.pred_table.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module libs.timestamp.
 :- import_module mdbcomp.prim_data.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_item.
@@ -121,7 +123,8 @@
             !IO),
 
         module_info_get_name(ModuleInfo, ModuleName),
-        module_name_to_file_name(ModuleName, ".used", yes, FileName, !IO),
+        module_name_to_file_name(ModuleName, ".used", do_create_dirs,
+            FileName, !IO),
         io.open_output(FileName, FileResult, !IO),
         (
             FileResult = ok(Stream0),
Index: compiler/simplify.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/simplify.m,v
retrieving revision 1.232
diff -u -b -r1.232 simplify.m
--- compiler/simplify.m	6 Jun 2008 08:04:45 -0000	1.232
+++ compiler/simplify.m	18 Jul 2008 10:05:40 -0000
@@ -144,6 +144,7 @@
 :- import_module hlds.quantification.
 :- import_module hlds.special_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.options.
 :- import_module libs.trace_params.
 :- import_module mdbcomp.
@@ -151,7 +152,6 @@
 :- import_module parse_tree.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_mode.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_type_subst.
 :- import_module parse_tree.prog_util.
Index: compiler/source_file_map.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/source_file_map.m,v
retrieving revision 1.24
diff -u -b -r1.24 source_file_map.m
--- compiler/source_file_map.m	23 Nov 2007 07:35:24 -0000	1.24
+++ compiler/source_file_map.m	18 Jul 2008 14:48:57 -0000
@@ -11,13 +11,17 @@
 % 
 % Maintain a mapping from module name to source file name.
 % 
+% The reason why this module is in the parse_tree package is that discovering
+% what module is stored in a file requires reading the ":- module" declaration
+% in that file.
+% 
 %-----------------------------------------------------------------------------%
 
 :- module parse_tree.source_file_map.
 :- interface.
 
 :- import_module mdbcomp.prim_data.
-:- import_module parse_tree.prog_io.
+:- import_module libs.file_util.
 
 :- import_module bool.
 :- import_module io.
@@ -48,7 +52,8 @@
 :- implementation.
 
 :- import_module libs.globals.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.prog_io.
 :- import_module parse_tree.prog_out.
 
 :- import_module char.
@@ -248,3 +253,5 @@
 :- func modules_file_name = string.
 
 modules_file_name = "Mercury.modules".
+
+%-----------------------------------------------------------------------------%
Index: compiler/structure_reuse.analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.analysis.m,v
retrieving revision 1.16
diff -u -b -r1.16 structure_reuse.analysis.m
--- compiler/structure_reuse.analysis.m	6 Jun 2008 02:18:06 -0000	1.16
+++ compiler/structure_reuse.analysis.m	18 Jul 2008 13:40:02 -0000
@@ -97,15 +97,15 @@
 :- import_module hlds.passes_aux.
 :- import_module hlds.pred_table.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_ctgc.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module transform_hlds.ctgc.structure_reuse.direct.
 :- import_module transform_hlds.ctgc.structure_reuse.domain.
@@ -664,7 +664,8 @@
 
 make_opt_int(!ModuleInfo, !IO) :-
     module_info_get_name(!.ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+        OptFileName, !IO),
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Appending structure_reuse pragmas to ",
         !IO),
Index: compiler/structure_reuse.direct.detect_garbage.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.direct.detect_garbage.m,v
retrieving revision 1.19
diff -u -b -r1.19 structure_reuse.direct.detect_garbage.m
--- compiler/structure_reuse.direct.detect_garbage.m	16 Jun 2008 04:52:31 -0000	1.19
+++ compiler/structure_reuse.direct.detect_garbage.m	18 Jul 2008 10:40:44 -0000
@@ -39,6 +39,7 @@
 :- import_module check_hlds.type_util.
 :- import_module libs.compiler_util.
 :- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_out.
 :- import_module transform_hlds.ctgc.datastruct.
 :- import_module transform_hlds.ctgc.livedata.
 
Index: compiler/structure_reuse.direct.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_reuse.direct.m,v
retrieving revision 1.12
diff -u -b -r1.12 structure_reuse.direct.m
--- compiler/structure_reuse.direct.m	28 May 2008 00:52:29 -0000	1.12
+++ compiler/structure_reuse.direct.m	18 Jul 2008 10:33:52 -0000
@@ -54,10 +54,10 @@
 
 :- import_module analysis.
 :- import_module hlds.passes_aux.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module parse_tree.error_util.
-:- import_module parse_tree.prog_out.
 :- import_module transform_hlds.ctgc.structure_reuse.direct.choose_reuse.
 :- import_module transform_hlds.ctgc.structure_reuse.direct.detect_garbage.
 :- import_module transform_hlds.ctgc.util.
Index: compiler/structure_sharing.analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/structure_sharing.analysis.m,v
retrieving revision 1.39
diff -u -b -r1.39 structure_sharing.analysis.m
--- compiler/structure_sharing.analysis.m	16 Jun 2008 04:52:31 -0000	1.39
+++ compiler/structure_sharing.analysis.m	18 Jul 2008 13:40:24 -0000
@@ -70,13 +70,14 @@
 :- import_module hlds.hlds_out.
 :- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module ll_backend.liveness.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_ctgc.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_out.
@@ -912,7 +913,8 @@
 
 make_opt_int(ModuleInfo, !IO) :-
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+        OptFileName, !IO),
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Appending structure_sharing pragmas to ",
         !IO),
Index: compiler/tabling_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/tabling_analysis.m,v
retrieving revision 1.17
diff -u -b -r1.17 tabling_analysis.m
--- compiler/tabling_analysis.m	6 Jun 2008 02:18:06 -0000	1.17
+++ compiler/tabling_analysis.m	18 Jul 2008 13:40:48 -0000
@@ -90,14 +90,14 @@
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module transform_hlds.dependency_graph.
 :- import_module transform_hlds.mmc_analysis.
 
@@ -782,7 +782,8 @@
 
 make_opt_int(ModuleInfo, !IO) :-
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+        OptFileName, !IO),
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Appending mm_tabling_info pragmas to `",
         !IO),
Index: compiler/term_constr_main.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/term_constr_main.m,v
retrieving revision 1.17
diff -u -b -r1.17 term_constr_main.m
--- compiler/term_constr_main.m	18 Feb 2008 23:57:45 -0000	1.17
+++ compiler/term_constr_main.m	18 Jul 2008 13:41:02 -0000
@@ -203,13 +203,13 @@
 :- implementation.
 
 :- import_module hlds.hlds_pred.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.lp_rational.
 :- import_module libs.options.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_util.
 :- import_module transform_hlds.dependency_graph.
 :- import_module transform_hlds.term_constr_build.
@@ -477,7 +477,8 @@
 
 make_opt_int(PredIds, ModuleInfo, !IO) :-
   module_info_get_name(ModuleInfo, ModuleName),
-  module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+  module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+    OptFileName, !IO),
   globals.io_lookup_bool_option(verbose, Verbose, !IO),
   maybe_write_string(Verbose,
       "% Appending termination2_info pragmas to `", !IO),
Index: compiler/termination.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/termination.m,v
retrieving revision 1.80
diff -u -b -r1.80 termination.m
--- compiler/termination.m	18 Feb 2008 23:57:45 -0000	1.80
+++ compiler/termination.m	18 Jul 2008 13:41:14 -0000
@@ -60,14 +60,14 @@
 :- import_module hlds.hlds_goal.
 :- import_module hlds.passes_aux.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module transform_hlds.dependency_graph.
 :- import_module transform_hlds.post_term_analysis.
 :- import_module transform_hlds.term_errors.
@@ -867,7 +867,8 @@
 
 make_termination_opt_int(PredIds, ModuleInfo, !IO) :-
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+        OptFileName, !IO),
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Appending termination_info pragmas to `",
         !IO),
Index: compiler/trailing_analysis.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/trailing_analysis.m,v
retrieving revision 1.36
diff -u -b -r1.36 trailing_analysis.m
--- compiler/trailing_analysis.m	6 Jun 2008 02:18:06 -0000	1.36
+++ compiler/trailing_analysis.m	18 Jul 2008 13:41:22 -0000
@@ -90,14 +90,14 @@
 :- import_module hlds.hlds_goal.
 :- import_module hlds.hlds_pred.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.error_util.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module transform_hlds.dependency_graph.
 :- import_module transform_hlds.mmc_analysis.
@@ -1027,7 +1027,8 @@
 
 make_opt_int(ModuleInfo, !IO) :-
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+    module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+        OptFileName, !IO),
     globals.io_lookup_bool_option(verbose, Verbose, !IO),
     maybe_write_string(Verbose, "% Appending trailing_info pragmas to `", !IO),
     maybe_write_string(Verbose, OptFileName, !IO),
Index: compiler/trans_opt.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/trans_opt.m,v
retrieving revision 1.50
diff -u -b -r1.50 trans_opt.m
--- compiler/trans_opt.m	16 Jul 2008 03:30:31 -0000	1.50
+++ compiler/trans_opt.m	19 Jul 2008 02:11:46 -0000
@@ -56,7 +56,7 @@
 
 :- import_module hlds.hlds_module.
 :- import_module mdbcomp.prim_data.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.module_imports.
 
 :- import_module bool.
 :- import_module io.
@@ -83,14 +83,17 @@
 :- implementation.
 
 :- import_module hlds.hlds_pred.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.mercury_to_mercury.
+:- import_module parse_tree.modules.
+:- import_module parse_tree.module_cmds.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_item.
 :- import_module parse_tree.prog_io.
-:- import_module parse_tree.prog_out.
 :- import_module transform_hlds.ctgc.
 :- import_module transform_hlds.ctgc.structure_reuse.
 :- import_module transform_hlds.ctgc.structure_reuse.analysis.
@@ -114,8 +117,8 @@
 
 write_trans_opt_file(Module, !IO) :-
     module_info_get_name(Module, ModuleName),
-    module_name_to_file_name(ModuleName, ".trans_opt.tmp", yes, TmpOptName,
-        !IO),
+    module_name_to_file_name(ModuleName, ".trans_opt.tmp", do_create_dirs,
+        TmpOptName, !IO),
     io.open_output(TmpOptName, Result, !IO),
     (
         Result = error(Error),
@@ -178,7 +181,8 @@
         io.set_output_stream(OldStream, _, !IO),
         io.close_output(Stream, !IO),
 
-        module_name_to_file_name(ModuleName, ".trans_opt", no, OptName, !IO),
+        module_name_to_file_name(ModuleName, ".trans_opt", do_not_create_dirs,
+            OptName, !IO),
         update_interface(OptName, !IO),
         touch_interface_datestamp(ModuleName, ".trans_opt_date", !IO)
     ).
Index: compiler/type_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/type_util.m,v
retrieving revision 1.191
diff -u -b -r1.191 type_util.m
--- compiler/type_util.m	11 Feb 2008 21:26:11 -0000	1.191
+++ compiler/type_util.m	18 Jul 2008 14:48:57 -0000
@@ -361,7 +361,7 @@
 %-----------------------------------------------------------------------------%
 
 type_ctor_module(_ModuleInfo, type_ctor(TypeSymName, _Arity)) = ModuleName :-
-    sym_name_get_module_name(TypeSymName, unqualified(""), ModuleName).
+    sym_name_get_module_name_default(TypeSymName, unqualified(""), ModuleName).
 
 type_ctor_name(_ModuleInfo, type_ctor(TypeSymName, _Arity)) =
     unqualify_name(TypeSymName).
Index: compiler/typecheck.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/typecheck.m,v
retrieving revision 1.432
diff -u -b -r1.432 typecheck.m
--- compiler/typecheck.m	16 Jul 2008 03:30:31 -0000	1.432
+++ compiler/typecheck.m	18 Jul 2008 16:44:13 -0000
@@ -127,7 +127,7 @@
 :- import_module mdbcomp.prim_data.
 :- import_module mdbcomp.program_representation.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.         % undesirable dependency
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_event.
 :- import_module parse_tree.prog_type.
Index: compiler/typecheck_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/typecheck_info.m,v
retrieving revision 1.24
diff -u -b -r1.24 typecheck_info.m
--- compiler/typecheck_info.m	27 Feb 2008 07:23:16 -0000	1.24
+++ compiler/typecheck_info.m	18 Jul 2008 10:06:29 -0000
@@ -371,10 +371,10 @@
 :- import_module check_hlds.type_util.
 :- import_module libs.
 :- import_module libs.compiler_util.
+:- import_module libs.file_util.
 :- import_module libs.globals.
 :- import_module libs.options.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
 :- import_module parse_tree.prog_type_subst.
 
Index: compiler/unify_proc.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unify_proc.m,v
retrieving revision 1.202
diff -u -b -r1.202 unify_proc.m
--- compiler/unify_proc.m	20 Feb 2008 02:44:19 -0000	1.202
+++ compiler/unify_proc.m	18 Jul 2008 14:48:57 -0000
@@ -165,7 +165,6 @@
 :- import_module parse_tree.error_util.
 :- import_module parse_tree.prog_mode.
 :- import_module parse_tree.prog_type.
-:- import_module parse_tree.prog_util.
 :- import_module recompilation.
 
 :- import_module int.
@@ -723,7 +722,8 @@
         PredName = special_pred_name(spec_pred_init, TypeCtor),
         module_info_get_name(ModuleInfo, ModuleName),
         TypeCtor = type_ctor(TypeSymName, _TypeArity),
-        sym_name_get_module_name(TypeSymName, ModuleName, TypeModuleName),
+        sym_name_get_module_name_default(TypeSymName, ModuleName,
+            TypeModuleName),
         InitPred = qualified(TypeModuleName, PredName),
         PredId   = invalid_pred_id,
         ModeId   = invalid_proc_id,
Index: compiler/unused_args.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unused_args.m,v
retrieving revision 1.155
diff -u -b -r1.155 unused_args.m
--- compiler/unused_args.m	6 Jun 2008 02:18:06 -0000	1.155
+++ compiler/unused_args.m	18 Jul 2008 13:41:55 -0000
@@ -100,7 +100,7 @@
 :- import_module libs.options.
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.mercury_to_mercury.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.prog_out.
 :- import_module parse_tree.prog_type.
@@ -248,7 +248,8 @@
         IntermodAnalysis = no
     ->
         module_info_get_name(!.ModuleInfo, ModuleName),
-        module_name_to_file_name(ModuleName, ".opt.tmp", no, OptFileName, !IO),
+        module_name_to_file_name(ModuleName, ".opt.tmp", do_not_create_dirs,
+            OptFileName, !IO),
         io.open_append(OptFileName, OptFileRes, !IO),
         (
             OptFileRes = ok(OptFile),
Index: compiler/unused_imports.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/unused_imports.m,v
retrieving revision 1.15
diff -u -b -r1.15 unused_imports.m
--- compiler/unused_imports.m	3 Apr 2008 05:26:46 -0000	1.15
+++ compiler/unused_imports.m	18 Jul 2008 11:32:03 -0000
@@ -53,6 +53,7 @@
 :- import_module hlds.hlds_pred.
 :- import_module mdbcomp.
 :- import_module mdbcomp.prim_data.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.modules.
 :- import_module parse_tree.prog_data.
 
@@ -70,7 +71,8 @@
 unused_imports(ModuleInfo, !:Specs, !IO) :-
     !:Specs = [],
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".m", no, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".m", do_not_create_dirs, FileName,
+        !IO),
 
     % Each parent module of the current module imports are inherited by
     % this module so we have to add the used modules of the parents to
Index: compiler/write_deps_file.m
===================================================================
RCS file: compiler/write_deps_file.m
diff -N compiler/write_deps_file.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ compiler/write_deps_file.m	19 Jul 2008 05:12:32 -0000
@@ -0,0 +1,2431 @@
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
+% Copyright (C) 2008 The University of Melbourne.
+% This file may only be copied under the terms of the GNU General
+% Public License - see the file COPYING in the Mercury distribution.
+%-----------------------------------------------------------------------------%
+%
+% File: write_deps_file.m.
+%
+%-----------------------------------------------------------------------------%
+
+:- module parse_tree.write_deps_file.
+:- interface.
+
+:- import_module libs.file_util.
+:- import_module mdbcomp.prim_data.
+:- import_module parse_tree.deps_map.
+:- import_module parse_tree.module_imports.
+
+:- import_module bool.
+:- import_module io.
+:- import_module list.
+:- import_module maybe.
+:- import_module set.
+
+    % write_dependency_file(Module, AllDeps, MaybeTransOptDeps):
+    %
+    % Write out the per-module makefile dependencies (`.d') file for the
+    % specified module. AllDeps is the set of all module names which the
+    % generated code for this module might depend on, i.e. all that have been
+    % used or imported, directly or indirectly, into this module, including
+    % via .opt or .trans_opt files, and including parent modules of nested
+    % modules. MaybeTransOptDeps is a list of module names which the
+    % `.trans_opt' file may depend on.  This is set to `no' if the
+    % dependency list is not available.
+    %
+:- pred write_dependency_file(module_imports::in, set(module_name)::in,
+    maybe(list(module_name))::in, io::di, io::uo) is det.
+
+    % Write out the `.dv' file, using the information collected in the
+    % deps_map data structure.
+    %
+:- pred generate_dependencies_write_dv_file(file_name::in, module_name::in,
+    deps_map::in, io::di, io::uo) is det.
+
+    % Write out the `.dep' file, using the information collected in the
+    % deps_map data structure.
+    %
+:- pred generate_dependencies_write_dep_file(file_name::in, module_name::in,
+    deps_map::in, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+    % Generate the list of .NET DLLs which could be referred to by this module
+    % (including the module itself).
+    %
+    % If we are compiling a module within the standard library we should
+    % reference the runtime DLLs and all other library DLLs.  If we are
+    % outside the library we should just reference mercury.dll (which will
+    % contain all the DLLs).
+    %
+:- func referenced_dlls(module_name, list(module_name)) = list(module_name).
+
+%-----------------------------------------------------------------------------%
+
+    % For each dependency, search intermod_directories for a .Suffix
+    % file or a .m file, filtering out those for which the search fails.
+    % If --use-opt-files is set, only look for `.opt' files,
+    % not `.m' files.
+    % XXX This won't find nested sub-modules.
+    % XXX Use `mmc --make' if that matters.
+    %
+:- pred get_opt_deps(bool::in, list(module_name)::in, list(string)::in,
+    string::in, list(module_name)::out, io::di, io::uo) is det.
+
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module libs.compiler_util.
+:- import_module libs.globals.
+:- import_module libs.options.
+:- import_module make.                      % undesirable dependency
+:- import_module parse_tree.file_names.
+:- import_module parse_tree.module_cmds.
+:- import_module parse_tree.prog_data.
+:- import_module parse_tree.prog_foreign.
+:- import_module parse_tree.prog_io.        % undesirable dependency
+:- import_module parse_tree.prog_item.
+:- import_module parse_tree.source_file_map.
+
+:- import_module assoc_list.
+:- import_module dir.
+:- import_module library.
+:- import_module map.
+:- import_module string.
+:- import_module pair.
+
+write_dependency_file(Module, AllDepsSet, MaybeTransOptDeps, !IO) :-
+    Module = module_imports(SourceFileName, SourceFileModuleName,
+        ModuleName, ParentDeps, IntDeps, ImplDeps, IndirectDeps,
+        _Children, InclDeps, NestedDeps, FactDeps0,
+        ContainsForeignCode, ForeignImports0, _ContainsForeignExport,
+        Items, _Error, _Timestamps, _HasMain, _Dir),
+
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    module_name_to_make_var_name(ModuleName, MakeVarName),
+    module_name_to_file_name(ModuleName, ".d", do_create_dirs,
+        DependencyFileName, !IO),
+    module_name_to_file_name(ModuleName, ".trans_opt_date", do_not_create_dirs,
+        TransOptDateFileName, !IO),
+
+    % To avoid problems with concurrent updates of `.d' files during
+    % parallel makes, we first create the file with a temporary name,
+    % and then rename it to the desired name when we've finished.
+
+    io.make_temp(dir.dirname(DependencyFileName), "tmp_d",
+        TmpDependencyFileName, !IO),
+    maybe_write_string(Verbose, "% Writing auto-dependency file `", !IO),
+    maybe_write_string(Verbose, DependencyFileName, !IO),
+    maybe_write_string(Verbose, "'...", !IO),
+    maybe_flush_output(Verbose, !IO),
+    io.open_output(TmpDependencyFileName, Result, !IO),
+    (
+        Result = error(IOError),
+        maybe_write_string(Verbose, " failed.\n", !IO),
+        maybe_flush_output(Verbose, !IO),
+        io.error_message(IOError, IOErrorMessage),
+        string.append_list(["error opening temporary file `",
+            TmpDependencyFileName, "' for output: ",
+            IOErrorMessage], Message),
+        report_error(Message, !IO)
+    ;
+        Result = ok(DepStream),
+        list.append(IntDeps, ImplDeps, LongDeps0),
+        ShortDeps0 = IndirectDeps,
+        set.list_to_set(LongDeps0, LongDepsSet0),
+        set.delete(LongDepsSet0, ModuleName, LongDepsSet),
+        set.list_to_set(ShortDeps0, ShortDepsSet0),
+        set.difference(ShortDepsSet0, LongDepsSet, ShortDepsSet1),
+        set.delete(ShortDepsSet1, ModuleName, ShortDepsSet),
+        set.to_sorted_list(LongDepsSet, LongDeps),
+        set.to_sorted_list(ShortDepsSet, ShortDeps),
+        set.to_sorted_list(AllDepsSet, AllDeps),
+        list.sort_and_remove_dups(FactDeps0, FactDeps),
+
+        (
+            MaybeTransOptDeps = yes(TransOptDeps0),
+            set.list_to_set(TransOptDeps0, TransOptDepsSet0),
+            set.intersect(TransOptDepsSet0, LongDepsSet, TransOptDepsSet),
+            set.to_sorted_list(TransOptDepsSet, TransOptDateDeps),
+
+            % Note that maybe_read_dependency_file searches for
+            % this exact pattern.
+            io.write_strings(DepStream, [TransOptDateFileName, " :"], !IO),
+            write_dependencies_list(TransOptDateDeps, ".trans_opt", DepStream,
+                !IO)
+        ;
+            MaybeTransOptDeps = no
+        ),
+
+        (
+            FactDeps = [_ | _],
+            io.write_strings(DepStream,
+                ["\n\n", MakeVarName, ".fact_tables ="], !IO),
+            write_file_dependencies_list(FactDeps, "", DepStream, !IO),
+            io.nl(DepStream, !IO),
+            globals.io_lookup_bool_option(assume_gmake, AssumeGmake, !IO),
+            (
+                AssumeGmake = yes,
+                io.write_strings(DepStream, [
+                    "\n\n", MakeVarName,
+                    ".fact_tables.os = $(", MakeVarName,
+                    ".fact_tables:%=$(os_subdir)%.$O)\n\n",
+                    MakeVarName,
+                    ".fact_tables.cs = $(", MakeVarName,
+                    ".fact_tables:%=$(cs_subdir)%.c)\n\n"
+                ], !IO)
+            ;
+                AssumeGmake = no,
+                io.write_strings(DepStream,
+                    [MakeVarName, ".fact_tables.cs ="], !IO),
+                write_fact_table_dependencies_list(ModuleName,
+                    FactDeps, ".c", DepStream, !IO),
+                io.write_strings(DepStream, ["\n\n",
+                    MakeVarName, ".fact_tables.os ="], !IO),
+                write_fact_table_dependencies_list(ModuleName,
+                    FactDeps, ".$O", DepStream, !IO),
+                io.nl(DepStream, !IO)
+            )
+        ;
+            FactDeps = []
+        ),
+
+        ( string.remove_suffix(SourceFileName, ".m", SourceFileBase) ->
+            ErrFileName = SourceFileBase ++ ".err"
+        ;
+            unexpected(this_file, "source file doesn't end in `.m'")
+        ),
+        module_name_to_file_name(ModuleName, ".optdate", do_not_create_dirs,
+            OptDateFileName, !IO),
+        module_name_to_file_name(ModuleName, ".c_date", do_not_create_dirs,
+            CDateFileName, !IO),
+        module_name_to_file_name(ModuleName, ".s_date", do_not_create_dirs,
+            AsmDateFileName, !IO),
+        module_name_to_file_name(ModuleName, ".pic_s_date", do_not_create_dirs,
+            PicAsmDateFileName, !IO),
+        module_name_to_file_name(ModuleName, ".$O", do_not_create_dirs,
+            ObjFileName, !IO),
+        module_name_to_file_name(ModuleName, ".il_date", do_not_create_dirs,
+            ILDateFileName, !IO),
+        module_name_to_file_name(ModuleName, ".java_date", do_not_create_dirs,
+            JavaDateFileName, !IO),
+        % XXX Why is the extension hardcoded to .pic_o here?  That looks
+        % wrong.  It should probably be .$(EXT_FOR_PIC_OBJECT) - juliensf.
+        module_name_to_file_name(ModuleName, ".pic_o", do_not_create_dirs,
+            PicObjFileName, !IO),
+        module_name_to_file_name(ModuleName, ".int0", do_not_create_dirs,
+            Int0FileName, !IO),
+        io.write_strings(DepStream, ["\n\n",
+            OptDateFileName, " ",
+            TransOptDateFileName, " ",
+            ErrFileName, " ",
+            CDateFileName, " ",
+            AsmDateFileName, " ",
+            PicAsmDateFileName, " ",
+            ILDateFileName, " ",
+            JavaDateFileName
+        ], !IO),
+        io.write_strings(DepStream, [" : ", SourceFileName], !IO),
+        % If the module contains nested sub-modules then the `.int0' file
+        % must first be built.
+        (
+            InclDeps = [_ | _],
+            io.write_strings(DepStream, [" ", Int0FileName], !IO)
+        ;
+            InclDeps = []
+        ),
+        write_dependencies_list(ParentDeps, ".int0", DepStream, !IO),
+        write_dependencies_list(LongDeps, ".int", DepStream, !IO),
+        write_dependencies_list(ShortDeps, ".int2", DepStream, !IO),
+
+        NestedExts = [
+            ".optdate",
+            ".trans_opt_date",
+            ".c_date",
+            ".s_date",
+            ".pic_s_date",
+            ".dir/*.$O",
+            ".il_date",
+            ".java_date"],
+
+        % If a module contains nested-submodules then we need to build
+        % the nested children before attempting to build the parent module.
+        (
+            NestedDeps = []
+        ;
+            NestedDeps = [_ | _],
+            Write = (pred(Ext::in, !.LIO::di, !:LIO::uo) is det :-
+                module_name_to_file_name(ModuleName, Ext, do_not_create_dirs,
+                    ExtName, !LIO),
+                io.write_strings(DepStream, ["\n\n", ExtName, " : "], !LIO),
+                write_dependencies_list(NestedDeps, Ext, DepStream, !LIO)
+            ),
+            list.foldl(Write, NestedExts, !IO)
+        ),
+        (
+            FactDeps = [_ | _],
+            io.write_strings(DepStream, [
+                " \\\n\t$(", MakeVarName, ".fact_tables)\n\n",
+                "$(", MakeVarName, ".fact_tables.os) : $(",
+                MakeVarName, ".fact_tables) ",
+                SourceFileName, "\n\n",
+                "$(", MakeVarName, ".fact_tables.cs) : ",
+                ObjFileName, "\n"
+            ], !IO)
+        ;
+            FactDeps = []
+        ),
+
+        globals.io_lookup_bool_option(use_opt_files, UseOptFiles, !IO),
+        globals.io_lookup_bool_option(intermodule_optimization, Intermod, !IO),
+        globals.io_lookup_accumulating_option(intermod_directories,
+            IntermodDirs, !IO),
+
+        % If intermodule_optimization is enabled then all the .mh files
+        % must exist because it is possible that the .c file imports them
+        % directly or indirectly.
+        (
+            Intermod = yes,
+            io.write_strings(DepStream, ["\n\n", ObjFileName, " : "], !IO),
+            write_dependencies_list(AllDeps, ".mh", DepStream, !IO)
+        ;
+            Intermod = no
+        ),
+        (
+            ( Intermod = yes
+            ; UseOptFiles = yes
+            )
+        ->
+            io.write_strings(DepStream, [
+                "\n\n",
+                TransOptDateFileName, " ",
+                ErrFileName, " ",
+                CDateFileName, " ",
+                AsmDateFileName, " ",
+                PicAsmDateFileName, " ",
+                ILDateFileName, " ",
+                JavaDateFileName, " : "
+            ], !IO),
+
+            % The target (e.g. C) file only depends on the .opt files
+            % from the current directory, so that inter-module optimization
+            % works when the .opt files for the library are unavailable.
+            % This is only necessary because make doesn't allow conditional
+            % dependencies. The dependency on the current module's .opt file
+            % is to make sure the module gets type-checked without having
+            % the definitions of abstract types from other modules.
+            %
+            % XXX The code here doesn't correctly handle dependencies
+            % on `.int' and `.int2' files needed by the `.opt' files.
+            globals.io_lookup_bool_option(transitive_optimization, TransOpt,
+                !IO),
+            globals.io_lookup_bool_option(use_trans_opt_files, UseTransOpt,
+                !IO),
+
+            (
+                ( TransOpt = yes
+                ; UseTransOpt = yes
+                )
+            ->
+                bool.not(UseTransOpt, BuildOptFiles),
+                get_both_opt_deps(BuildOptFiles, [ModuleName | LongDeps],
+                    IntermodDirs, OptDeps, TransOptDeps, !IO),
+                OptInt0Deps = sort_and_remove_dups(
+                    condense(list.map(get_ancestors, OptDeps))),
+                write_dependencies_list(OptDeps, ".opt", DepStream, !IO),
+                write_dependencies_list(OptInt0Deps, ".int0", DepStream, !IO),
+
+                io.write_strings(DepStream, [
+                    "\n\n",
+                    ErrFileName, " ",
+                    CDateFileName, " ",
+                    AsmDateFileName, " ",
+                    PicAsmDateFileName, " ",
+                    ILDateFileName, " ",
+                    JavaDateFileName, " : "
+                ], !IO),
+                write_dependencies_list(TransOptDeps, ".trans_opt", DepStream,
+                    !IO)
+            ;
+                bool.not(UseOptFiles, BuildOptFiles),
+                get_opt_deps(BuildOptFiles, [ModuleName | LongDeps],
+                    IntermodDirs, ".opt", OptDeps, !IO),
+                OptInt0Deps = sort_and_remove_dups(
+                    condense(list.map(get_ancestors, OptDeps))),
+                write_dependencies_list(OptDeps, ".opt", DepStream, !IO),
+                write_dependencies_list(OptInt0Deps, ".int0", DepStream, !IO)
+            )
+        ;
+            true
+        ),
+
+        globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
+        globals.io_get_target(CompilationTarget, !IO),
+        (
+            HighLevelCode = yes,
+            CompilationTarget = target_c
+        ->
+            % For --high-level-code with --target c, we need to make sure that
+            % we generate the header files for imported modules before
+            % compiling the C files, since the generated C files
+            % #include those header files.
+
+            io.write_strings(DepStream, [
+                "\n\n",
+                PicObjFileName, " ",
+                ObjFileName, " :"
+            ], !IO),
+            write_dependencies_list(AllDeps, ".mih", DepStream, !IO)
+        ;
+            true
+        ),
+
+        % We need to tell make how to make the header files. The header files
+        % are actually built by the same command that creates the .c or .s
+        % file, so we just make them depend on the .c or .s files.
+        % This is needed for the --high-level-code rule above, and for
+        % the rules introduced for `:- pragma foreign_import_module'
+        % declarations. In some grades the header file won't actually be built
+        % (e.g. LLDS grades for modules not containing `:- pragma export'
+        % declarations), but this rule won't do any harm.
+
+        module_name_to_file_name(ModuleName, ".c", do_not_create_dirs,
+            CFileName, !IO),
+        module_name_to_file_name(ModuleName, ".s", do_not_create_dirs,
+            AsmFileName, !IO),
+        module_name_to_file_name(ModuleName, ".mh", do_not_create_dirs,
+            HeaderFileName, !IO),
+        module_name_to_file_name(ModuleName, ".mih", do_not_create_dirs,
+            HeaderFileName2, !IO),
+        io.write_strings(DepStream, [
+            "\n\n",
+            "ifeq ($(TARGET_ASM),yes)\n",
+            HeaderFileName, " ", HeaderFileName2, " : ", AsmFileName, "\n",
+            "else\n",
+            HeaderFileName, " ",  HeaderFileName2, " : ", CFileName, "\n",
+            "endif"
+        ], !IO),
+
+        % The `.module_dep' file is made as a side effect of
+        % creating the `.c', `.s', `.il', or `.java'.
+
+        module_name_to_file_name(ModuleName, ".il", do_not_create_dirs,
+            ILFileName, !IO),
+        module_name_to_file_name(ModuleName, ".java", do_not_create_dirs,
+            JavaFileName, !IO),
+        module_name_to_file_name(ModuleName, make_module_dep_file_extension,
+            do_not_create_dirs, ModuleDepFileName, !IO),
+        io.write_strings(DepStream, [
+            "\n\n",
+            "ifeq ($(TARGET_ASM),yes)\n",
+            ModuleDepFileName, " : ", AsmFileName, "\n",
+            "else\n",
+            " ifeq ($(findstring il,$(GRADE)),il)\n",
+            ModuleDepFileName, " : ", ILFileName, "\n",
+            "  ifeq ($(findstring java,$(GRADE)),java)\n",
+            ModuleDepFileName, " : ", JavaFileName, "\n",
+            "  else\n",
+            ModuleDepFileName, " : ", CFileName, "\n",
+            "  endif\n",
+            " endif\n",
+            "endif"
+        ], !IO),
+
+        % The .date and .date0 files depend on the .int0 files for the parent
+        % modules, and the .int3 files for the directly and indirectly imported
+        % modules.
+        %
+        % For nested sub-modules, the `.date' files for the parent modules
+        % also depend on the same things as the `.date' files for this module,
+        % since all the `.date' files will get produced by a single mmc
+        % command. Similarly for `.date0' files, except these don't depend
+        % on the `.int0' files, because when doing the
+        % `--make-private-interface' for nested modules, mmc will process
+        % the modules in outermost to innermost order so as to produce each
+        % `.int0' file before it is needed.
+
+        module_name_to_file_name(ModuleName, ".date", do_not_create_dirs,
+            DateFileName, !IO),
+        module_name_to_file_name(ModuleName, ".date0", do_not_create_dirs,
+            Date0FileName, !IO),
+        io.write_strings(DepStream, [
+            "\n\n", DateFileName, " ", Date0FileName
+        ], !IO),
+        write_dependencies_list(ParentDeps, ".date", DepStream, !IO),
+        io.write_strings(DepStream, [" : ", SourceFileName], !IO),
+        write_dependencies_list(ParentDeps, ".int0", DepStream, !IO),
+        write_dependencies_list(LongDeps, ".int3", DepStream, !IO),
+        write_dependencies_list(ShortDeps, ".int3", DepStream, !IO),
+
+        io.write_strings(DepStream, ["\n\n", Date0FileName], !IO),
+        write_dependencies_list(ParentDeps, ".date0", DepStream, !IO),
+        io.write_strings(DepStream, [" : ", SourceFileName], !IO),
+        write_dependencies_list(LongDeps, ".int3", DepStream, !IO),
+        write_dependencies_list(ShortDeps, ".int3", DepStream, !IO),
+        io.write_string(DepStream, "\n\n", !IO),
+
+        % If we can pass the module name rather than the file name, then do so.
+        % `--smart-recompilation' doesn't work if the file name is passed
+        % and the module name doesn't match the file name.
+
+        have_source_file_map(HaveMap, !IO),
+        (
+            HaveMap = yes,
+            module_name_to_file_name(SourceFileModuleName, ModuleArg)
+        ;
+            HaveMap = no,
+            ModuleArg = SourceFileName
+        ),
+
+        globals.io_get_target(Target, !IO),
+        globals.io_lookup_bool_option(sign_assembly, SignAssembly, !IO),
+        globals.io_get_globals(Globals, !IO),
+
+        % If we are on the IL backend, add the dependency that the
+        % top level dll of a nested module hierachy depends on all
+        % of it sub-modules dlls, as they are referenced from
+        % inside the top level dll.
+        % XXX Do we need to do the same for Java?
+
+        module_name_to_file_name(ModuleName, ".dll", do_not_create_dirs,
+            DllFileName, !IO),
+        module_name_to_file_name(ModuleName, ".class", do_not_create_dirs,
+            ClassFileName, !IO),
+        module_name_to_file_name(ModuleName, ".beam", do_not_create_dirs,
+            BeamFileName, !IO),
+        SubModules = submodules(ModuleName, AllDeps),
+        (
+            Target = target_il,
+            SubModules = [_ | _]
+        ->
+            io.write_strings(DepStream, [DllFileName, " : "], !IO),
+            write_dll_dependencies_list(SubModules, "", DepStream, !IO),
+            io.nl(DepStream, !IO)
+        ;
+            true
+        ),
+
+        (
+            ContainsForeignCode = contains_foreign_code(LangSet),
+            ForeignImports = ForeignImports0
+        ;
+            ContainsForeignCode = contains_foreign_code_unknown,
+            get_item_list_foreign_code(Globals, Items, LangSet,
+                ForeignImports1, _),
+            % If we're generating the `.dep' file, ForeignImports0 will contain
+            % a conservative approximation to the set of foreign imports
+            % needed which will include imports required by imported modules.
+            (
+                ForeignImports0 = [],
+                ForeignImports = ForeignImports1
+            ;
+                ForeignImports0 = [_ | _],
+                ForeignImports = ForeignImports0
+            )
+        ;
+            ContainsForeignCode = contains_no_foreign_code,
+            set.init(LangSet),
+            ForeignImports = ForeignImports0
+        ),
+
+        % Handle dependencies introduced by
+        % `:- pragma foreign_import_module' declarations.
+
+        list.filter_map(
+            (pred(ForeignImportMod::in, Import::out) is semidet :-
+                Import = foreign_import_module_name_from_module(
+                    ForeignImportMod, SourceFileModuleName),
+
+                % XXX We can't include mercury.dll as mmake can't find it,
+                % but we know that it exists.
+                Import \= unqualified("mercury")
+            ), ForeignImports, ForeignImportedModules),
+        (
+            ForeignImportedModules = []
+        ;
+            ForeignImportedModules = [_ | _],
+            (
+                Target = target_il,
+                ForeignImportTargets = [DllFileName],
+                ForeignImportExt = ".dll"
+            ;
+                Target = target_java,
+                ForeignImportTargets = [ClassFileName],
+                ForeignImportExt = ".java"
+            ;
+                Target = target_erlang,
+                ForeignImportTargets = [BeamFileName],
+                ForeignImportExt = ".hrl"
+            ;
+                Target = target_c,
+                % NOTE: for C (and asm) the possible targets might be a .o
+                % file _or_ a .pic_o file.  We need to include dependencies
+                % for the latter otherwise invoking mmake with a <module>.pic_o
+                % target will break.
+                ForeignImportTargets = [ObjFileName, PicObjFileName],
+                ForeignImportExt = ".mh"
+            ;
+                Target = target_asm,
+                ForeignImportTargets = [ObjFileName, PicObjFileName],
+                ForeignImportExt = ".mh"
+            ;
+                % XXX These are just the C ones at the moment.
+                Target = target_x86_64,
+                ForeignImportTargets = [ObjFileName, PicObjFileName],
+                ForeignImportExt = ".mh"
+            ),
+            WriteForeignImportTarget = (pred(ForeignImportTarget::in,
+                    !.IO::di, !:IO::uo) is det :-
+                io.write_string(DepStream, "\n\n", !IO),
+                io.write_string(DepStream, ForeignImportTarget, !IO),
+                io.write_string(DepStream, " : ", !IO),
+                write_dependencies_list(ForeignImportedModules,
+                    ForeignImportExt, DepStream, !IO),
+                io.write_string(DepStream, "\n\n", !IO)
+            ),
+            list.foldl(WriteForeignImportTarget, ForeignImportTargets, !IO)
+        ),
+
+        (
+            Target = target_il,
+            not set.empty(LangSet)
+        ->
+            Langs = set.to_sorted_list(LangSet),
+            list.foldl(write_foreign_dependency_for_il(DepStream,
+                ModuleName, AllDeps, ForeignImports), Langs, !IO)
+        ;
+            true
+        ),
+
+        % If we are signing the assembly, then we will need the strong key
+        % to sign the il file with so add a dependency that the il file
+        % requires the strong name file `mercury.sn'. Also add the variable
+        % ILASM_KEYFLAG-<module> which is used to build the command line
+        % for ilasm.
+        (
+            Target = target_il,
+            SignAssembly = yes
+        ->
+            module_name_to_make_var_name(ModuleName, ModuleNameString),
+            module_name_to_file_name(ModuleName, ".il", do_not_create_dirs,
+                IlFileName, !IO),
+
+            io.write_strings(DepStream, [
+                "ILASM_KEYFLAG-", ModuleNameString,
+                    " = /keyf=mercury.sn\n",
+                IlFileName, " : mercury.sn\n"], !IO)
+        ;
+            true
+        ),
+
+        module_name_to_file_name(ModuleName, ".int", do_not_create_dirs,
+            IntFileName, !IO),
+        module_name_to_file_name(ModuleName, ".int2", do_not_create_dirs,
+            Int2FileName, !IO),
+        module_name_to_file_name(ModuleName, ".int3", do_not_create_dirs,
+            Int3FileName, !IO),
+        module_name_to_file_name(ModuleName, ".opt", do_not_create_dirs,
+            OptFileName, !IO),
+        module_name_to_file_name(ModuleName, ".trans_opt", do_not_create_dirs,
+            TransOptFileName, !IO),
+        module_name_to_file_name(ModuleName, ".date3", do_not_create_dirs,
+            Date3FileName, !IO),
+
+        % We add some extra dependencies to the generated `.d' files, so that
+        % local `.int', `.opt', etc. files shadow the installed versions
+        % properly (e.g. for when you're trying to build a new version
+        % of an installed library). This saves the user from having to add
+        % these explicitly if they have multiple libraries installed
+        % in the same installation hierarchy which aren't independent (e.g.
+        % one uses another). These extra dependencies are necessary due to
+        % the way the combination of search paths and pattern rules
+        % works in Make.
+        %
+        % Be very careful about changing the following rules. The `@:' is a
+        % silent do-nothing command. It is used to force GNU Make to recheck
+        % the timestamp on the target file.  (It is a pity that GNU Make
+        % doesn't have a way of handling these sorts of rules in a
+        % nicer manner.)
+
+        io.write_strings(DepStream, [
+            "\n",
+            Int0FileName, " : ", Date0FileName, "\n",
+            "\t@:\n",
+            IntFileName, " : ", DateFileName, "\n",
+            "\t@:\n",
+            Int2FileName, " : ", DateFileName, "\n",
+            "\t@:\n",
+            Int3FileName, " : ", Date3FileName, "\n",
+            "\t@:\n",
+            OptFileName, " : ", OptDateFileName, "\n",
+            "\t@:\n",
+            TransOptFileName, " : ", TransOptDateFileName, "\n",
+            "\t@:\n"
+        ], !IO),
+
+        globals.io_lookup_bool_option(use_subdirs, UseSubdirs, !IO),
+        (
+            UseSubdirs = yes,
+            io.nl(DepStream, !IO),
+            list.foldl(write_subdirs_shorthand_rule(DepStream, ModuleName),
+                [".c", ".$O", ".pic_o", ".s", ".pic_s",
+                ".java", ".class", ".il", ".dll"], !IO)
+        ;
+            UseSubdirs = no
+        ),
+
+        ( SourceFileName \= default_source_file(ModuleName) ->
+            % The pattern rules in Mmake.rules won't work, since the source
+            % file name doesn't match the expected source file name for this
+            % module name. This can occur due to just the use of different
+            % source file names, or it can be due to the use of nested modules.
+            % So we need to output hard-coded rules in this case.
+            %
+            % The rules output below won't work in the case of nested modules
+            % with parallel makes, because it will end up invoking the same
+            % command twice (since it produces two output files) at the same
+            % time.
+            %
+            % Any changes here will require corresponding changes to
+            % scripts/Mmake.rules. See that file for documentation
+            % on these rules.
+
+            io.write_strings(DepStream, [
+                "\n",
+                Date0FileName, " : ", SourceFileName, "\n",
+                "\t$(MCPI) $(ALL_GRADEFLAGS) ",
+                    "$(ALL_MCPIFLAGS) ", ModuleArg, "\n",
+                DateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCI) $(ALL_GRADEFLAGS) $(ALL_MCIFLAGS) ",
+                    ModuleArg, "\n",
+                Date3FileName, " : ", SourceFileName, "\n",
+                "\t$(MCSI) $(ALL_GRADEFLAGS) $(ALL_MCSIFLAGS) ",
+                    ModuleArg, "\n",
+                OptDateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCOI) $(ALL_GRADEFLAGS) $(ALL_MCOIFLAGS) ",
+                    ModuleArg, "\n",
+                TransOptDateFileName, " : ", SourceFileName,
+                    "\n",
+                "\t$(MCTOI) $(ALL_GRADEFLAGS) ",
+                    "$(ALL_MCTOIFLAGS) ", ModuleArg, "\n",
+                CDateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
+                    ModuleArg, " $(ERR_REDIRECT)\n",
+                "ifeq ($(TARGET_ASM),yes)\n",
+                AsmDateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
+                    "--target-code-only ", ModuleArg,
+                    " $(ERR_REDIRECT)\n",
+                PicAsmDateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
+                    "--target-code-only --pic ",
+                    "\\\n",
+                "\t\t--cflags ""$(GCCFLAGS_FOR_PIC)"" ",
+                    ModuleArg, " $(ERR_REDIRECT)\n",
+                "endif # TARGET_ASM\n",
+                ILDateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
+                    "--il-only ", ModuleArg,
+                    " $(ERR_REDIRECT)\n",
+                JavaDateFileName, " : ", SourceFileName, "\n",
+                "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
+                    "--java-only ", ModuleArg,
+                    " $(ERR_REDIRECT)\n"
+            ], !IO)
+        ;
+            true
+        ),
+
+        io.close_output(DepStream, !IO),
+        io.rename_file(TmpDependencyFileName, DependencyFileName, Result3,
+            !IO),
+        (
+            Result3 = error(_),
+            % On some systems, we need to remove the existing file
+            % first, if any.  So try again that way.
+            io.remove_file(DependencyFileName, Result4, !IO),
+            (
+                Result4 = error(Error4),
+                maybe_write_string(Verbose, " failed.\n", !IO),
+                maybe_flush_output(Verbose, !IO),
+                io.error_message(Error4, ErrorMsg),
+                string.append_list(["can't remove file `", DependencyFileName,
+                    "': ", ErrorMsg], Message),
+                report_error(Message, !IO)
+            ;
+                Result4 = ok,
+                io.rename_file(TmpDependencyFileName, DependencyFileName,
+                    Result5, !IO),
+                (
+                    Result5 = error(Error5),
+                    maybe_write_string(Verbose, " failed.\n", !IO),
+                    maybe_flush_output(Verbose, !IO),
+                    io.error_message(Error5, ErrorMsg),
+                    string.append_list(["can't rename file `",
+                        TmpDependencyFileName, "' as `", DependencyFileName,
+                        "': ", ErrorMsg], Message),
+                    report_error(Message, !IO)
+                ;
+                    Result5 = ok,
+                    maybe_write_string(Verbose, " done.\n", !IO)
+                )
+            )
+        ;
+            Result3 = ok,
+            maybe_write_string(Verbose, " done.\n", !IO)
+        )
+    ).
+
+    % submodules(Module, Imports):
+    %
+    % Returns the list of submodules from Imports which are sub-modules of
+    % Module, if Module is a top level module and not in the std library.
+    % Otherwise it returns the empty list.
+    %
+:- func submodules(module_name, list(module_name)) = list(module_name).
+
+submodules(Module, Modules0) = Modules :-
+    (
+        Module = unqualified(Str),
+        \+ mercury_std_library_module_name(Module)
+    ->
+        P = (pred(M::in) is semidet :-
+            Str = outermost_qualifier(M),
+            M \= Module
+        ),
+        list.filter(P, Modules0, Modules)
+    ;
+        Modules = []
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred write_dependencies_list(list(module_name)::in, string::in,
+    io.output_stream::in, io::di, io::uo) is det.
+
+write_dependencies_list([], _, _, !IO).
+write_dependencies_list([Module | Modules], Suffix, DepStream, !IO) :-
+    module_name_to_file_name(Module, Suffix, do_not_create_dirs,
+        FileName, !IO),
+    io.write_string(DepStream, " \\\n\t", !IO),
+    io.write_string(DepStream, FileName, !IO),
+    write_dependencies_list(Modules, Suffix, DepStream, !IO).
+
+:- pred write_compact_dependencies_list(list(module_name)::in, string::in,
+    string::in, maybe(pair(string))::in, io.output_stream::in,
+    io::di, io::uo) is det.
+
+write_compact_dependencies_list(Modules, Prefix, Suffix, Basis, DepStream,
+        !IO) :-
+    (
+        Basis = yes(VarName - OldSuffix),
+        io.write_string(DepStream, "$(", !IO),
+        io.write_string(DepStream, VarName, !IO),
+        io.write_string(DepStream, ":%", !IO),
+        io.write_string(DepStream, OldSuffix, !IO),
+        io.write_string(DepStream, "=", !IO),
+        io.write_string(DepStream, Prefix, !IO),
+        io.write_string(DepStream, "%", !IO),
+        io.write_string(DepStream, Suffix, !IO),
+        io.write_string(DepStream, ")", !IO)
+    ;
+        Basis = no,
+        write_dependencies_list(Modules, Suffix, DepStream, !IO)
+    ).
+
+:- pred write_compact_dependencies_separator(maybe(pair(string))::in,
+    io.output_stream::in, io::di, io::uo) is det.
+
+write_compact_dependencies_separator(no, _DepStream, !IO).
+write_compact_dependencies_separator(yes(_), DepStream, !IO) :-
+    io.write_string(DepStream, " ", !IO).
+
+:- pred write_dll_dependencies_list(list(module_name)::in,
+    string::in, io.output_stream::in, io::di, io::uo) is det.
+
+write_dll_dependencies_list(Modules, Prefix, DepStream, !IO) :-
+    list.foldl(write_dll_dependency(DepStream, Prefix), Modules, !IO).
+
+:- pred write_dll_dependency(io.output_stream::in, string::in,
+    module_name::in, io::di, io::uo) is det.
+
+write_dll_dependency(DepStream, Prefix, Module, !IO) :-
+    module_name_to_file_name(Module, ".dll", do_not_create_dirs,
+        FileName, !IO),
+    io.write_string(DepStream, " \\\n\t", !IO),
+    io.write_string(DepStream, Prefix, !IO),
+    io.write_string(DepStream, FileName, !IO).
+
+:- pred write_fact_table_dependencies_list(module_name::in,
+    list(file_name)::in, string::in, io.output_stream::in,
+    io::di, io::uo) is det.
+
+write_fact_table_dependencies_list(_, [], _, _, !IO).
+write_fact_table_dependencies_list(Module, [FactTable | FactTables], Suffix,
+        DepStream, !IO) :-
+    fact_table_file_name(Module, FactTable, Suffix, do_not_create_dirs,
+        FileName, !IO),
+    io.write_string(DepStream, " \\\n\t", !IO),
+    io.write_string(DepStream, FileName, !IO),
+    write_fact_table_dependencies_list(Module, FactTables, Suffix,
+        DepStream, !IO).
+
+:- pred write_extra_link_dependencies_list(
+    assoc_list(file_name, module_name)::in, string::in,
+    io.output_stream::in, io::di, io::uo) is det.
+
+write_extra_link_dependencies_list([], _, _, !IO).
+write_extra_link_dependencies_list([ExtraLink - Module | ExtraLinks], Suffix,
+        DepStream, !IO) :-
+    extra_link_obj_file_name(Module, ExtraLink, Suffix, do_not_create_dirs,
+        FileName, !IO),
+    io.write_string(DepStream, " \\\n\t", !IO),
+    io.write_string(DepStream, FileName, !IO),
+    write_extra_link_dependencies_list(ExtraLinks, Suffix, DepStream, !IO).
+
+:- pred write_file_dependencies_list(list(string)::in, string::in,
+    io.output_stream::in, io::di, io::uo) is det.
+
+write_file_dependencies_list([], _, _, !IO).
+write_file_dependencies_list([FileName | FileNames], Suffix, DepStream, !IO) :-
+    io.write_string(DepStream, " \\\n\t", !IO),
+    io.write_string(DepStream, FileName, !IO),
+    io.write_string(DepStream, Suffix, !IO),
+    write_file_dependencies_list(FileNames, Suffix, DepStream, !IO).
+
+    % Generate the following dependency.  This dependency is
+    % needed because module__cpp_code.dll might refer to
+    % high level data in any of the mercury modules it
+    % imports plus itself.
+    % We also generate a dependency on the .il file, so that mmake
+    % knows we need to generate the .il file to get the foreign language
+    % source file (e.g. .cpp file).
+    %
+    % For example, for MC++ we generate:
+    %
+    %   <module>__cpp_code.dll : <module>.dll <imports>.dll
+    %   <module>__cpp_code.cpp : <module>.il
+    %
+    % (the rule to generate .dll from .cpp is a pattern rule in
+    % scripts/Mmake.rules).
+    %
+:- pred write_foreign_dependency_for_il(io.output_stream::in, sym_name::in,
+    list(module_name)::in, foreign_import_module_info_list::in,
+    foreign_language::in, io::di, io::uo) is det.
+
+write_foreign_dependency_for_il(DepStream, ModuleName, AllDeps,
+        ForeignImports, ForeignLang, !IO) :-
+    (
+        ForeignModuleName = foreign_language_module_name(ModuleName,
+            ForeignLang),
+        ForeignExt = foreign_language_file_extension(ForeignLang)
+    ->
+        module_name_to_make_var_name(ForeignModuleName,
+            ForeignModuleNameString),
+        module_name_to_file_name(ForeignModuleName, ForeignExt,
+            do_not_create_dirs, ForeignFileName, !IO),
+        module_name_to_file_name(ModuleName, ".il", do_not_create_dirs,
+            IlFileName, !IO),
+        module_name_to_file_name(ModuleName, ".dll", do_not_create_dirs,
+            DllFileName, !IO),
+        module_name_to_file_name(ForeignModuleName, ".dll", do_not_create_dirs,
+            ForeignDllFileName, !IO),
+
+        io.write_strings(DepStream,
+            [ForeignDllFileName, " : ", DllFileName], !IO),
+        % XXX This change doesn't work correctly because mmake can't find
+        % the dlls which don't reside in the current directory.
+        % write_dll_dependencies_list(ModuleName, AllDeps, DepStream, !IO),
+        io.nl(DepStream, !IO),
+
+        io.write_strings(DepStream,
+            [ForeignFileName, " : ", IlFileName, "\n\n"], !IO),
+
+        (
+            ForeignLang = lang_csharp,
+            % Store in the variable CSHARP_ASSEMBLY_REFS-foreign_code_name
+            % the command line argument to reference all the dlls the
+            % foreign code module references.
+            io.write_strings(DepStream,
+                ["CSHARP_ASSEMBLY_REFS-", ForeignModuleNameString, "="], !IO),
+            ( mercury_std_library_module_name(ModuleName) ->
+                Prefix = "/addmodule:"
+            ;
+                Prefix = "/r:"
+            ),
+            ForeignDeps = list.map(
+                (func(M) = foreign_import_module_name_from_module(M,
+                    ModuleName)),
+                ForeignImports),
+            Deps = AllDeps ++ ForeignDeps,
+            write_dll_dependencies_list(referenced_dlls(ModuleName, Deps),
+                Prefix, DepStream, !IO),
+            io.nl(DepStream, !IO)
+        ;
+            ( ForeignLang = lang_c
+            ; ForeignLang = lang_java
+            ; ForeignLang = lang_il
+            ; ForeignLang = lang_erlang
+            )
+        )
+    ;
+        % This foreign language doesn't generate an external file
+        % so there are no dependencies to generate.
+        true
+    ).
+
+    % With `--use-subdirs', allow users to type `mmake module.c'
+    % rather than `mmake Mercury/cs/module.c'.
+    %
+:- pred write_subdirs_shorthand_rule(io.output_stream::in,
+    module_name::in, string::in, io::di, io::uo) is det.
+
+write_subdirs_shorthand_rule(DepStream, ModuleName, Ext, !IO) :-
+    module_name_to_file_name(ModuleName, ModuleStr),
+    module_name_to_file_name(ModuleName, Ext, do_not_create_dirs, Target, !IO),
+    ShorthandTarget = ModuleStr ++ Ext,
+    io.write_string(DepStream, ".PHONY: ", !IO),
+    io.write_string(DepStream, ShorthandTarget, !IO),
+    io.nl(DepStream, !IO),
+    io.write_string(DepStream, ShorthandTarget, !IO),
+    io.write_string(DepStream, ": ", !IO),
+    io.write_string(DepStream, Target, !IO),
+    io.nl(DepStream, !IO).
+
+%-----------------------------------------------------------------------------%
+
+generate_dependencies_write_dv_file(SourceFileName, ModuleName, DepsMap,
+        !IO) :-
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    module_name_to_file_name(ModuleName, ".dv", do_create_dirs,
+        DvFileName, !IO),
+    maybe_write_string(Verbose, "% Creating auto-dependency file `", !IO),
+    maybe_write_string(Verbose, DvFileName, !IO),
+    maybe_write_string(Verbose, "'...\n", !IO),
+    io.open_output(DvFileName, DvResult, !IO),
+    (
+        DvResult = ok(DvStream),
+        generate_dv_file(SourceFileName, ModuleName, DepsMap, DvStream, !IO),
+        io.close_output(DvStream, !IO),
+        maybe_write_string(Verbose, "% done.\n", !IO)
+    ;
+        DvResult = error(IOError),
+        maybe_write_string(Verbose, " failed.\n", !IO),
+        maybe_flush_output(Verbose, !IO),
+        io.error_message(IOError, IOErrorMessage),
+        string.append_list(["error opening file `", DvFileName,
+            "' for output: ", IOErrorMessage], DvMessage),
+        report_error(DvMessage, !IO)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+generate_dependencies_write_dep_file(SourceFileName, ModuleName, DepsMap,
+        !IO) :-
+    globals.io_lookup_bool_option(verbose, Verbose, !IO),
+    module_name_to_file_name(ModuleName, ".dep", do_create_dirs,
+        DepFileName, !IO),
+    maybe_write_string(Verbose, "% Creating auto-dependency file `", !IO),
+    maybe_write_string(Verbose, DepFileName, !IO),
+    maybe_write_string(Verbose, "'...\n", !IO),
+    io.open_output(DepFileName, DepResult, !IO),
+    (
+        DepResult = ok(DepStream),
+        generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO),
+        io.close_output(DepStream, !IO),
+        maybe_write_string(Verbose, "% done.\n", !IO)
+    ;
+        DepResult = error(IOError),
+        maybe_write_string(Verbose, " failed.\n", !IO),
+        maybe_flush_output(Verbose, !IO),
+        io.error_message(IOError, IOErrorMessage),
+        string.append_list(["error opening file `", DepFileName,
+            "' for output: ", IOErrorMessage], DepMessage),
+        report_error(DepMessage, !IO)
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred generate_dv_file(file_name::in, module_name::in, deps_map::in,
+    io.output_stream::in, io::di, io::uo) is det.
+
+generate_dv_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO) :-
+    io.write_string(DepStream,
+        "# Automatically generated dependency variables for module `", !IO),
+    ModuleNameString = sym_name_to_string(ModuleName),
+    io.write_string(DepStream, ModuleNameString, !IO),
+    io.write_string(DepStream, "'\n", !IO),
+    io.write_string(DepStream, "# generated from source file `", !IO),
+    io.write_string(DepStream, SourceFileName, !IO),
+    io.write_string(DepStream, "'\n", !IO),
+
+    library.version(Version),
+    io.write_string(DepStream,
+        "# Generated by the Mercury compiler, version ", !IO),
+    io.write_string(DepStream, Version, !IO),
+    io.write_string(DepStream, ".\n\n", !IO),
+
+    map.keys(DepsMap, Modules0),
+    select_ok_modules(Modules0, DepsMap, Modules1),
+    list.sort(compare_module_names, Modules1, Modules),
+
+    module_name_to_make_var_name(ModuleName, MakeVarName),
+    list.map(get_source_file(DepsMap), Modules, SourceFiles0),
+    list.sort_and_remove_dups(SourceFiles0, SourceFiles),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".ms =", !IO),
+    write_file_dependencies_list(SourceFiles, ".m", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".errs =", !IO),
+    write_file_dependencies_list(SourceFiles, ".err", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".mods =", !IO),
+    write_dependencies_list(Modules, "", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    % The modules for which we need to generate .int0 files.
+    ModulesWithSubModules = list.filter(
+      (pred(Module::in) is semidet :-
+          map.lookup(DepsMap, Module, deps(_, ModuleImports)),
+          ModuleImports ^ children = [_ | _]
+      ), Modules),
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".parent_mods =", !IO),
+    write_dependencies_list(ModulesWithSubModules, "", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    globals.io_get_target(Target, !IO),
+    (
+        Target = target_il,
+        ForeignModulesAndExts = foreign_modules(Modules, DepsMap)
+    ;
+        ( Target = target_c
+        ; Target = target_java
+        ; Target = target_asm
+        ; Target = target_x86_64
+        ; Target = target_erlang
+        ),
+        ForeignModulesAndExts = []
+    ),
+    ForeignModules = assoc_list.keys(ForeignModulesAndExts),
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".foreign =", !IO),
+    write_dependencies_list(ForeignModules, "", DepStream, !IO),
+    io.write_string(DepStream, "\n\n", !IO),
+
+    globals.io_lookup_bool_option(assume_gmake, Gmake, !IO),
+    (
+        Gmake = yes,
+        string.append(MakeVarName, ".mods", ModsVarName),
+        Basis = yes(ModsVarName - ""),
+
+        string.append(MakeVarName, ".foreign", ForeignVarName),
+        ForeignBasis = yes(ForeignVarName - ""),
+
+        string.append(MakeVarName, ".parent_mods", ParentModsVarName),
+        ParentBasis = yes(ParentModsVarName - "")
+    ;
+        Gmake = no,
+        Basis = no,
+        ForeignBasis = no,
+        ParentBasis = no
+    ),
+
+    get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs),
+
+    MakeFileName = (pred(M - E::in, F::out, IO0::di, IO::uo) is det :-
+        module_name_to_file_name(M, E, do_create_dirs, F0, IO0, IO),
+        F = "$(os_subdir)" ++ F0
+    ),
+
+    list.map_foldl(MakeFileName, ForeignModulesAndExts, ForeignFileNames, !IO),
+
+    % .foreign_cs are the source files which have had foreign code placed
+    % in them.
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".foreign_cs = ", !IO),
+    write_file_dependencies_list(ForeignFileNames, "", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    % The dlls that contain the foreign_code.
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".foreign_dlls = ", !IO),
+    write_compact_dependencies_list(ForeignModules, "$(dlls_subdir)",
+        ".dll", ForeignBasis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".init_cs = ", !IO),
+    write_compact_dependencies_list(Modules, "$(cs_subdir)", ".c",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".cs = $(", !IO),
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".init_cs) ", !IO),
+    write_extra_link_dependencies_list(ExtraLinkObjs, ".c", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".dlls = ", !IO),
+    write_compact_dependencies_list(Modules, "$(dlls_subdir)", ".dll",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_ss = ", !IO),
+    write_compact_dependencies_list(Modules, "$(ss_subdir)", ".s",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_pic_ss = ", !IO),
+    write_compact_dependencies_list(Modules, "$(pic_ss_subdir)", ".pic_s",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_s_dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(s_dates_subdir)",
+        ".s_date", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_pic_s_dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(pic_s_dates_subdir)",
+        ".pic_s_date", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_os = ", !IO),
+    write_compact_dependencies_list(Modules, "$(os_subdir)", ".$O",
+        Basis, DepStream, !IO),
+    write_extra_link_dependencies_list(ExtraLinkObjs, ".$O", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_pic_os = ", !IO),
+    write_compact_dependencies_list(Modules, "$(os_subdir)",
+        ".$(EXT_FOR_PIC_OBJECTS)", Basis, DepStream, !IO),
+    write_extra_link_dependencies_list(ExtraLinkObjs,
+        ".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    IsNested = (pred(Mod::in) is semidet :-
+        get_submodule_kind(Mod, DepsMap) = nested_submodule
+    ),
+    (
+        % For --target asm, we only generate separate object files
+        % for top-level modules and separate sub-modules, not for
+        % nested sub-modules.
+        Target = target_asm,
+        list.filter(IsNested, Modules, NestedModules, MainModules),
+        NestedModules = [_ | _]
+    ->
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".ss = ", !IO),
+        write_dependencies_list(MainModules, ".s", DepStream, !IO),
+        io.write_string(DepStream, "\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".pic_ss = ", !IO),
+        write_dependencies_list(MainModules, ".pic_s", DepStream, !IO),
+        io.write_string(DepStream, "\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".s_dates = ", !IO),
+        write_dependencies_list(MainModules, ".s_date", DepStream, !IO),
+        io.write_string(DepStream, "\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".pic_s_dates = ", !IO),
+        write_dependencies_list(MainModules, ".pic_s_date", DepStream, !IO),
+        io.write_string(DepStream, "\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".os = ", !IO),
+        write_dependencies_list(MainModules, ".$O", DepStream, !IO),
+        write_extra_link_dependencies_list(ExtraLinkObjs, ".$O", DepStream,
+            !IO),
+        io.write_string(DepStream, "\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".pic_os = ", !IO),
+        write_dependencies_list(MainModules, ".$(EXT_FOR_PIC_OBJECTS)",
+            DepStream, !IO),
+        write_extra_link_dependencies_list(ExtraLinkObjs,
+            ".$(EXT_FOR_PIC_OBJECTS)", DepStream, !IO),
+        io.write_string(DepStream, "\n", !IO)
+    ;
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".ss = $(", !IO),
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".all_ss)\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".pic_ss = $(", !IO),
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".all_pic_ss)\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".s_dates = $(", !IO),
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".all_s_dates)\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".pic_s_dates = $(", !IO),
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".all_pic_s_dates)\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".os = $(", !IO),
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".all_os)\n", !IO),
+
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".pic_os = $(", !IO),
+        io.write_string(DepStream, MakeVarName, !IO),
+        io.write_string(DepStream, ".all_pic_os)\n", !IO)
+    ),
+
+    % $(foo.cs_or_ss) contains the names of the generated intermediate
+    % files between `.m' and `.o' files. This is used in foo.dep
+    % to make sure the intermediate files are generated before the
+    % object files, so that errors are reported as soon as possible.
+    %
+    % If TARGET_ASM=yes, we define $(foo.cs_or_ss) to be $(foo.ss),
+    % otherwise it is defined to be $(foo.cs).
+
+    io.write_strings(DepStream, [
+        "ifeq ($(TARGET_ASM),yes)\n",
+        MakeVarName, ".cs_or_ss =$(", MakeVarName, ".ss)\n",
+        "else\n",
+        MakeVarName, ".cs_or_ss =$(", MakeVarName, ".cs)\n",
+        "endif\n\n"
+    ], !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".useds = ", !IO),
+    write_compact_dependencies_list(Modules, "$(useds_subdir)", ".used",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".ils = ", !IO),
+    write_compact_dependencies_list(Modules, "$(ils_subdir)", ".il",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".javas = ", !IO),
+    write_compact_dependencies_list(Modules, "$(javas_subdir)", ".java",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".classes = ", !IO),
+    write_compact_dependencies_list(Modules, "$(classes_subdir)", ".class",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, " ", !IO),
+    % The Java compiler creates a .class file for each class
+    % within the original .java file.  The filenames of all
+    % these can be matched with `module\$*.class', hence the
+    % "\\$$*.class" below.
+    % If no such files exist, Make will use the pattern verbatim,
+    % so we enclose the pattern in a `wildcard' function to prevent this.
+    % XXX This relies on GNU Make.
+    io.write_string(DepStream, "$(wildcard ", !IO),
+    write_compact_dependencies_list(Modules, "$(classes_subdir)",
+        "\\$$*.class", Basis, DepStream, !IO),
+    io.write_string(DepStream, ")\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".dirs = ", !IO),
+    write_compact_dependencies_list(Modules, "$(dirs_subdir)", ".dir",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".dir_os = ", !IO),
+    write_compact_dependencies_list(Modules, "$(dirs_subdir)", ".dir/*.$O",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(dates_subdir)", ".date",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".date0s = ", !IO),
+    write_compact_dependencies_list(Modules, "$(date0s_subdir)", ".date0",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".date3s = ", !IO),
+    write_compact_dependencies_list(Modules, "$(date3s_subdir)", ".date3",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".optdates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(optdates_subdir)",
+        ".optdate", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".trans_opt_dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(trans_opt_dates_subdir)",
+        ".trans_opt_date", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".c_dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(c_dates_subdir)",
+        ".c_date", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".il_dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(il_dates_subdir)",
+        ".il_date", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".java_dates = ", !IO),
+    write_compact_dependencies_list(Modules, "$(java_dates_subdir)",
+        ".java_date", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".ds = ", !IO),
+    write_compact_dependencies_list(Modules, "$(ds_subdir)", ".d",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".module_deps = ", !IO),
+    write_compact_dependencies_list(Modules, "$(module_deps_subdir)",
+        make_module_dep_file_extension, Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".mihs = ", !IO),
+    globals.io_lookup_bool_option(highlevel_code, HighLevelCode, !IO),
+    (
+        HighLevelCode = yes,
+        (
+            ( Target = target_c
+            ; Target = target_asm
+            ),
+            % For the `--target c' MLDS back-end, we generate `.mih' files
+            % for every module.  Likewise for the `--target asm' back-end.
+            % (For the `--target asm' back-end, we previously used to do
+            % that only for modules that contain C code, but this caused
+            % trouble when trying to interoperate between compiled with
+            % `--target c' and code compiled with `--target asm', so now we
+            % generate them unconditionally.)
+            write_compact_dependencies_list(Modules,
+                "$(mihs_subdir)", ".mih", Basis, DepStream, !IO)
+        ;
+            % For the IL and Java targets, currently we don't generate
+            % `.mih' files at all; although perhaps we should...
+            ( Target = target_il
+            ; Target = target_java
+            ; Target = target_erlang
+            )
+        ;
+            Target = target_x86_64,
+            unexpected(this_file, "--highlevel-code with --target x86_64")
+        )
+    ;
+        % For the LLDS back-end, we don't use `.mih' files at all
+        HighLevelCode = no
+    ),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".mhs = ", !IO),
+    (
+        ( Target = target_c
+        ; Target = target_asm
+        ; Target = target_x86_64
+        ),
+        write_compact_dependencies_list(Modules, "", ".mh", Basis,
+            DepStream, !IO)
+    ;
+        ( Target = target_il
+        ; Target = target_java
+        ; Target = target_erlang
+        )
+    ),
+    io.write_string(DepStream, "\n", !IO),
+
+    % The `<module>.all_mihs' variable is like `<module>.mihs' except
+    % that it contains header files for all the modules, regardless
+    % of the grade or --target option.  It is used by the rule for
+    % `mmake realclean', which should remove anything that could have
+    % been automatically generated, even if the grade or --target option
+    % has changed.
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_mihs = ", !IO),
+    write_compact_dependencies_list(Modules, "$(mihs_subdir)", ".mih",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    % The `<module>.all_mhs' variable is like `<module>.mhs' except
+    % that it contains header files for all the modules, as for
+    % `<module>.all_mihs' above.
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_mhs = ", !IO),
+    write_compact_dependencies_list(Modules, "", ".mh", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".ints = ", !IO),
+    write_compact_dependencies_list(Modules, "$(ints_subdir)", ".int",
+        Basis, DepStream, !IO),
+    write_compact_dependencies_separator(Basis, DepStream, !IO),
+    write_compact_dependencies_list(Modules, "$(int2s_subdir)", ".int2",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    % `.int0' files are only generated for modules with sub-modules.
+    % XXX ... or at least they should be.  Currently we end up generating
+    % .int0 files for nested submodules that don't have any children.
+    % (We do the correct thing for separate sub-modules.)
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".int0s = ", !IO),
+    write_compact_dependencies_list(ModulesWithSubModules, "$(int0s_subdir)",
+         ".int0", ParentBasis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    % XXX The `<module>.all_int0s' variables is like `<module>.int0s' except
+    % that it contains .int0 files for all modules, regardless of whether
+    % they should have been created or not.  It is used by the rule for
+    % `mmake realclean' to ensure that we clean up all the .int0 files,
+    % including the ones that were accidently created by the bug described
+    % above.
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".all_int0s = ", !IO),
+    write_compact_dependencies_list(Modules, "$(int0s_subdir)", ".int0",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".int3s = ", !IO),
+    write_compact_dependencies_list(Modules, "$(int3s_subdir)", ".int3",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".opts = ", !IO),
+    write_compact_dependencies_list(Modules, "$(opts_subdir)", ".opt",
+        Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".trans_opts = ", !IO),
+    write_compact_dependencies_list(Modules, "$(trans_opts_subdir)",
+        ".trans_opt", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".analysiss = ", !IO),
+    write_compact_dependencies_list(Modules, "$(analysiss_subdir)",
+        ".analysis", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".requests = ", !IO),
+    write_compact_dependencies_list(Modules, "$(requests_subdir)",
+        ".request", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".imdgs = ", !IO),
+    write_compact_dependencies_list(Modules, "$(imdgs_subdir)",
+        ".imdg", Basis, DepStream, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    io.write_string(DepStream, MakeVarName, !IO),
+    io.write_string(DepStream, ".profs = ", !IO),
+    write_compact_dependencies_list(Modules, "", ".prof", Basis, DepStream,
+        !IO),
+    io.write_string(DepStream, "\n\n", !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- pred select_ok_modules(list(module_name)::in, deps_map::in,
+    list(module_name)::out) is det.
+
+select_ok_modules([], _, []).
+select_ok_modules([Module | Modules0], DepsMap, Modules) :-
+    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
+    module_imports_get_error(ModuleImports, Error),
+    ( Error = fatal_module_errors ->
+        Modules = Modules1
+    ;
+        Modules = [Module | Modules1]
+    ),
+    select_ok_modules(Modules0, DepsMap, Modules1).
+
+%-----------------------------------------------------------------------------%
+
+    % Find out which modules will generate as external foreign
+    % language files.
+    % We return the module names and file extensions.
+    %
+:- func foreign_modules(list(module_name), deps_map)
+    = assoc_list(module_name, string).
+
+foreign_modules(Modules, DepsMap) = ForeignModules :-
+    P = (pred(M::in, FMs::out) is semidet :-
+        module_has_foreign(DepsMap, M, LangList),
+        FMs = list.filter_map((func(L) = (NewM - Ext) is semidet :-
+            NewM = foreign_language_module_name(M, L),
+            Ext = foreign_language_file_extension(L)
+        ), LangList)
+    ),
+    list.filter_map(P, Modules, ForeignModulesList),
+    ForeignModules = list.condense(ForeignModulesList).
+
+    % Succeed iff we need to generate a foreign language output file
+    % for the specified module.
+    %
+:- pred module_has_foreign(deps_map::in, module_name::in,
+    list(foreign_language)::out) is semidet.
+
+module_has_foreign(DepsMap, Module, LangList) :-
+    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
+    ModuleImports ^ has_foreign_code = contains_foreign_code(Langs),
+    LangList = set.to_sorted_list(Langs).
+
+%-----------------------------------------------------------------------------%
+
+    % get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs):
+    %
+    % Find any extra .$O files that should be linked into the executable.
+    % These include fact table object files and object files for foreign
+    % code that can't be generated inline for this target.
+    %
+:- pred get_extra_link_objects(list(module_name)::in, deps_map::in,
+    compilation_target::in, assoc_list(file_name, module_name)::out) is det.
+
+get_extra_link_objects(Modules, DepsMap, Target, ExtraLinkObjs) :-
+    get_extra_link_objects_2(Modules, DepsMap, Target, [], ExtraLinkObjs0),
+    list.reverse(ExtraLinkObjs0, ExtraLinkObjs).
+
+:- pred get_extra_link_objects_2(list(module_name)::in, deps_map::in,
+    compilation_target::in,
+    assoc_list(file_name, module_name)::in,
+    assoc_list(file_name, module_name)::out) is det.
+
+get_extra_link_objects_2([], _DepsMap, _Target, !ExtraLinkObjs).
+get_extra_link_objects_2([Module | Modules], DepsMap, Target,
+        !ExtraLinkObjs) :-
+    map.lookup(DepsMap, Module, deps(_, ModuleImports)),
+
+    % Handle object files for fact tables.
+    FactDeps = ModuleImports ^ fact_table_deps,
+    list.length(FactDeps, NumFactDeps),
+    list.duplicate(NumFactDeps, Module, ModuleList),
+    assoc_list.from_corresponding_lists(FactDeps, ModuleList, FactTableObjs),
+
+    % Handle object files for foreign code.
+    % XXX Currently we only support `C' foreign code.
+    (
+        Target = target_asm,
+        ModuleImports ^ has_foreign_code = contains_foreign_code(Langs),
+        set.member(lang_c, Langs)
+    ->
+        FileName = sym_name_to_string(Module),
+        NewLinkObjs = [(FileName ++ "__c_code") - Module | FactTableObjs]
+    ;
+        NewLinkObjs = FactTableObjs
+    ),
+    list.append(NewLinkObjs, !ExtraLinkObjs),
+    get_extra_link_objects_2(Modules, DepsMap, Target, !ExtraLinkObjs).
+
+%-----------------------------------------------------------------------------%
+
+:- pred generate_dep_file(file_name::in, module_name::in, deps_map::in,
+    io.output_stream::in, io::di, io::uo) is det.
+
+generate_dep_file(SourceFileName, ModuleName, DepsMap, DepStream, !IO) :-
+    io.write_string(DepStream,
+        "# Automatically generated dependencies for module `", !IO),
+    ModuleNameString = sym_name_to_string(ModuleName),
+    io.write_string(DepStream, ModuleNameString, !IO),
+    io.write_string(DepStream, "'\n", !IO),
+    io.write_string(DepStream,
+        "# generated from source file `", !IO),
+    io.write_string(DepStream, SourceFileName, !IO),
+    io.write_string(DepStream, "'\n", !IO),
+
+    library.version(Version),
+    io.write_string(DepStream,
+        "# Generated by the Mercury compiler, version ", !IO),
+    io.write_string(DepStream, Version, !IO),
+    io.write_string(DepStream, ".\n\n", !IO),
+
+    module_name_to_make_var_name(ModuleName, MakeVarName),
+
+    module_name_to_file_name(ModuleName, ".init", do_create_dirs,
+        InitFileName, !IO),
+    module_name_to_file_name(ModuleName, "_init.c", do_create_dirs,
+        InitCFileName, !IO),
+    module_name_to_file_name(ModuleName, "_init.s", do_not_create_dirs,
+        InitAsmFileName, !IO),
+    module_name_to_file_name(ModuleName, "_init.$O", do_create_dirs,
+        InitObjFileName, !IO),
+    module_name_to_file_name(ModuleName, "_init.pic_o", do_create_dirs,
+        InitPicObjFileName, !IO),
+
+    % Note we have to do some ``interesting'' hacks to get
+    % `$(ALL_MLLIBS_DEP)' to work in the dependency list
+    % (and not complain about undefined variables).
+    % These hacks rely on features of GNU Make, so should not be used
+    % if we cannot assume we are using GNU Make.
+    globals.io_lookup_bool_option(assume_gmake, Gmake, !IO),
+    (
+        Gmake = yes,
+        append_list(["\\\n\t\t$(foreach @,", MakeVarName,
+            ",$(ALL_MLLIBS_DEP))"],
+            All_MLLibsDepString),
+        append_list(["\\\n\t\t$(foreach @,", MakeVarName,
+            ",$(ALL_MLOBJS))"],
+            All_MLObjsString),
+        append_list([
+        "\\\n\t\t$(patsubst %.o,%.$(EXT_FOR_PIC_OBJECTS),$(foreach @,",
+            MakeVarName, ",$(ALL_MLOBJS)))"],
+            All_MLPicObjsString)
+    ;
+        Gmake = no,
+        All_MLLibsDepString = "$(ALL_MLLIBS_DEP)",
+        All_MLObjsString = "$(ALL_MLOBJS)",
+        All_MLPicObjsString = "$(ALL_MLPICOBJS)"
+    ),
+
+    % When compiling to C, we want to include $(foo.cs) first in
+    % the dependency list, before $(foo.os).
+    % This is not strictly necessary, since the .$O files themselves depend
+    % on the .c files, but want to do it to ensure that Make will try to
+    % create all the C files first, thus detecting errors early,
+    % rather than first spending time compiling C files to .$O,
+    % which could be a waste of time if the program contains errors.
+    %
+    % When compiling to assembler, we want to do the same kind of thing,
+    % for the same reason, but with the `.s' files rather than the `.c' files.
+
+    module_name_to_file_name(ModuleName, "", do_not_create_dirs,
+        ExeFileName, !IO),
+
+    IfIL = ["ifeq ($(findstring il,$(GRADE)),il)\n"],
+    ILMainRule = [ExeFileName, " : ", ExeFileName, ".exe\n",
+        ExeFileName, ".exe : ", "$(", MakeVarName, ".dlls) ",
+        "$(", MakeVarName, ".foreign_dlls)\n"],
+    Else = ["else\n"],
+    IfJava = [" ifeq ($(findstring java,$(GRADE)),java)\n"],
+    JavaMainRule = [ExeFileName, " : $(", MakeVarName, ".classes)\n"],
+    Else2 = [" else\n"],
+    EndIf2 = [" endif\n"],
+
+    % XXX The output here is GNU Make-specific.
+    io.write_strings(DepStream, [
+        "ifneq ($(EXT_FOR_EXE),)\n",
+        ".PHONY : ", ExeFileName, "\n",
+        ExeFileName, " : ", ExeFileName, "$(EXT_FOR_EXE)\n",
+        "endif\n"
+    ], !IO),
+
+    MainRule =
+        [ExeFileName, "$(EXT_FOR_EXE) : $(", MakeVarName, ".cs_or_ss) ",
+            "$(", MakeVarName, ".os) ", InitObjFileName, " ",
+            All_MLObjsString, " ", All_MLLibsDepString, "\n",
+        "\t$(ML) $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) -- $(ALL_LDFLAGS) ",
+            "-o ", ExeFileName, "$(EXT_FOR_EXE) ", InitObjFileName, " \\\n",
+        "\t\t$(", MakeVarName, ".os) ", All_MLObjsString, " $(ALL_MLLIBS)\n"],
+    EndIf = ["endif\n"],
+
+    globals.io_get_target(Target, !IO),
+    (
+        Gmake = yes,
+        Rules = IfIL ++ ILMainRule ++ Else ++
+            IfJava ++ JavaMainRule ++ Else2 ++
+            MainRule ++ EndIf2 ++ EndIf
+    ;
+        Gmake = no,
+        (
+            Target = target_il,
+            Rules = ILMainRule
+        ;
+            Target = target_java,
+            Rules = JavaMainRule
+        ;
+            Target = target_erlang,
+            % XXX not yet
+            Rules = []
+        ;
+            ( Target = target_c
+            ; Target = target_asm
+            ; Target = target_x86_64    % XXX this is only provisional.
+            ),
+            Rules = MainRule
+        )
+    ),
+    io.write_strings(DepStream, Rules, !IO),
+
+    globals.io_lookup_bool_option(intermodule_optimization, Intermod, !IO),
+    (
+        Intermod = yes,
+        string.append_list(["$(", MakeVarName, ".opts) "], MaybeOptsVar)
+    ;
+        Intermod = no,
+        MaybeOptsVar = ""
+    ),
+    globals.io_lookup_bool_option(transitive_optimization, TransOpt, !IO),
+    (
+        TransOpt = yes,
+        string.append_list(["$(", MakeVarName, ".trans_opts) "],
+            MaybeTransOptsVar)
+    ;
+        TransOpt = no,
+        MaybeTransOptsVar = ""
+    ),
+    globals.io_lookup_bool_option(generate_mmc_make_module_dependencies,
+        MmcMakeDeps, !IO),
+    (
+        MmcMakeDeps = yes,
+        string.append_list(["$(", MakeVarName, ".module_deps) "],
+            MaybeModuleDepsVar)
+    ;
+        MmcMakeDeps = no,
+        MaybeModuleDepsVar = ""
+    ),
+
+    module_name_to_lib_file_name("lib", ModuleName, "", do_not_create_dirs,
+        LibTargetName, !IO),
+    module_name_to_lib_file_name("lib", ModuleName, ".$A", do_create_dirs,
+        LibFileName, !IO),
+    module_name_to_lib_file_name("lib", ModuleName, ".$(EXT_FOR_SHARED_LIB)",
+        do_create_dirs, SharedLibFileName, !IO),
+    module_name_to_lib_file_name("lib", ModuleName, ".$(EXT_FOR_SHARED_LIB)",
+        do_not_create_dirs, MaybeSharedLibFileName, !IO),
+    module_name_to_file_name(ModuleName, ".jar", do_not_create_dirs,
+        JarFileName, !IO),
+
+    % Set up the installed name for shared libraries.
+
+    globals.io_lookup_bool_option(shlib_linker_use_install_name,
+        UseInstallName, !IO),
+    (
+        UseInstallName = yes,
+        get_install_name_option(SharedLibFileName, InstallNameOpt, !IO)
+    ;
+        UseInstallName = no,
+        InstallNameOpt = ""
+    ),
+
+    AllInts = [
+        "$(", MakeVarName, ".ints) ",
+        "$(", MakeVarName, ".int3s) ",
+        MaybeOptsVar, MaybeTransOptsVar,
+        InitFileName, "\n\n"
+    ],
+    ILLibRule = [
+        LibTargetName, " : ", "$(", MakeVarName, ".dlls) ",
+            "$(", MakeVarName, ".foreign_dlls) \\\n\t\t"
+        | AllInts
+    ],
+    JavaLibRule = [
+        LibTargetName, " : ", JarFileName, " \\\n\t\t"
+        | AllInts
+    ],
+    LibRule = [
+        LibTargetName, " : ", LibFileName, " ",
+        MaybeSharedLibFileName, " \\\n\t\t"
+        | AllInts
+    ],
+    (
+        Gmake = yes,
+        LibRules = IfIL ++ ILLibRule ++ Else ++
+            IfJava ++ JavaLibRule ++ Else2 ++
+            LibRule ++ EndIf2 ++ EndIf
+    ;
+        Gmake = no,
+        (
+            Target = target_il,
+            LibRules = ILLibRule
+        ;
+            Target = target_java,
+            LibRules = JavaLibRule
+        ;
+            Target = target_erlang,
+            % XXX not done yet
+            LibRules = []
+        ;
+            ( Target = target_c
+            ; Target = target_asm
+            ; Target = target_x86_64    % XXX This is only provisional.
+            ),
+            LibRules = LibRule
+        )
+    ),
+    io.write_strings(DepStream, [
+        ".PHONY : ", LibTargetName, "\n" |
+        LibRules
+    ], !IO),
+
+    io.write_strings(DepStream, [
+        "ifneq ($(EXT_FOR_SHARED_LIB),$A)\n",
+        SharedLibFileName, " : $(", MakeVarName, ".cs_or_ss) ",
+            "$(", MakeVarName, ".pic_os) ",
+            All_MLPicObjsString, " ", All_MLLibsDepString, "\n",
+        "\t$(ML) --make-shared-lib $(ALL_GRADEFLAGS) $(ALL_MLFLAGS) ",
+            "-- ", InstallNameOpt, " $(ALL_LD_LIBFLAGS) -o ",
+            SharedLibFileName, " \\\n",
+        "\t\t$(", MakeVarName, ".pic_os) ", All_MLPicObjsString,
+            " $(ALL_MLLIBS)\n",
+        "endif\n\n"
+    ], !IO),
+
+    io.write_strings(DepStream, [
+        LibFileName, " : $(", MakeVarName, ".cs_or_ss) ",
+            "$(", MakeVarName, ".os) ", All_MLObjsString, "\n",
+        "\trm -f ", LibFileName, "\n",
+        "\t$(AR) $(ALL_ARFLAGS) $(AR_LIBFILE_OPT)", LibFileName, " ",
+            "$(", MakeVarName, ".os) ", All_MLObjsString, "\n",
+        "\t$(RANLIB) $(ALL_RANLIBFLAGS) ", LibFileName, "\n\n"
+    ], !IO),
+
+    ClassFiles = "$(" ++ MakeVarName ++ ".classes)",
+    list_class_files_for_jar(ModuleName, ClassFiles, ListClassFiles, !IO),
+    io.write_strings(DepStream, [
+        JarFileName, " : ", "$(", MakeVarName, ".classes)\n",
+        "\t$(JAR) $(JAR_CREATE_FLAGS) ", JarFileName, " ",
+        ListClassFiles, "\n\n"
+    ], !IO),
+
+    module_name_to_file_name(ModuleName, ".dep", do_not_create_dirs,
+        DepFileName, !IO),
+    module_name_to_file_name(ModuleName, ".dv", do_not_create_dirs,
+        DvFileName, !IO),
+
+    io.write_strings(DepStream, [
+        InitFileName, " : ", DepFileName, " $(", MakeVarName, ".cs)\n",
+        "\techo > ", InitFileName, "\n"
+    ], !IO),
+    io.write_strings(DepStream, [
+        "\t$(MKLIBINIT) ", "$(", MakeVarName, ".cs)", " >> ",
+        InitFileName, "\n"
+    ], !IO),
+
+    % $(EXTRA_INIT_COMMAND) should expand to a command to
+    % generate extra entries in the `.init' file for a library.
+    % It may expand to the empty string.
+    io.write_string(DepStream, "\t$(EXTRA_INIT_COMMAND) >> ", !IO),
+    io.write_string(DepStream, InitFileName, !IO),
+    io.write_string(DepStream, "\n", !IO),
+
+    % The `force-module_init' dependency forces the commands for
+    % the `module_init.c' rule to be run every time the rule
+    % is considered.
+    ModuleFileName = sym_name_to_string(ModuleName),
+    ForceC2InitTarget = "force-" ++ ModuleFileName ++ "_init",
+    TmpInitCFileName = InitCFileName ++ ".tmp",
+    io.write_strings(DepStream, [
+        ForceC2InitTarget, " :\n\n",
+        InitCFileName, " : ", ForceC2InitTarget, " $(", MakeVarName, ".cs)\n",
+        "\t@$(C2INIT) $(ALL_GRADEFLAGS) $(ALL_C2INITFLAGS) ",
+            "--init-c-file ", TmpInitCFileName,
+            " $(", MakeVarName, ".init_cs) $(ALL_C2INITARGS)\n",
+        "\t at mercury_update_interface ", InitCFileName, "\n\n"
+    ], !IO),
+
+    module_name_to_lib_file_name("lib", ModuleName, ".install_ints",
+        do_not_create_dirs, LibInstallIntsTargetName, !IO),
+    (
+        Intermod = yes,
+        OptStr = " opt"
+    ;
+        Intermod = no,
+        OptStr = ""
+    ),
+    (
+        Intermod = yes,
+        map.member(DepsMap, _, deps(_, Imports)),
+        Imports ^ children = [_ | _]
+    ->
+        % The `.int0' files only need to be installed with
+        % `--intermodule-optimization'.
+        Int0Str = " int0",
+        MaybeInt0sVar = "$(" ++ MakeVarName ++ ".int0s) "
+    ;
+        Int0Str = "",
+        MaybeInt0sVar = ""
+    ),
+    (
+        TransOpt = yes,
+        TransOptStr = " trans_opt"
+    ;
+        TransOpt = no,
+        TransOptStr = ""
+    ),
+    (
+        MmcMakeDeps = yes,
+        DepStr = " module_dep"
+    ;
+        MmcMakeDeps = no,
+        DepStr = ""
+    ),
+
+    io.write_strings(DepStream, [
+        ".PHONY : ", LibInstallIntsTargetName, "\n",
+        LibInstallIntsTargetName, " : $(", MakeVarName, ".ints) $(",
+            MakeVarName, ".int3s) ", MaybeInt0sVar, MaybeOptsVar,
+            MaybeTransOptsVar, MaybeModuleDepsVar,
+            " install_lib_dirs\n",
+        "\tfiles=""$(", MakeVarName, ".ints) $(", MakeVarName,
+            ".int3s) ", MaybeInt0sVar, MaybeOptsVar,
+            MaybeTransOptsVar, MaybeModuleDepsVar, """; \\\n",
+        "\tfor file in $$files; do \\\n",
+        "\t\ttarget=""$(INSTALL_INT_DIR)/`basename $$file`""; \\\n",
+        "\t\tif cmp -s ""$$file"" ""$$target""; then \\\n",
+        "\t\t\techo \"$$target unchanged\"; \\\n",
+        "\t\telse \\\n",
+        "\t\t\techo \"installing $$target\"; \\\n",
+        "\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
+        "\t\tfi; \\\n",
+        "\tdone\n",
+        "\t# The following is needed to support the `--use-subdirs' option\n",
+        "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
+        "\t# `$(INSTALL)'.\n",
+        "\tfor ext in int int2 int3",
+        Int0Str, OptStr, TransOptStr, DepStr,
+        "; do \\\n",
+        "\t\tdir=""$(INSTALL_INT_DIR)/Mercury/$${ext}s""; \\\n",
+        "\t\trm -rf ""$$dir""; \\\n",
+        "\t\t$(LN_S) .. ""$$dir"" || { \\\n",
+        "\t\t\t{ [ -d ""$$dir"" ] || \\\n",
+        "\t\t\t$(INSTALL_MKDIR) ""$$dir""; } && \\\n",
+        "\t\t\t$(INSTALL) ""$(INSTALL_INT_DIR)""/*.$$ext ""$$dir""; \\\n",
+        "\t\t} || exit 1; \\\n",
+        "\tdone\n\n"
+    ], !IO),
+
+    % XXX  Note that we install the `.opt' and `.trans_opt' files
+    % in two places: in the `lib/$(GRADE)/opts' directory, so
+    % that mmc will find them, and also in the `ints' directory,
+    % so that Mmake will find them.  That's not ideal, but it works.
+
+    module_name_to_lib_file_name("lib", ModuleName, ".install_opts",
+        do_not_create_dirs, LibInstallOptsTargetName, !IO),
+    io.write_strings(DepStream,
+        [".PHONY : ", LibInstallOptsTargetName, "\n",
+        LibInstallOptsTargetName, " : "], !IO),
+    (
+        Intermod = no,
+        TransOpt = no
+    ->
+        io.write_string(DepStream, "\n\t@:\n\n", !IO)
+    ;
+        io.write_strings(DepStream, [
+        MaybeOptsVar, MaybeTransOptsVar, "install_grade_dirs\n",
+        "\tfiles=""", MaybeOptsVar, MaybeTransOptsVar, """; \\\n",
+        "\tfor file in $$files; do \\\n",
+        "\t\ttarget=""$(INSTALL_GRADE_INT_DIR)/`basename $$file`"";\\\n",
+        "\t\tif cmp -s ""$$file"" ""$$target""; then \\\n",
+        "\t\t\techo \"$$target unchanged\"; \\\n",
+        "\t\telse \\\n",
+        "\t\t\techo \"installing $$target\"; \\\n",
+        "\t\t\t$(INSTALL) ""$$file"" ""$$target""; \\\n",
+        "\t\tfi; \\\n",
+        "\tdone\n",
+        "\t# The following is needed to support the `--use-subdirs' option\n",
+        "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
+        "\t# `$(INSTALL)'.\n",
+        "\tfor ext in ",
+        OptStr, TransOptStr,
+        "; do \\\n",
+        "\t\tdir=""$(INSTALL_GRADE_INT_DIR)/Mercury/$${ext}s""; \\\n",
+        "\t\trm -rf ""$$dir""; \\\n",
+        "\t\t$(LN_S) .. ""$$dir"" || { \\\n",
+        "\t\t\t{ [ -d ""$$dir"" ] || \\\n",
+        "\t\t\t\t$(INSTALL_MKDIR) ""$$dir""; } && \\\n",
+        "\t\t\t$(INSTALL) ""$(INSTALL_GRADE_INT_DIR)""/*.$$ext \\\n",
+        "\t\t\t\t""$$dir""; \\\n",
+        "\t\t} || exit 1; \\\n",
+        "\tdone\n\n"
+        ], !IO)
+    ),
+
+    % XXX  Note that we install the header files in two places:
+    % in the `lib/inc' or `lib/$(GRADE)/$(FULLARCH)/inc' directory,
+    % so that the C compiler will find them, and also in the `ints' directory,
+    % so that Mmake will find them.  That's not ideal, but it works.
+    %
+    % (A better fix would be to change the VPATH setting in
+    % scripts/Mmake.vars.in so that Mmake also searches the
+    % `lib/$(GRADE)/$(FULLARCH)/inc' directory, but doing that properly
+    % is non-trivial.)
+
+    module_name_to_lib_file_name("lib", ModuleName, ".install_hdrs",
+        do_not_create_dirs, LibInstallHdrsTargetName, !IO),
+    io.write_strings(DepStream, [
+        ".PHONY : ", LibInstallHdrsTargetName, "\n",
+        LibInstallHdrsTargetName, " : ",
+            "$(", MakeVarName, ".mhs) ",
+            "install_lib_dirs\n",
+        "ifeq ($(", MakeVarName, ".mhs),)\n",
+        "\t@:\n",
+        "else\n",
+        "\tfor hdr in $(", MakeVarName, ".mhs); do \\\n",
+        "\t\t$(INSTALL) $$hdr $(INSTALL_INT_DIR); \\\n",
+        "\t\t$(INSTALL) $$hdr $(INSTALL_INC_DIR); \\\n",
+        "\tdone\n",
+        "endif\n\n"], !IO),
+
+    module_name_to_lib_file_name("lib", ModuleName, ".install_grade_hdrs",
+        do_not_create_dirs, LibInstallGradeHdrsTargetName, !IO),
+    io.write_strings(DepStream, [
+        ".PHONY : ", LibInstallGradeHdrsTargetName, "\n",
+        LibInstallGradeHdrsTargetName, " : ",
+            "$(", MakeVarName, ".mihs) ",
+            "install_grade_dirs\n",
+    "ifeq ($(", MakeVarName, ".mihs),)\n",
+    "\t@:\n",
+    "else\n",
+    "\tfor hdr in $(", MakeVarName, ".mihs); do \\\n",
+    "\t\t$(INSTALL) $$hdr $(INSTALL_INT_DIR); \\\n",
+    "\t\t$(INSTALL) $$hdr $(INSTALL_GRADE_INC_DIR); \\\n",
+    "\tdone\n",
+    "\t# The following is needed to support the `--use-subdirs' option\n",
+    "\t# We try using `$(LN_S)', but if that fails, then we just use\n",
+    "\t# `$(INSTALL)'.\n",
+    "\trm -rf $(INSTALL_GRADE_INC_SUBDIR)\n",
+    "\t$(LN_S) .. $(INSTALL_GRADE_INC_SUBDIR) || { \\\n",
+    "\t\t{ [ -d $(INSTALL_GRADE_INC_SUBDIR) ] || \\\n",
+    "\t\t\t$(INSTALL_MKDIR) $(INSTALL_GRADE_INC_SUBDIR); \\\n",
+    "\t\t} && \\\n",
+    "\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
+    "\t\t\t$(INSTALL_GRADE_INC_SUBDIR); \\\n",
+    "\t} || exit 1\n",
+    "\trm -rf $(INSTALL_INT_DIR)/Mercury/mihs\n",
+    "\t$(LN_S) .. $(INSTALL_INT_DIR)/Mercury/mihs || { \\\n",
+    "\t\t{ [ -d $(INSTALL_INT_DIR)/Mercury/mihs ] || \\\n",
+    "\t\t\t$(INSTALL_MKDIR) \\\n",
+    "\t\t\t$(INSTALL_INT_DIR)/Mercury/mihs; \\\n",
+    "\t\t} && \\\n",
+    "\t\t$(INSTALL) $(INSTALL_GRADE_INC_DIR)/*.mih \\\n",
+    "\t\t\t$(INSTALL_INT_DIR); \\\n",
+    "\t} || exit 1\n",
+    "endif\n\n"], !IO),
+
+    module_name_to_file_name(ModuleName, ".check", do_not_create_dirs,
+        CheckTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".ints", do_not_create_dirs,
+        IntsTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".int3s", do_not_create_dirs,
+        Int3sTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".opts", do_not_create_dirs,
+        OptsTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".trans_opts", do_not_create_dirs,
+        TransOptsTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".ss", do_not_create_dirs,
+        SsTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".pic_ss", do_not_create_dirs,
+        PicSsTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".ils", do_not_create_dirs,
+        ILsTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".javas", do_not_create_dirs,
+        JavasTargetName, !IO),
+    module_name_to_file_name(ModuleName, ".classes", do_not_create_dirs,
+        ClassesTargetName, !IO),
+
+    % We need to explicitly mention
+    % $(foo.pic_ss) somewhere in the Mmakefile, otherwise it
+    % won't build properly with --target asm: GNU Make's pattern rule
+    % algorithm will try to use the .m -> .c_date -> .c -> .pic_o rule chain
+    % rather than the .m -> .pic_s_date -> .pic_s -> .pic_o chain.
+    % So don't remove the pic_ss target here.
+
+    io.write_strings(DepStream, [
+        ".PHONY : ", CheckTargetName, "\n",
+        CheckTargetName, " : $(", MakeVarName, ".errs)\n\n",
+        ".PHONY : ", IntsTargetName, "\n",
+        IntsTargetName, " : $(", MakeVarName, ".dates)\n\n",
+        ".PHONY : ", Int3sTargetName, "\n",
+        Int3sTargetName, " : $(", MakeVarName, ".date3s)\n\n",
+        ".PHONY : ", OptsTargetName, "\n",
+        OptsTargetName, " : $(", MakeVarName, ".optdates)\n\n",
+        ".PHONY : ", TransOptsTargetName, "\n",
+        TransOptsTargetName, " : $(", MakeVarName,
+            ".trans_opt_dates)\n\n",
+        ".PHONY : ", SsTargetName, "\n",
+        SsTargetName, " : $(", MakeVarName, ".ss)\n\n",
+        ".PHONY : ", PicSsTargetName, "\n",
+        PicSsTargetName, " : $(", MakeVarName, ".pic_ss)\n\n",
+        ".PHONY : ", ILsTargetName, "\n",
+        ILsTargetName, " : $(", MakeVarName, ".ils)\n\n",
+        ".PHONY : ", JavasTargetName, "\n",
+        JavasTargetName, " : $(", MakeVarName, ".javas)\n\n",
+        ".PHONY : ", ClassesTargetName, "\n",
+        ClassesTargetName, " : $(", MakeVarName, ".classes)\n\n"
+    ], !IO),
+
+    % If you change the clean targets below, please also update the
+    % documentation in doc/user_guide.texi.
+    %
+    % XXX The use of xargs in the clean targets doesn't handle special
+    % characters in the file names correctly. This is currently not a problem
+    % in practice as we never generate names containing special characters,
+    % any fix for this problem will also require a fix in `mmake.in'.
+
+    module_name_to_file_name(ModuleName, ".clean", do_not_create_dirs,
+        CleanTargetName, !IO),
+    io.write_strings(DepStream, [
+        "clean_local : ", CleanTargetName, "\n"
+    ], !IO),
+    io.write_strings(DepStream, [
+        ".PHONY : ", CleanTargetName, "\n",
+        CleanTargetName, " :\n",
+        "\t-echo $(", MakeVarName, ".dirs) | xargs rm -rf \n",
+        "\t-echo $(", MakeVarName, ".cs) ", InitCFileName,
+            " | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".mihs) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_ss) ", InitAsmFileName,
+            " | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_pic_ss) ",
+            InitAsmFileName, " | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_os) ", InitObjFileName,
+            " | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_pic_os) ",
+            InitPicObjFileName, " | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".c_dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".il_dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".java_dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_s_dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_pic_s_dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".useds) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".ils) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".javas) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".profs) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".errs) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".foreign_cs) | xargs rm -f\n"
+    ], !IO),
+
+    io.write_string(DepStream, "\n", !IO),
+
+    module_name_to_file_name(ModuleName, ".realclean", do_not_create_dirs,
+        RealCleanTargetName, !IO),
+    io.write_strings(DepStream, [
+        "realclean_local : ", RealCleanTargetName, "\n"
+    ], !IO),
+    io.write_strings(DepStream, [
+        ".PHONY : ", RealCleanTargetName, "\n",
+        RealCleanTargetName, " : ", CleanTargetName, "\n",
+        "\t-echo $(", MakeVarName, ".dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".date0s) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".date3s) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".optdates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".trans_opt_dates) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".ints) | xargs rm -f\n",
+        % XXX This should acutally be .int0s but we need to make sure that
+        % we delete any spurious .int0 files created for nested sub-modules.
+        % For further details see the XXX comments above.
+        "\t-echo $(", MakeVarName, ".all_int0s) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".int3s) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".opts) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".trans_opts) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".analysiss) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".requests) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".imdgs) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".ds) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".module_deps) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_mhs) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".all_mihs) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".dlls) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".foreign_dlls) | xargs rm -f\n",
+        "\t-echo $(", MakeVarName, ".classes) | xargs rm -f\n"
+    ], !IO),
+    io.write_strings(DepStream, [
+        "\t-rm -f ",
+            ExeFileName, "$(EXT_FOR_EXE) ",
+            InitFileName, " ",
+            LibFileName, " ",
+            SharedLibFileName, " ",
+            JarFileName, " ",
+            DepFileName, " ",
+            DvFileName, "\n\n"
+    ], !IO).
+
+%-----------------------------------------------------------------------------%
+
+:- pred get_source_file(deps_map::in, module_name::in, file_name::out) is det.
+
+get_source_file(DepsMap, ModuleName, FileName) :-
+    map.lookup(DepsMap, ModuleName, Deps),
+    Deps = deps(_, ModuleImports),
+    module_imports_get_source_file_name(ModuleImports, SourceFileName),
+    ( string.remove_suffix(SourceFileName, ".m", SourceFileBase) ->
+        FileName = SourceFileBase
+    ;
+        unexpected(this_file, "source file name doesn't end in `.m'")
+    ).
+
+%-----------------------------------------------------------------------------%
+
+referenced_dlls(Module, DepModules0) = Modules :-
+    DepModules = [Module | DepModules0],
+
+    % If we are not compiling a module in the mercury std library then
+    % replace all the std library dlls with one reference to mercury.dll.
+    ( mercury_std_library_module_name(Module) ->
+        % In the standard library we need to add the runtime dlls.
+        Modules = list.remove_dups(
+            [unqualified("mercury_dotnet"), unqualified("mercury_il")
+                | DepModules])
+    ;
+        F = (func(M) =
+            ( mercury_std_library_module_name(M) ->
+                unqualified("mercury")
+            ;
+                % A sub module is located in the top level assembly.
+                unqualified(outermost_qualifier(M))
+            )
+        ),
+        Modules = list.remove_dups(list.map(F, DepModules))
+    ).
+
+%-----------------------------------------------------------------------------%
+
+    % get_both_opt_deps(Deps, Directories, OptDeps, TransOptDeps):
+    %
+    % For each dependency, search intermod_directories for a .m file.
+    % If it exists, add it to both output lists. Otherwise, if a .opt
+    % file exists, add it to the OptDeps list, and if a .trans_opt
+    % file exists, add it to the TransOptDeps list.
+    % If --use-opt-files is set, don't look for `.m' files, since we are
+    % not building `.opt' files, only using those which are available.
+    % XXX This won't find nested sub-modules.
+    % XXX Use `mmc --make' if that matters.
+    %
+:- pred get_both_opt_deps(bool::in, list(module_name)::in, list(string)::in,
+    list(module_name)::out, list(module_name)::out, io::di, io::uo) is det.
+
+get_both_opt_deps(_, [], _, [], [], !IO).
+get_both_opt_deps(BuildOptFiles, [Dep | Deps], IntermodDirs,
+        !:OptDeps, !:TransOptDeps, !IO) :-
+    get_both_opt_deps(BuildOptFiles, Deps, IntermodDirs,
+        !:OptDeps, !:TransOptDeps, !IO),
+    (
+        BuildOptFiles = yes,
+        search_for_module_source(IntermodDirs, IntermodDirs,
+            Dep, Result1, !IO),
+        (
+            Result1 = ok(_),
+            !:OptDeps = [Dep | !.OptDeps],
+            !:TransOptDeps = [Dep | !.TransOptDeps],
+            io.seen(!IO),
+            Found = yes
+        ;
+            Result1 = error(_),
+            Found = no
+        )
+    ;
+        BuildOptFiles = no,
+        Found = no
+    ),
+    (
+        Found = no,
+        module_name_to_file_name(Dep, ".opt", do_not_create_dirs,
+            OptName, !IO),
+        search_for_file(IntermodDirs, OptName, Result2, !IO),
+        (
+            Result2 = ok(_),
+            !:OptDeps = [Dep | !.OptDeps],
+            io.seen(!IO)
+        ;
+            Result2 = error(_)
+        ),
+        module_name_to_file_name(Dep, ".trans_opt", do_not_create_dirs,
+            TransOptName, !IO),
+        search_for_file(IntermodDirs, TransOptName, Result3, !IO),
+        (
+            Result3 = ok(_),
+            !:TransOptDeps = [Dep | !.TransOptDeps],
+            io.seen(!IO)
+        ;
+            Result3 = error(_)
+        )
+    ;
+        Found = yes
+    ).
+
+get_opt_deps(_, [], _, _, [], !IO).
+get_opt_deps(BuildOptFiles, [Dep | Deps], IntermodDirs, Suffix, !:OptDeps,
+        !IO) :-
+    get_opt_deps(BuildOptFiles, Deps, IntermodDirs, Suffix, !:OptDeps, !IO),
+    (
+        BuildOptFiles = yes,
+        search_for_module_source(IntermodDirs, IntermodDirs,
+            Dep, Result1, !IO),
+        (
+            Result1 = ok(_),
+            !:OptDeps = [Dep | !.OptDeps],
+            Found = yes,
+            io.seen(!IO)
+        ;
+            Result1 = error(_),
+            Found = no
+        )
+    ;
+        BuildOptFiles = no,
+        Found = no
+    ),
+    (
+        Found = no,
+        module_name_to_search_file_name(Dep, Suffix, OptName, !IO),
+        search_for_file(IntermodDirs, OptName, Result2, !IO),
+        (
+            Result2 = ok(_),
+            !:OptDeps = [Dep | !.OptDeps],
+            io.seen(!IO)
+        ;
+            Result2 = error(_)
+        )
+    ;
+        Found = yes
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- pred compare_module_names(module_name::in, module_name::in,
+    comparison_result::out) is det.
+
+compare_module_names(Sym1, Sym2, Result) :-
+    Str1 = sym_name_to_string(Sym1),
+    Str2 = sym_name_to_string(Sym2),
+    compare(Result, Str1, Str2).
+
+%-----------------------------------------------------------------------------%
+
+:- func this_file = string.
+
+this_file = "write_deps_file.m".
+
+%-----------------------------------------------------------------------------%
Index: compiler/xml_documentation.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/xml_documentation.m,v
retrieving revision 1.21
diff -u -b -r1.21 xml_documentation.m
--- compiler/xml_documentation.m	3 Apr 2008 05:26:46 -0000	1.21
+++ compiler/xml_documentation.m	18 Jul 2008 16:45:06 -0000
@@ -42,7 +42,7 @@
 :- import_module mdbcomp.prim_data.
 :- import_module parse_tree.
 :- import_module parse_tree.error_util.
-:- import_module parse_tree.modules.
+:- import_module parse_tree.file_names.
 :- import_module parse_tree.prog_data.
 :- import_module parse_tree.source_file_map.
 
@@ -84,7 +84,8 @@
 
 xml_documentation(ModuleInfo, !IO) :-
     module_info_get_name(ModuleInfo, ModuleName),
-    module_name_to_file_name(ModuleName, ".xml", yes, FileName, !IO),
+    module_name_to_file_name(ModuleName, ".xml", do_create_dirs, FileName,
+        !IO),
 
     lookup_module_source_file(ModuleName, SrcFileName, !IO),
     io.open_input(SrcFileName, SrcResult, !IO),
cvs diff: Diffing compiler/notes
Index: compiler/notes/compiler_design.html
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/notes/compiler_design.html,v
retrieving revision 1.134
diff -u -b -r1.134 compiler_design.html
--- compiler/notes/compiler_design.html	3 Apr 2008 05:26:46 -0000	1.134
+++ compiler/notes/compiler_design.html	19 Jul 2008 08:33:11 -0000
@@ -294,10 +294,33 @@
 <li><p> imports and exports are handled at this point (modules.m)
 
 	<p>
+	read_module.m has code to read in modules in the form of .m,
+	.int, .opt etc files.
+
+	<p>
 	modules.m has the code to write out `.int', `.int2', `.int3',
 	`.d' and `.dep' files.
 	
 	<p>
+	write_deps_file.m writes out Makefile fragments.
+
+	<p>
+	file_names.m does conversions between module names and file names.
+
+	<p>
+	module_cmds.m handles the commands for manipulating interface files of
+	various kinds.
+
+	<p>
+	module_imports.m contains the module_imports type and its access
+	predicates, and the predicates that compute various sorts of
+	direct dependencies (those caused by imports) between modules.
+
+	<p>
+	deps_map.m contains the data structure for recording indirect
+	dependencies between modules, and the predicates for creating it.
+
+	<p>
 	source_file_map.m contains code to read, write and search
 	the mapping between module names and file names.
 
@@ -1735,6 +1758,11 @@
 
 	<dl>
 
+	<dt> file_util.m:
+		<dd>
+		Predicates to deal with files, such as searching for a file
+		in a list of directories.
+
 	<dt> process_util.m:
 		<dd>
 		Predicates to deal with process creation and signal handling.
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
Index: mdbcomp/prim_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/prim_data.m,v
retrieving revision 1.28
diff -u -b -r1.28 prim_data.m
--- mdbcomp/prim_data.m	27 Feb 2008 07:23:56 -0000	1.28
+++ mdbcomp/prim_data.m	19 Jul 2008 04:33:41 -0000
@@ -1,4 +1,3 @@
-%-----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
 %-----------------------------------------------------------------------------%
 % Copyright (C) 2005-2008 The University of Melbourne.
@@ -63,6 +62,14 @@
 
 :- type module_name == sym_name.
 
+    % get_ancestors(ModuleName) =  ParentDeps:
+    %
+    % ParentDeps is the list of ancestor modules for this module, oldest first;
+    % e.g. if the ModuleName is `foo.bar.baz', then ParentDeps would be
+    % [`foo', `foo.bar'].
+    %
+:- func get_ancestors(module_name) = list(module_name).
+
     % A proc_label is a data structure a backend can use to as the basis
     % of the label used as the entry point of a procedure.
     %
@@ -134,6 +141,8 @@
     %
 :- func get_special_pred_id_arity(special_pred_id) = int.
 
+%-----------------------------------------------------------------------------%
+
     % string_to_sym_name_sep(String, Separator) = SymName:
     %
     % Convert a string, possibly prefixed with module qualifiers (separated
@@ -169,6 +178,70 @@
     %
 :- pred is_submodule(module_name::in, module_name::in) is semidet.
 
+    % Given a symbol name, return its unqualified name.
+    %
+:- func unqualify_name(sym_name) = string.
+
+    % sym_name_get_module_name(SymName) = ModName:
+    %
+    % Given a symbol name, return the module qualifiers(s).
+    % Fails if the symbol is unqualified.
+    %
+:- pred sym_name_get_module_name(sym_name::in, module_name::out) is semidet.
+
+    % sym_name_get_module_name_default(SymName, DefaultModName, ModName):
+    %
+    % Given a symbol name, return the module qualifier(s).
+    % If the symbol is unqualified, then return the specified default
+    % module name.
+    %
+:- pred sym_name_get_module_name_default(sym_name::in, module_name::in,
+    module_name::out) is det.
+
+    % match_sym_name(PartialSymName, CompleteSymName):
+    %
+    % Succeeds iff there is some sequence of module qualifiers
+    % which when prefixed to PartialSymName gives CompleteSymName.
+    %
+:- pred match_sym_name(sym_name::in, sym_name::in) is semidet.
+
+    % remove_sym_name_prefix(SymName0, Prefix, SymName)
+    % succeeds iff
+    %   SymName and SymName0 have the same module qualifier
+    %   and the unqualified part of SymName0 has the given prefix
+    %   and the unqualified part of SymName is the unqualified
+    %       part of SymName0 with the prefix removed.
+    %
+:- pred remove_sym_name_prefix(sym_name, string, sym_name).
+:- mode remove_sym_name_prefix(in, in, out) is semidet.
+:- mode remove_sym_name_prefix(out, in, in) is det.
+
+    % remove_sym_name_suffix(SymName0, Suffix, SymName)
+    % succeeds iff
+    %   SymName and SymName0 have the same module qualifier
+    %   and the unqualified part of SymName0 has the given suffix
+    %   and the unqualified part of SymName is the unqualified
+    %       part of SymName0 with the suffix removed.
+    %
+:- pred remove_sym_name_suffix(sym_name::in, string::in, sym_name::out)
+    is semidet.
+
+    % add_sym_name_suffix(SymName0, Suffix, SymName)
+    % succeeds iff
+    %   SymName and SymName0 have the same module qualifier
+    %   and the unqualified part of SymName is the unqualified
+    %       part of SymName0 with the suffix added.
+    %
+:- pred add_sym_name_suffix(sym_name::in, string::in, sym_name::out) is det.
+
+    % transform_sym_base_name(TransformFunc, SymName0) = SymName
+    % succeeds iff
+    %   SymName and SymName0 have the same module qualifier
+    %   and the unqualified part of SymName is the result of applying
+    %   TransformFunc to the unqualified part of SymName0.
+    %
+:- func transform_sym_base_name(func(string) = string, sym_name) = sym_name.
+
     % insert_module_qualifier(ModuleName, SymName0) = SymName:
     %
     % Prepend the specified ModuleName onto the module qualifiers in SymName0,
@@ -176,6 +249,19 @@
     %
 :- func insert_module_qualifier(string, sym_name) = sym_name.
 
+    % Given a sym_name return the top level qualifier of that name.
+    %
+:- func outermost_qualifier(sym_name) = string.
+
+:- func add_outermost_qualifier(string, sym_name) = sym_name.
+
+    % Remove and return the top level qualifier of a sym_name.
+    %
+:- pred strip_outermost_qualifier(sym_name::in,
+    string::out, sym_name::out) is semidet.
+
+%-----------------------------------------------------------------------------%
+
     % Returns all the modules which are automatically imported.
     %
 :- func all_builtin_modules = list(sym_name).
@@ -282,6 +368,16 @@
 
 %-----------------------------------------------------------------------------%
 
+get_ancestors(ModuleName) = get_ancestors_2(ModuleName, []).
+
+:- func get_ancestors_2(module_name, list(module_name)) = list(module_name).
+
+get_ancestors_2(unqualified(_), Ancestors) = Ancestors.
+get_ancestors_2(qualified(Parent, _), Ancestors0) =
+    get_ancestors_2(Parent, [Parent | Ancestors0]).
+
+%-----------------------------------------------------------------------------%
+
 string_to_sym_name_sep(String, ModuleSeparator) = Result :-
     % This would be simpler if we had a string.rev_sub_string_search/3 pred.
     % With that, we could search for underscores right-to-left, and construct
@@ -311,12 +407,75 @@
 
 sym_name_to_string(SymName) = sym_name_to_string_sep(SymName, ".").
 
+unqualify_name(unqualified(Name)) = Name.
+unqualify_name(qualified(_ModuleName, Name)) = Name.
+
+sym_name_get_module_name(unqualified(_), _) :- fail.
+sym_name_get_module_name(qualified(ModuleName, _), ModuleName).
+
+sym_name_get_module_name_default(SymName, DefaultModuleName, ModuleName) :-
+    (
+        SymName = unqualified(_),
+        ModuleName = DefaultModuleName
+    ;
+        SymName = qualified(ModuleName, _)
+    ).
+
+    % match_sym_name(PartialSymName, CompleteSymName):
+    %
+    % Succeeds iff there is some sequence of module qualifiers
+    % which when prefixed to PartialSymName gives CompleteSymName.
+    %
+match_sym_name(qualified(Module1, Name), qualified(Module2, Name)) :-
+    match_sym_name(Module1, Module2).
+match_sym_name(unqualified(Name), unqualified(Name)).
+match_sym_name(unqualified(Name), qualified(_, Name)).
+
+remove_sym_name_prefix(qualified(Module, Name0), Prefix,
+        qualified(Module, Name)) :-
+    string.append(Prefix, Name, Name0).
+remove_sym_name_prefix(unqualified(Name0), Prefix, unqualified(Name)) :-
+    string.append(Prefix, Name, Name0).
+
+remove_sym_name_suffix(qualified(Module, Name0), Suffix,
+        qualified(Module, Name)) :-
+    string.remove_suffix(Name0, Suffix, Name).
+remove_sym_name_suffix(unqualified(Name0), Suffix, unqualified(Name)) :-
+    string.remove_suffix(Name0, Suffix, Name).
+
+add_sym_name_suffix(qualified(Module, Name0), Suffix,
+        qualified(Module, Name)) :-
+    string.append(Name0, Suffix, Name).
+add_sym_name_suffix(unqualified(Name0), Suffix, unqualified(Name)) :-
+    string.append(Name0, Suffix, Name).
+
+transform_sym_base_name(TransformFunc, qualified(Module, Name0)) =
+        qualified(Module, TransformFunc(Name0)).
+transform_sym_base_name(TransformFunc, unqualified(Name0)) =
+        unqualified(TransformFunc(Name0)).
+
 insert_module_qualifier(ModuleName, unqualified(PlainName)) =
         qualified(unqualified(ModuleName), PlainName).
 insert_module_qualifier(ModuleName, qualified(ModuleQual0, PlainName)) =
         qualified(ModuleQual, PlainName) :-
     insert_module_qualifier(ModuleName, ModuleQual0) = ModuleQual.
 
+outermost_qualifier(unqualified(Name)) = Name.
+outermost_qualifier(qualified(Module, _Name)) = outermost_qualifier(Module).
+
+add_outermost_qualifier(Qual, unqualified(Name)) =
+        qualified(unqualified(Qual), Name).
+add_outermost_qualifier(Qual, qualified(Module, Name)) =
+        qualified(add_outermost_qualifier(Qual, Module), Name).
+
+strip_outermost_qualifier(qualified(unqualified(OuterQual), Name),
+        OuterQual, unqualified(Name)).
+strip_outermost_qualifier(qualified(Module @ qualified(_, _), Name),
+        OuterQual, qualified(RemainingQual, Name)) :-
+    strip_outermost_qualifier(Module, OuterQual, RemainingQual).
+
+%-----------------------------------------------------------------------------%
+
 is_submodule(SymName, SymName).
 is_submodule(qualified(SymNameA, _), SymNameB) :-
     is_submodule(SymNameA, SymNameB).
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list