[m-rev.] for review: mmc --make [1]

Simon Taylor stayl at cs.mu.OZ.AU
Wed Feb 6 02:20:30 AEDT 2002


Estimated hours taken: 500

Add an alternative implementation of Mmake as part of the compiler.
The advantages of this are
	- more accurate dependencies
	- no `mmake depend' step
	- less process creation (no processes are created to
		build interface files).

Still to do:
	- handle --split-c-files
	- handle the IL backend properly
	- library installation	
	- allow the compiler to be built and the nightly tests
	  to be run with `mmc --make'

compiler/make.m:
	Control the build process.

compiler/make.program_target.m:
	Build executables and libraries.

compiler/make.module_target.m:
	Build C files, object files, interface files etc.

compiler/make.dependencies.m:
	Work out the depenendencies between targets.

compiler/make.module_dep_file.m:
	Record the inter-module dependencies between invocations of mmc.

compiler/make.util.m:
	Utility predicates used by `mmc --make'.

compiler/compile_target_code.m:
	This module will eventually contain the predicates used
	to compile the target code files generated by the compiler
	which are now in mercury_compile.m. (That will be done
	as a separate change for ease of reviewing).

	For now compile_target_code.m 

compiler/mercury_compile.m:
	Export the predicates used to compile target code.

	Call make.m.

	Pass the name of the top-level module in the source file to modules.m.
	It is needed when generating the `.module_dep' files.

	Lookup the option defaults (which will eventually be stored in
	DEFAULT_MCFLAGS by the mmc script) before compiling. Up until now
	the option defaults have been passed on the command line by the
	mmc script, but with `mmc --make' the default options need
	to be overridden by the value of the MCFLAGS make variable, but
	the MCFLAGS make variable is overridden by command line options.

	Pass the value of `--link-flags' to c2init.

	Remove some uninformative messages printed when a C, IL, etc.
	compilation fails.

compiler/options_file.m:
	Read files containing Make style variable assignments.

compiler/options.m:
doc/user_guide.texi:
	Add a new options category: build system options.

	Add some extra options:
	--warn-undefined-options-variables - like mmake --warn-undefined-vars
	--verbose-commands - print commands that the user might be 
		interested in, like C compilation, but not things
		like mercury_update_interface.
	--output-compile-error-lines - print the first n lines
		of the error file generated by a command.
	--generate-mmc-make-modules-dependencies - generate dependencies
		for use by `mmc --make' even when using Mmake.
	
	--il-assembler, --ilasm-flags, --mcpp-compiler, --mcpp-flags,
	--csharp-compiler, --csharp-flags, --install-prefix,
	--install-command, --libgrades, --options-files,
	--options-search-directories.

compiler/modules.m:
	Add fields to the `module_imports' type for use by make.*m.

	Don't try to fill in fields of the module_imports structure
	lazily. It's error prone, and probably doesn't save much
	anyway.

	Clean up the code to compute what foreign languages
	are used by a list of item.

	Simplify the handling of fact tables by recording that a module
	containing fact tables has foreign code to implement them,
	rather than requiring separate checks everywhere.

	Generalise predicates like get_interface so that they
	work even after the imported items have been read.

	Fix the handling of header files with the LLDS backend.

	Install the `.module_dep' files created for use by
	`mmc --make'.

compiler/*.m:
	Use record syntax rather than explicit deconstruction to
	refer to fields of the `module_imports' type.

compiler/*.m:
	Be more careful about where output goes.
	mercury_compile.m sets the output stream to be io__stderr_stream
	at the start of compilation, so remove all explicit writes to
	io__stderr_stream (with `--make' the error output stream may be
	a `.err' file, not io__stderr_stream).

	Change all occurrences of io__tell/io__told to use
	io__open_output/io__close_output (io__told restores the current
	output stream to io__stdout_stream, not the previous value).

compiler/passes_aux.m:
	Make the output from system commands go to the current
	output stream, not C stdout and stderr.

	Allow commands to be printed with `--verbose-commands'.

	Remove uninformative error messages when a command fails.

compiler/timestamp.m:
	Add functions oldest_timestamp and newest_timestamp.

compiler/llds_out.m:
	Record the number of C files written with `--split-c-files'
	in <module>.num_split.

compiler/prog_io.m:
compiler/*.m:
	`search_for_file' now returns the directory in which the
	file was found.

compiler/foreign.m:
	Use sub-typing to make some calls to predicates in this
	module `det' rather than `semidet'.

compiler/handle_options.m:
	Return the option arguments.

compiler/Mmakefile:
	make.util.m refers to kill() and `struct sigaction' which
	are not exported from <signal.h> unless `--no-ansi' is
	passed to gcc.

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

runtime/mercury_signal.h:
runtime/mercury_signal.c:
	Add a function MR_signal_should_restart() which alters
	whether a signal restarts or interrupts system calls.
	In general restarting is the preferred behaviour, but
	the wait() for a child process needs to be interruptible.

scripts/Mmake.vars.in:
	Add subdirs for `.module_dep', `.err_date'
	and `.num_split' files.

library/io.m:
	Add a version of io_call_system which returns the signal 
	that killed the command rather than converting it into
	an error message.

	Add a predicate to interpret the result of system() or wait().

library/list.m:
	Add list__map_foldl2 and a unique mode for list__foldl3.

NEWS:
	Document the new library predicates.

configure.in:
runtime/mercury_conf.h.in:
runtime/RESERVED_MACRO_NAMES:
	Check for siginterrupt().

doc/user_guide.texi:
	Document the new options.

	Add a description of `mmc --make' to the "Using Mmake" chapter.

Index: NEWS
===================================================================
RCS file: /home/mercury1/repository/mercury/NEWS,v
retrieving revision 1.240
diff -u -u -r1.240 NEWS
--- NEWS	30 Jan 2002 14:50:59 -0000	1.240
+++ NEWS	5 Feb 2002 14:59:50 -0000
@@ -80,6 +80,7 @@
 * We've added some other new functions to list.m, namely
   list__last_det/2, list__split_last/3 and list__split_last_det/3.
 * We've added cc_multi modes to list__foldl/4 and list__foldr/4.
+* We've added a predicate list__map_foldl2.
 * As mentioned above, the constructor for lists has changed from './2'
   to `[|]/2'. This change affects the behaviour of the term manipulation
   predicates in the standard library when dealing with values of
@@ -131,6 +132,10 @@
 
 * We've added a predicate to io.m to return the last modification time
   of a file (io__file_modification_time).
+
+* There is a variant of io__call_system, io__call_system_return_signal
+  which on interrupt returns the number of the signal which interrupted
+  the command rather than just an error message.
 
 * We've added a predicate `std_util__map_maybe/3' and a function
   `std_util__map_maybe/2' to apply a predicate or a function to
Index: configure.in
===================================================================
RCS file: /home/mercury1/repository/mercury/configure.in,v
retrieving revision 1.295
diff -u -u -r1.295 configure.in
--- configure.in	3 Feb 2002 09:01:25 -0000	1.295
+++ configure.in	4 Feb 2002 05:58:47 -0000
@@ -445,7 +445,7 @@
 esac
 AC_HAVE_FUNCS(sysconf getpagesize gethostname)
 AC_HAVE_FUNCS(mprotect memalign memmove)
-AC_HAVE_FUNCS(sigaction setitimer)
+AC_HAVE_FUNCS(sigaction siginterrupt setitimer)
 AC_HAVE_FUNCS(snprintf vsnprintf _vsnprintf strerror)
 AC_HAVE_FUNCS(open close dup dup2 fdopen fileno fstat stat isatty)
 AC_HAVE_FUNCS(getpid setpgid fork execlp wait kill)
Index: compiler/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/Mmakefile,v
retrieving revision 1.50
diff -u -u -r1.50 Mmakefile
--- compiler/Mmakefile	14 Jan 2002 04:59:34 -0000	1.50
+++ compiler/Mmakefile	1 Feb 2002 13:27:46 -0000
@@ -100,6 +100,10 @@
 
 CFLAGS-rl_code=-O1
 
+# make.util.m uses `kill' and `struct sigaction' from <signal.h>,
+# which are not available with `--ansi'.
+CFLAGS-make.util = --no-ansi
+
 # The c_code in the module gcc.m needs the header files from the GNU C
 # distribution.
 CFLAGS-gcc =	-DMERCURY_BOOTSTRAP_H \
Index: compiler/bytecode.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/bytecode.m,v
retrieving revision 1.48
diff -u -u -r1.48 bytecode.m
--- compiler/bytecode.m	8 Jul 2001 16:40:04 -0000	1.48
+++ compiler/bytecode.m	24 Jan 2002 13:41:17 -0000
@@ -145,14 +145,16 @@
 bytecode__version(9).
 
 output_bytecode_file(FileName, ByteCodes) -->
-	io__tell_binary(FileName, Result),
+	io__open_binary_output(FileName, Result),
 	(
-		{ Result = ok }
+		{ Result = ok(FileStream) }
 	->
+		io__set_binary_output_stream(FileStream, OutputStream),
 		{ bytecode__version(Version) },
 		output_short(Version),
 		output_bytecode_list(ByteCodes),
-		io__told_binary
+		io__set_binary_output_stream(OutputStream, _),
+		io__close_binary_output(FileStream)
 	;
 		io__progname_base("byte.m", ProgName),
 		io__write_string("\n"),
@@ -164,16 +166,18 @@
 	).
 
 debug_bytecode_file(FileName, ByteCodes) -->
-	io__tell(FileName, Result),
+	io__open_output(FileName, Result),
 	(
-		{ Result = ok }
+		{ Result = ok(FileStream) }
 	->
+		io__set_output_stream(FileStream, OutputStream),
 		{ bytecode__version(Version) },
 		io__write_string("bytecode_version "),
 		io__write_int(Version),
 		io__write_string("\n"),
 		debug_bytecode_list(ByteCodes),
-		io__told
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream)
 	;
 		io__progname_base("byte.m", ProgName),
 		io__write_string("\n"),
Index: compiler/export.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/export.m,v
retrieving revision 1.50
diff -u -u -r1.50 export.m
--- compiler/export.m	6 Nov 2001 15:20:40 -0000	1.50
+++ compiler/export.m	24 Jan 2002 13:38:36 -0000
@@ -558,10 +558,11 @@
 export__produce_header_file(C_ExportDecls, ModuleName) -->
 	{ C_ExportDecls = [_|_] },
 	module_name_to_file_name(ModuleName, ".h", yes, FileName),
-	io__tell(FileName, Result),
+	io__open_output(FileName, Result),
 	(
-		{ Result = ok }
+		{ Result = ok(FileStream) }
 	->
+		io__set_output_stream(FileStream, OutputStream),
 		module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
 		{ library__version(Version) },
 		io__write_strings(["/*\n** Automatically generated from `", 
@@ -594,7 +595,8 @@
 			"#endif\n",
 			"\n",
 			"#endif /* ", GuardMacroName, " */\n"]),
-		io__told
+		io__set_output_stream(OutputStream, _),
+		io__close_output(OutputStream)
 	;
 		io__progname_base("export.m", ProgName),
 		io__write_string("\n"),
Index: compiler/foreign.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/foreign.m,v
retrieving revision 1.10
diff -u -u -r1.10 foreign.m
--- compiler/foreign.m	16 Jan 2002 01:13:18 -0000	1.10
+++ compiler/foreign.m	18 Jan 2002 06:02:59 -0000
@@ -154,18 +154,29 @@
 	% for use in machine-readable name mangling.
 :- func simple_foreign_language_string(foreign_language) = string.
 
+	% Sub-type of foreign_language for languages for which
+	% we generate external files for foreign code.
+:- inst lang_gen_ext_file 
+	--->	c
+	;	managed_cplusplus
+	;	csharp
+	.
+
 	% The file extension used for this foreign language (including
 	% the dot).
 	% Not all foreign languages generate external files,
 	% so this function only succeeds for those that do.
-:- func foreign_language_file_extension(foreign_language) = string
-		is semidet.
+:- func foreign_language_file_extension(foreign_language) = string.
+:- mode foreign_language_file_extension(in) = out is semidet.
+:- mode foreign_language_file_extension(in(lang_gen_ext_file)) = out is det.
 
 	% The module name used for this foreign language.
 	% Not all foreign languages generate external modules 
 	% so this function only succeeds for those that do.
 :- func foreign_language_module_name(module_name, foreign_language) =
-		module_name is semidet.
+		module_name.
+:- mode foreign_language_module_name(in, in) = out is semidet.
+:- mode foreign_language_module_name(in, in(lang_gen_ext_file)) = out is det.
 
 :- implementation.
 
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.126
diff -u -u -r1.126 handle_options.m
--- compiler/handle_options.m	24 Jan 2002 02:27:22 -0000	1.126
+++ compiler/handle_options.m	3 Feb 2002 14:40:07 -0000
@@ -20,13 +20,24 @@
 :- import_module list, bool, std_util, io.
 :- import_module globals, options.
 
-:- pred handle_options(maybe(string), list(string), bool, io__state, io__state).
-:- mode handle_options(out, out, out, di, uo) is det.
+	% handle_options(Args, MaybeError, OptionArgs, NonOptionArgs, Link).
+:- pred handle_options(list(string), maybe(string), list(string),
+		list(string), bool, io__state, io__state).
+:- mode handle_options(in, out, out, out, out, di, uo) is det.
 
+	% usage_error(Descr, Message)
+	%
+	% Display the description of the error location, the error message
+	% and then a usage message.
+:- pred usage_error(string::in, string::in,
+		io__state::di, io__state::uo) is det.
+
+	% usage_error(Message)
+	%
 	% Display error message and then usage message
 :- pred usage_error(string::in, io__state::di, io__state::uo) is det.
 
-	% Display usage message
+	% Display usage message.
 :- pred usage(io__state::di, io__state::uo) is det.
 
 	% Display long usage message for help
@@ -49,15 +60,15 @@
 :- import_module prog_data, foreign.
 :- import_module char, dir, int, string, map, set, getopt, library.
 
-handle_options(MaybeError, Args, Link) -->
-	io__command_line_arguments(Args0),
+handle_options(Args0, MaybeError, OptionArgs, Args, Link) -->
 	% io__write_string("original arguments\n"),
 	% dump_arguments(Args0),
 	{ OptionOps = option_ops(short_option, long_option,
 		option_defaults, special_handler) },
 	% default to optimization level `-O2'
 	{ Args1 = ["-O2" | Args0] },
-	{ getopt__process_options(OptionOps, Args1, Args, Result) },
+	{ getopt__process_options(OptionOps, Args1,
+		OptionArgs, Args, Result) },
 	% io__write_string("final arguments\n"),
 	% dump_arguments(Args),
 	postprocess_options(Result, MaybeError),
@@ -266,11 +277,10 @@
 	% and assume --num-tag-bits 0
 	( { NumTagBits1 < 0 } ->
 		io__progname_base("mercury_compile", ProgName),
-		io__stderr_stream(StdErr),
 		report_warning(ProgName),
 		report_warning(
 			": warning: --num-tag-bits invalid or unspecified\n"),
-		io__write_string(StdErr, ProgName),
+		io__write_string(ProgName),
 		report_warning(": using --num-tag-bits 0 (tags disabled)\n"),
 		{ NumTagBits = 0 }
 	;
@@ -356,6 +366,12 @@
 	% --no-mlds-optimize implies --no-optimize-tailcalls
 	option_neg_implies(optimize, optimize_tailcalls, bool(no)),
 
+	% make.m controls generating object code and linking itself,
+	% so mercury_compile.m should only generate target code when
+	% given a module to process.
+	option_implies(make, compile_only, bool(yes)),
+	option_implies(make, target_code_only, bool(yes)),
+
 	option_implies(verbose_check_termination, check_termination,bool(yes)),
 	option_implies(check_termination, termination, bool(yes)),
 	option_implies(check_termination, warn_missing_trans_opt_files,
@@ -440,7 +456,17 @@
 	maybe_disable_smart_recompilation(Smart, target_code_only, no,
 		"`--no-target-code-only'"),
 
+	% --rebuild is just like --make but always rebuilds the files
+	% without checking timestamps.
+	option_implies(rebuild, make, bool(yes)),
+
+	% --make does not handle --transitive-intermodule-optimization.
+	% --transitive-intermodule-optimization is in the process of
+	% being rewritten anyway.
+	option_implies(make, transitive_optimization, bool(no)),
+
 	option_implies(very_verbose, verbose, bool(yes)),
+	option_implies(verbose, verbose_commands, bool(yes)),
 
 	globals__io_lookup_int_option(debug_liveness, DebugLiveness),
 	(
@@ -459,6 +485,9 @@
 		[]
 	),
 
+	% --split-c-files is not supported by the high-level C code generator.
+	option_implies(highlevel_code, split_c_files, bool(no)),
+
 	% --split-c-files implies --procs-per-c-function 1
 	option_implies(split_c_files, procs_per_c_function, int(1)),
 
@@ -952,20 +981,29 @@
 		[]
 	).
 
+usage_error(ErrorDescr, ErrorMessage) -->
+	write_program_name,	
+	io__write_string(ErrorDescr),
+	io__nl,
+	usage_error(ErrorMessage).
+
 usage_error(ErrorMessage) -->
-	io__progname_base("mercury_compile", ProgName),
-	io__stderr_stream(StdErr),
-	io__write_string(StdErr, ProgName),
-	io__write_string(StdErr, ": "),
-	io__write_string(StdErr, ErrorMessage),
-	io__write_string(StdErr, "\n"),
+	write_program_name,
+	io__write_string(ErrorMessage),
+	io__write_string("\n"),
 	io__set_exit_status(1),
 	usage.
 
+:- pred write_program_name(io__state::di, io__state::uo) is det.
+
+write_program_name -->
+	io__progname_base("mercury_compile", ProgName),
+	io__write_string(ProgName),
+	io__write_string(": ").
+
 usage -->
-	io__stderr_stream(StdErr),
 	{ library__version(Version) },
- 	io__write_strings(StdErr, [
+ 	io__write_strings([
 		"Mercury Compiler, version ", Version, "\n",
 		"Copyright (C) 1993-2000 The University of Melbourne\n",
 		"Usage: mmc [<options>] <arguments>\n",
Index: compiler/intermod.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/intermod.m,v
retrieving revision 1.111
diff -u -u -r1.111 intermod.m
--- compiler/intermod.m	16 Jan 2002 01:13:22 -0000	1.111
+++ compiler/intermod.m	3 Feb 2002 15:40:36 -0000
@@ -110,16 +110,16 @@
 
 	{ module_info_name(ModuleInfo0, ModuleName) },
 	module_name_to_file_name(ModuleName, ".opt.tmp", yes, TmpName),
-	io__tell(TmpName, Result2),
+	io__open_output(TmpName, Result2),
 	(
 		{ Result2 = error(Err2) },
 		{ io__error_message(Err2, Msg2) },
-		io__stderr_stream(ErrStream2),
-		io__write_string(ErrStream2, Msg2),
+		io__write_string(Msg2),
 		io__set_exit_status(1),
 		{ ModuleInfo = ModuleInfo0 }
 	;
-		{ Result2 = ok },
+		{ Result2 = ok(FileStream) },
+		io__set_output_stream(FileStream, OutputStream),
 		{ module_info_predids(ModuleInfo0, RealPredIds) },
 		{ module_info_assertion_table(ModuleInfo0, AssertionTable) },
 		{ assertion_table_pred_ids(AssertionTable, AssertPredIds) },
@@ -140,7 +140,8 @@
 		intermod__write_intermod_info(IntermodInfo),
 		{ intermod_info_get_module_info(ModuleInfo1,
 			IntermodInfo, _) },
-		io__told,
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream),
 		globals__io_lookup_bool_option(intermod_unused_args,
 			UnusedArgs),
 		( { UnusedArgs = yes } ->
@@ -2054,8 +2055,10 @@
 		%
 		% Read in the .opt files for imported and ancestor modules.
 		%
-	{ Module0 = module_imports(_, ModuleName, Ancestors0, InterfaceDeps0,
-				ImplementationDeps0, _, _, _, _, _, _, _, _) },
+	{ ModuleName = Module0 ^ module_name },
+	{ Ancestors0 = Module0 ^ parent_deps },
+	{ InterfaceDeps0 = Module0 ^ int_deps },
+	{ ImplementationDeps0 = Module0 ^ impl_deps },
 	{ list__condense([Ancestors0, InterfaceDeps0, ImplementationDeps0],
 		OptFiles) },
 	read_optimization_interfaces(OptFiles, [], OptItems, no, OptError),
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.184
diff -u -u -r1.184 llds_out.m
--- compiler/llds_out.m	25 Jan 2002 08:22:49 -0000	1.184
+++ compiler/llds_out.m	4 Feb 2002 01:43:05 -0000
@@ -259,7 +259,7 @@
 :- import_module rtti, rtti_out, layout, layout_out, options, trace_params.
 :- import_module exprn_aux, prog_util, prog_out, hlds_pred.
 :- import_module export, mercury_to_mercury, modules, passes_aux.
-:- import_module c_util, foreign.
+:- import_module c_util, foreign, compile_target_code.
 
 :- import_module int, char, string, std_util.
 :- import_module set, bintree_set, assoc_list, require.
@@ -288,6 +288,7 @@
 			UserForeignCodes, Exports, Vars, Datas, Modules) },
 		module_name_to_file_name(ModuleName, ".dir", yes, ObjDirName),
 		make_directory(ObjDirName),
+
 		output_split_c_file_init(ModuleName, Modules, Datas,
 			StackLayoutLabels, MaybeRLFile),
 		output_split_user_foreign_codes(UserForeignCodes, ModuleName,
@@ -299,7 +300,16 @@
 		output_split_comp_gen_c_datas(Datas, ModuleName,
 			C_HeaderInfo, StackLayoutLabels, Num3, Num4),
 		output_split_comp_gen_c_modules(Modules, ModuleName,
-			C_HeaderInfo, StackLayoutLabels, Num4, _Num)
+			C_HeaderInfo, StackLayoutLabels, Num4, Num),
+
+		compile_target_code__write_num_split_c_files(ModuleName,
+			Num, Succeeded),
+		( { Succeeded = no } ->
+			compile_target_code__remove_split_c_output_files(
+				ModuleName, Num)
+		;
+			[]
+		)
 	;
 		output_single_c_file(C_File, no,
 			StackLayoutLabels, MaybeRLFile)
@@ -383,11 +393,12 @@
 	module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
 	module_name_to_split_c_file_name(ModuleName, 0, ".c", FileName),
 
-	io__tell(FileName, Result),
+	io__open_output(FileName, Result),
 	(
-		{ Result = ok }
+		{ Result = ok(FileStream) }
 	->
 		{ library__version(Version) },
+		io__set_output_stream(FileStream, OutputStream),
 		output_c_file_intro_and_grade(SourceFileName, Version),
 		output_init_comment(ModuleName),
 		output_c_file_mercury_headers,
@@ -396,7 +407,8 @@
 		output_c_module_init_list(ModuleName, Modules, Datas,
 			StackLayoutLabels, DeclSet0, _DeclSet),
 		output_rl_file(ModuleName, MaybeRLFile),
-		io__told
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream)
 	;
 		io__progname_base("llds.m", ProgName),
 		io__write_string("\n"),
@@ -476,11 +488,12 @@
 	;
 		module_name_to_file_name(ModuleName, ".c", yes, FileName)
 	),
-	io__tell(FileName, Result),
+	io__open_output(FileName, Result),
 	(
-		{ Result = ok }
+		{ Result = ok(FileStream) }
 	->
 		{ library__version(Version) },
+		io__set_output_stream(FileStream, OutputStream),
 		module_name_to_file_name(ModuleName, ".m", no, SourceFileName),
 		output_c_file_intro_and_grade(SourceFileName, Version),
 		( { SplitFiles = yes(_) } ->
@@ -513,7 +526,8 @@
 				StackLayoutLabels, DeclSet5, _DeclSet)
 		),
 		output_rl_file(ModuleName, MaybeRLFile),
-		io__told
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream)
 	;
 		io__progname_base("llds.m", ProgName),
 		io__write_string("\n"),
Index: compiler/make_hlds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/make_hlds.m,v
retrieving revision 1.398
diff -u -u -r1.398 make_hlds.m
--- compiler/make_hlds.m	30 Jan 2002 01:40:24 -0000	1.398
+++ compiler/make_hlds.m	3 Feb 2002 15:36:52 -0000
@@ -291,11 +291,8 @@
 		;
 			{ Status = Status0 },
 			{ Module = Module0 },
-			io__stderr_stream(StdErr),
-			io__set_output_stream(StdErr, OldStream),
 			prog_out__write_context(Context),
-			report_warning("Warning: `external' declaration requires arity.\n"),
-			io__set_output_stream(OldStream, _)
+			report_warning("Warning: `external' declaration requires arity.\n")
 		)
 	; { ModuleDefn = module(_ModuleName) } ->
 		report_unexpected_decl("module", Context),
@@ -314,11 +311,8 @@
 	;
 		{ Status = Status0 },
 		{ Module = Module0 },
-		io__stderr_stream(StdErr),
-		io__set_output_stream(StdErr, OldStream),
 		prog_out__write_context(Context),
-		report_warning("Warning: declaration not yet implemented.\n"),
-		io__set_output_stream(OldStream, _)
+		report_warning("Warning: declaration not yet implemented.\n")
 	).
 
 add_item_decl_pass_1(nothing(_), _, Status, Module, Status, Module) --> [].
@@ -1953,15 +1947,12 @@
 			Body, Context, Status, Module3) },
 		{ module_info_set_types(Module3, Types, Module) },
 		( { Body = uu_type(_) } ->
-			io__stderr_stream(StdErr),
-			io__set_output_stream(StdErr, OldStream),
 			prog_out__write_context(Context),
 			io__write_string("Error in type declaration: \n"),
 			prog_out__write_context(Context),
 			io__write_string(
 	"  the syntax for type equivalence is `:- type t1 == t2'.\n"),
-			io__set_exit_status(1),
-			io__set_output_stream(OldStream, _)
+			io__set_exit_status(1)
 		;
 			% XXX we can't handle abstract exported
 			% polymorphic equivalence types with monomorphic
@@ -1973,8 +1964,6 @@
 			{ term__contains_var_list(Args, Var) },
 			{ \+ term__contains_var(EqvType, Var) }
 		->
-			io__stderr_stream(StdErr),
-			io__set_output_stream(StdErr, OldStream),
 			prog_out__write_context(Context),
 			io__write_string(
 	"Sorry, not implemented: polymorphic equivalence type,\n"),
@@ -1994,8 +1983,7 @@
 			;
 				[]
 			),
-			io__set_exit_status(1),
-			io__set_output_stream(OldStream, _)
+			io__set_exit_status(1)
 		;
 			[]
 		)
@@ -2121,8 +2109,6 @@
 		{ OtherConsDefn = hlds_cons_defn(_, _, _, TypeId, _) }
 	->
 		% XXX we should record each error using module_info_incr_errors
-		io__stderr_stream(StdErr),
-		io__set_output_stream(StdErr, OldStream),
 		prog_out__write_context(Context),
 		io__write_string("Error: constructor `"),
 		hlds_out__write_cons_id(QualifiedConsId),
@@ -2130,7 +2116,6 @@
 		hlds_out__write_type_id(TypeId),
 		io__write_string("' multiply defined.\n"),
 		io__set_exit_status(1),
-		io__set_output_stream(OldStream, _),
 		{ QualifiedConsDefns = QualifiedConsDefns1 }
 	;
 		{ QualifiedConsDefns = [ConsDefn | QualifiedConsDefns1] }	
@@ -2235,8 +2220,6 @@
 		% XXX we should record each error
 		% using module_info_incr_errors
 		{ FieldDefn = hlds_ctor_field_defn(Context, _, _, _, _) },
-		io__stderr_stream(StdErr),
-		io__set_output_stream(StdErr, OldStream),
 		{ prog_out__sym_name_to_string(FieldName, FieldString) },
 		{ ErrorPieces = [
 			words("Error: field"),
@@ -2254,7 +2237,6 @@
 		io__write_string(FieldString),
 		io__write_string("'.\n"),
 		io__set_exit_status(1),
-		io__set_output_stream(OldStream, _),
 		{ FieldNameTable = FieldNameTable0 }
 	;
 		{ unqualify_name(FieldName, UnqualFieldName) },
@@ -4136,8 +4118,6 @@
 				PredicateTable, ModuleInfo) }
 		;
 			{ module_info_incr_errors(ModuleInfo1, ModuleInfo) }, 
-			io__stderr_stream(StdErr),
-			io__set_output_stream(StdErr, OldStream),
 			prog_out__write_context(Context),
 			io__write_string("Error: `:- pragma import' "),
 			io__write_string("declaration for undeclared mode "),
@@ -4145,7 +4125,6 @@
 			hlds_out__write_simple_call_id(PredOrFunc,
 				PredName/Arity),
 			io__write_string(".\n"),
-			io__set_output_stream(OldStream, _),
 			{ Info = Info0 }
 		)
 	).
@@ -4324,8 +4303,6 @@
 				ModuleInfo)
 		;
 			{ module_info_incr_errors(ModuleInfo1, ModuleInfo) }, 
-			io__stderr_stream(StdErr),
-			io__set_output_stream(StdErr, OldStream),
 			prog_out__write_context(Context),
 			io__write_string("Error: `:- pragma foreign_proc' "),
 			io__write_string("declaration for undeclared mode "),
@@ -4333,7 +4310,6 @@
 			hlds_out__write_simple_call_id(PredOrFunc,
 				PredName/Arity),
 			io__write_string(".\n"),
-			io__set_output_stream(OldStream, _),
 			{ Info = Info0 }
 		)
 	).
@@ -4703,25 +4679,22 @@
 warn_overlap([], _, _) --> [].
 warn_overlap([Warn|Warns], VarSet, PredCallId) -->
 	{ Warn = warn_overlap(Vars, Context) },
-	io__stderr_stream(StdErr),
-	io__set_output_stream(StdErr, OldStream),
 	prog_out__write_context(Context),
-	io__write_string(StdErr, "In clause for "),
+	io__write_string("In clause for "),
 	hlds_out__write_simple_call_id(PredCallId),
-	io__write_string(StdErr, ":\n"),
+	io__write_string(":\n"),
 	prog_out__write_context(Context),
 	( { Vars = [Var] } ->
-		io__write_string(StdErr, "  warning: variable `"),
+		io__write_string("  warning: variable `"),
 		mercury_output_var(Var, VarSet, no),
-		report_warning(StdErr, "' has overlapping scopes.\n")
+		report_warning("' has overlapping scopes.\n")
 	;
-		io__write_string(StdErr, "  warning: variables `"),
+		io__write_string("  warning: variables `"),
 		mercury_output_vars(Vars, VarSet, no),
-		report_warning(StdErr, "'\n"),
+		report_warning("'\n"),
 		prog_out__write_context(Context),
-		report_warning(StdErr, "  each have overlapping scopes.\n")
+		report_warning("  each have overlapping scopes.\n")
 	),
-	io__set_output_stream(OldStream, _),
 	warn_overlap(Warns, VarSet, PredCallId).
 
 %-----------------------------------------------------------------------------%
@@ -4972,8 +4945,6 @@
 		( { UnmentionedVars = [] } ->
 			[]
 		;
-			io__stderr_stream(StdErr1),
-			io__set_output_stream(StdErr1, OldStream1),
 			prog_out__write_context(Context),
 			io__write_string("In the " ++ LangStr ++ " code for "),
 			hlds_out__write_simple_call_id(PredOrFuncCallId),
@@ -4981,8 +4952,7 @@
 			prog_out__write_context(Context),
 			write_variable_warning_start(UnmentionedVars),
 			io__write_string("not occur in the " ++
-				LangStr ++ " code.\n"),
-			io__set_output_stream(OldStream1, _)
+				LangStr ++ " code.\n")
 		)
 	;
 		{ PragmaImpl = nondet(_, _, FirstCode, _,
@@ -4999,8 +4969,6 @@
 		( { UnmentionedInputVars = [] } ->
 			[]
 		;
-			io__stderr_stream(StdErr2),
-			io__set_output_stream(StdErr2, OldStream2),
 			prog_out__write_context(Context),
 			io__write_string("In the " ++ LangStr ++ " code for "),
 			hlds_out__write_simple_call_id(PredOrFuncCallId),
@@ -5008,8 +4976,7 @@
 			prog_out__write_context(Context),
 			write_variable_warning_start(UnmentionedInputVars),
 			io__write_string("not occur in the first " ++
-				LangStr ++ " code.\n "),
-			io__set_output_stream(OldStream2, _)
+				LangStr ++ " code.\n ")
 		),
 		{ solutions(lambda([Name::out] is nondet, (
 				list__member(yes(Name - Mode), ArgInfo),
@@ -5021,8 +4988,6 @@
 		( { UnmentionedFirstOutputVars = [] } ->
 			[]
 		;
-			io__stderr_stream(StdErr3),
-			io__set_output_stream(StdErr3, OldStream3),
 			prog_out__write_context(Context),
 			io__write_string("In the " ++ LangStr ++ " code for "),
 			hlds_out__write_simple_call_id(PredOrFuncCallId),
@@ -5032,8 +4997,7 @@
 				UnmentionedFirstOutputVars),
 			io__write_string("not occur in the first " ++
 				LangStr ++ " code or the shared " ++ LangStr ++
-				" code.\n "),
-			io__set_output_stream(OldStream3, _)
+				" code.\n ")
 		),
 		{ solutions(lambda([Name::out] is nondet, (
 				list__member(yes(Name - Mode), ArgInfo),
@@ -5045,8 +5009,6 @@
 		( { UnmentionedLaterOutputVars = [] } ->
 			[]
 		;
-			io__stderr_stream(StdErr4),
-			io__set_output_stream(StdErr4, OldStream4),
 			prog_out__write_context(Context),
 			io__write_string("In the " ++ LangStr ++ " code for "),
 			hlds_out__write_simple_call_id(PredOrFuncCallId),
@@ -5056,8 +5018,7 @@
 				UnmentionedLaterOutputVars),
 			io__write_string("not occur in the retry " ++
 				LangStr ++ " code or the shared " ++ LangStr ++
-				" code.\n "),
-			io__set_output_stream(OldStream4, _)
+				" code.\n ")
 		)
 	;
 		{ PragmaImpl = import(_, _, _, _) }
@@ -5168,8 +5129,6 @@
 
 warn_singletons(GoalVars, NonLocals, QuantVars, VarSet, Context,
 		PredOrFuncCallId) -->
-	io__stderr_stream(StdErr),
-
 	% find all the variables in the goal that don't occur outside the
 	% goal (i.e. are singleton), have a variable name that doesn't
 	% start with "_" or "DCG_", and don't have the same name as any
@@ -5193,18 +5152,18 @@
 		[]
 	;
 		prog_out__write_context(Context),
-		io__write_string(StdErr, "In clause for "),
+		io__write_string("In clause for "),
 		hlds_out__write_simple_call_id(PredOrFuncCallId),
-		io__write_string(StdErr, ":\n"),
+		io__write_string(":\n"),
 		prog_out__write_context(Context),
 		( { SingletonVars = [_] } ->
-			io__write_string(StdErr, "  warning: variable `"),
+			io__write_string("  warning: variable `"),
 			mercury_output_vars(SingletonVars, VarSet, no),
-			report_warning(StdErr, "' occurs only once in this scope.\n")
+			report_warning("' occurs only once in this scope.\n")
 		;
-			io__write_string(StdErr, "  warning: variables `"),
+			io__write_string("  warning: variables `"),
 			mercury_output_vars(SingletonVars, VarSet, no),
-			report_warning(StdErr, "' occur only once in this scope.\n")
+			report_warning("' occur only once in this scope.\n")
 		)
 	),
 
@@ -5225,18 +5184,18 @@
 		[]
 	;
 		prog_out__write_context(Context),
-		io__write_string(StdErr, "In clause for "),
+		io__write_string("In clause for "),
 		hlds_out__write_simple_call_id(PredOrFuncCallId),
-		io__write_string(StdErr, ":\n"),
+		io__write_string(":\n"),
 		prog_out__write_context(Context),
 		( { MultiVars = [_] } ->
-			io__write_string(StdErr, "  warning: variable `"),
+			io__write_string("  warning: variable `"),
 			mercury_output_vars(MultiVars, VarSet, no),
-			report_warning(StdErr, "' occurs more than once in this scope.\n")
+			report_warning("' occurs more than once in this scope.\n")
 		;
-			io__write_string(StdErr, "  warning: variables `"),
+			io__write_string("  warning: variables `"),
 			mercury_output_vars(MultiVars, VarSet, no),
-			report_warning(StdErr, "' occur more than once in this scope.\n")
+			report_warning("' occur more than once in this scope.\n")
 		)
 	).
 
Index: compiler/mercury_compile.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_compile.m,v
retrieving revision 1.229
diff -u -u -r1.229 mercury_compile.m
--- compiler/mercury_compile.m	11 Jan 2002 07:41:20 -0000	1.229
+++ compiler/mercury_compile.m	5 Feb 2002 11:29:30 -0000
@@ -1,5 +1,5 @@
 %-----------------------------------------------------------------------------%
-% Copyright (C) 1994-2001 The University of Melbourne.
+% Copyright (C) 1994-2002 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.
 %-----------------------------------------------------------------------------%
@@ -15,9 +15,83 @@
 
 :- module mercury_compile.
 :- interface.
-:- import_module io.
 
-:- pred main(io__state::di, io__state::uo) is det.
+:- import_module modules, prog_io, prog_data.
+:- import_module bool, io, list, std_util.
+
+:- pred main(io__state, io__state).
+:- mode main(di, uo) is det.
+
+	% main(Args).
+:- pred main(list(string), io__state, io__state).
+:- mode main(in, di, uo) is det.
+
+	% The predicates below are used by mercury_compile.m
+	% and by make.m and its sub-modules.
+	% XXX Move the following into compile_target_code.m.
+
+	% mercury_compile__compile_c_file(ErrorStream, CFile,
+	%		ObjFile, Succeeded).
+:- pred mercury_compile__compile_c_file(io__output_stream, string, string,
+		bool, io__state, io__state).
+:- mode mercury_compile__compile_c_file(in, in, in, out, di, uo) is det.
+
+:- pred mercury_compile__compile_c_file(io__output_stream, module_name,
+		bool, io__state, io__state).
+:- mode mercury_compile__compile_c_file(in, in, out, di, uo) is det.
+
+	% mercury_compile__split_c_to_obj(ErrorStream, ModuleName,
+	%	NumChunks, Succeeded).
+	% Compile the `.c' files produced for a module with `--split-c-files'.
+:- pred mercury_compile__split_c_to_obj(io__output_stream, module_name,
+		int, bool, io__state, io__state).
+:- mode mercury_compile__split_c_to_obj(in, in, in, out, di, uo) is det.
+
+:- pred mercury_compile__assemble(io__output_stream,
+		module_name, bool, io__state, io__state).
+:- mode mercury_compile__assemble(in, in, out, di, uo) is det.
+
+:- pred mercury_compile__compile_java_file(io__output_stream,
+		module_name, bool, io__state, io__state).
+:- mode mercury_compile__compile_java_file(in, in, out, di, uo) is det.
+
+	% mercury_compile__il_assemble(ErrorStream,
+	%		ModuleName, HasMain, Succeeded).
+:- pred mercury_compile__il_assemble(io__output_stream, module_name,
+		has_main, bool, io__state, io__state).
+:- mode mercury_compile__il_assemble(in, in, in, out, di, uo) is det.
+
+:- pred mercury_compile__il_assemble(io__output_stream, file_name, file_name,
+		has_main, bool, io__state, io__state).
+:- mode mercury_compile__il_assemble(in, in, in, in, out, di, uo) is det.
+
+:- pred mercury_compile__compile_managed_cplusplus_file(io__output_stream,
+		file_name, file_name, bool, io__state, io__state).
+:- mode mercury_compile__compile_managed_cplusplus_file(in, in, in,
+		out, di, uo) is det.
+
+:- pred mercury_compile__compile_csharp_file(io__output_stream,
+		file_name, file_name, bool, io__state, io__state).
+:- mode mercury_compile__compile_csharp_file(in, in, in, out, di, uo) is det.
+
+	% mercury_compile__make_init_obj_file(ErrorStream,
+	%	MainModuleName, AllModuleNames, MaybeInitObjFileName).
+:- pred mercury_compile__make_init_obj_file(io__output_stream,
+		module_name, list(module_name), maybe(file_name),
+		io__state, io__state) is det.
+:- mode mercury_compile__make_init_obj_file(in, in, in, out, di, uo) is det.
+
+:- type linked_target_type
+	--->	executable
+	;	static_library
+	;	shared_library
+	.
+
+	% mercury_compile__link(TargetType, MainModuleName,
+	%	ObjectFileNames, Succeeded).
+:- pred mercury_compile__link(io__output_stream, linked_target_type,
+		module_name, list(string), bool, io__state, io__state).
+:- mode mercury_compile__link(in, in, in, in, out, di, uo) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -75,10 +149,10 @@
 :- import_module layout, dependency_graph, prog_util, rl_dump, rl_file.
 :- import_module options, globals, trace_params, passes_aux.
 :- import_module recompilation, recompilation_usage, recompilation_check.
-:- import_module timestamp.
+:- import_module options_file, make, timestamp.
 
 	% library modules
-:- import_module int, list, map, set, std_util, dir, require, string, bool.
+:- import_module int, list, map, set, std_util, require, string, bool, dir.
 :- import_module library, getopt, set_bbbtree, term, varset, assoc_list.
 :- import_module gc.
 
@@ -86,8 +160,27 @@
 
 main -->
 	gc_init,
-	handle_options(MaybeError, Args, Link),
-	main_2(MaybeError, Args, Link).
+
+	 	% All messages go to stderr
+	io__stderr_stream(StdErr),
+	io__set_output_stream(StdErr, _),
+	io__command_line_arguments(Args0),
+
+	% Lookup the the default options in the
+	% environment (set by the mmc script).
+	lookup_default_options(options_variables_init, MaybeMCFlags),
+	(
+	    { MaybeMCFlags = yes(MCFlags) },
+	    handle_options(MCFlags ++ Args0, MaybeError,
+	    	OptionArgs, NonOptionArgs, Link),
+	    main_2(MaybeError, OptionArgs, NonOptionArgs, Link)
+	;
+	    { MaybeMCFlags = no },
+	    io__set_exit_status(1)
+	).
+
+main(Args) -->
+	main_2(no, [], Args, no).
 
 %-----------------------------------------------------------------------------%
 
@@ -112,23 +205,28 @@
 
 %-----------------------------------------------------------------------------%
 
-:- pred main_2(maybe(string), list(string), bool, io__state, io__state).
-:- mode main_2(in, in, in, di, uo) is det.
+:- pred main_2(maybe(string), list(string), list(string),
+		bool, io__state, io__state).
+:- mode main_2(in, in, in, in, di, uo) is det.
 
-main_2(yes(ErrorMessage), _, _) -->
+main_2(yes(ErrorMessage), _, _, _) -->
 	usage_error(ErrorMessage).
-main_2(no, Args, Link) -->
+main_2(no, OptionArgs, Args, Link) -->
 	globals__io_lookup_bool_option(help, Help),
 	globals__io_lookup_bool_option(output_grade_string, OutputGrade),
 	globals__io_lookup_bool_option(filenames_from_stdin,
 		FileNamesFromStdin),
+	globals__io_lookup_bool_option(make, Make),
 	( { Help = yes } ->
 		long_usage
 	; { OutputGrade = yes } ->
 		globals__io_get_globals(Globals),
 		{ compute_grade(Globals, Grade) },
-		io__write_string(Grade),
-		io__write_string("\n")
+		io__stdout_stream(Stdout),
+		io__write_string(Stdout, Grade),
+		io__write_string(Stdout, "\n")
+	; { Make = yes } ->
+		make__process_args(OptionArgs, Args)
 	; { Args = [], FileNamesFromStdin = no } ->
 		usage
 	;
@@ -137,7 +235,7 @@
 		( { ExitStatus = 0 } ->
 			( { Link = yes } ->
 				mercury_compile__link_module_list(
-					ModulesToLink)
+					ModulesToLink, _Succeeded)
 			;
 				[]
 			)
@@ -183,7 +281,7 @@
 			% starting the gcc backend to avoid overwriting
 			% the output assembler file even if recompilation 
 			% is found to be unnecessary.
-		    	process_args(Args, ModulesToLink)
+		    	mercury_compile__process_args(Args, ModulesToLink)
 		    ;
 			io__write_string(
 "Sorry, not implemented: `--target asm' with `--smart-recompilation'\n"),
@@ -195,7 +293,7 @@
 		;
 		    compile_using_gcc_backend(
 		    	string_to_file_or_module(FirstArg),
-			process_args(Args), ModulesToLink)
+			mercury_compile__process_args(Args), ModulesToLink)
 	        )
 	    ;
 		io__write_string(
@@ -207,7 +305,7 @@
 		% If we're NOT using the GCC back-end,
 		% then we can just call process_args directly,
 		% rather than via GCC.
-	    process_args(Args, ModulesToLink)
+	    mercury_compile__process_args(Args, ModulesToLink)
 	).
 
 :- pred compiling_to_asm(globals::in) is semidet.
@@ -296,12 +394,9 @@
 		globals__io_lookup_bool_option(target_code_only, 
 				TargetCodeOnly),
 		( { Result = ok, TargetCodeOnly = no } ->
-			globals__io_lookup_string_option(object_file_extension,
-				Obj),
-			module_name_to_file_name(ModuleName, Obj,
-				yes, O_File),
-			mercury_compile__asm_to_obj(
-				AsmFile, O_File, _AssembleOK)
+			io__output_stream(OutputStream),
+			mercury_compile__assemble(OutputStream,
+				ModuleName, _AssembleOK)
 		;
 			[]
 		)
@@ -442,10 +537,6 @@
 :- mode process_arg(in, out, di, uo) is det.
 
 process_arg(Arg, ModulesToLink) -->
-	 	% All messages go to stderr
-	io__stderr_stream(StdErr),
-	io__set_output_stream(StdErr, _),
-
 	{ FileOrModule = string_to_file_or_module(Arg) },
 	globals__io_lookup_bool_option(generate_dependencies, GenerateDeps),
 	( { GenerateDeps = yes } ->
@@ -617,8 +708,8 @@
 				Items, SubModuleList),
 			list__foldl(
 				(pred(SubModule::in, di, uo) is det -->
-					ProcessModule(FileName, MaybeTimestamp,
-						SubModule)
+					ProcessModule(FileName, ModuleName,
+						MaybeTimestamp, SubModule)
 				),
 				SubModuleList)
 		),
@@ -750,7 +841,7 @@
 			globals__io_set_trace_level_none,
 
 			compile_all_submodules(FileName,
-				ModuleName - NestedSubModules,
+				ModuleName, NestedSubModules,
 				MaybeTimestamp, ReadModules,
 				FindTimestampFiles, SubModuleListToCompile,
 				ModulesToLink),
@@ -759,7 +850,7 @@
 			globals__io_set_trace_level(TraceLevel)
 		;
 			compile_all_submodules(FileName,
-				ModuleName - NestedSubModules,
+				ModuleName, NestedSubModules,
 				MaybeTimestamp, ReadModules,
 				FindTimestampFiles, SubModuleListToCompile,
 				ModulesToLink)
@@ -777,42 +868,46 @@
 	%
 	% i.e. compile nested modules to a single C file.
 
-:- pred compile_all_submodules(string, pair(module_name, list(module_name)),
+:- pred compile_all_submodules(string, module_name, list(module_name),
 	maybe(timestamp), read_modules, find_timestamp_file_names,
 	list(pair(module_name, item_list)),
 	list(string), io__state, io__state).
-:- mode compile_all_submodules(in, in, in, in, in(find_timestamp_file_names),
-	in, out, di, uo) is det.
+:- mode compile_all_submodules(in, in, in, in, in,
+	in(find_timestamp_file_names), in, out, di, uo) is det.
 
-compile_all_submodules(FileName, NestedSubModules, MaybeTimestamp, ReadModules,
-		FindTimestampFiles, SubModuleList, ModulesToLink) -->
+compile_all_submodules(FileName, SourceFileModuleName, NestedSubModules,
+		MaybeTimestamp, ReadModules, FindTimestampFiles,
+		SubModuleList, ModulesToLink) -->
 	list__foldl(
-		compile(FileName, NestedSubModules, MaybeTimestamp,
-			ReadModules, FindTimestampFiles),
+		compile(FileName, SourceFileModuleName, NestedSubModules,
+			MaybeTimestamp, ReadModules, FindTimestampFiles),
 		SubModuleList),
 	list__map_foldl(module_to_link, SubModuleList, ModulesToLink).
 
-:- pred make_interface(file_name, maybe(timestamp),
+:- pred make_interface(file_name, module_name, maybe(timestamp),
 		pair(module_name, item_list), io__state, io__state).
-:- mode make_interface(in, in, in, di, uo) is det.
+:- mode make_interface(in, in, in, in, di, uo) is det.
 
-make_interface(SourceFileName, MaybeTimestamp, ModuleName - Items) -->
-	make_interface(SourceFileName, ModuleName, MaybeTimestamp, Items).
+make_interface(SourceFileName, SourceFileModuleName, MaybeTimestamp,
+		ModuleName - Items) -->
+	make_interface(SourceFileName, SourceFileModuleName,
+		ModuleName, MaybeTimestamp, Items).
 
-:- pred make_short_interface(file_name, maybe(timestamp),
+:- pred make_short_interface(file_name, module_name, maybe(timestamp),
 		pair(module_name, item_list), io__state, io__state).
-:- mode make_short_interface(in, in, in, di, uo) is det.
+:- mode make_short_interface(in, in, in, in, di, uo) is det.
 
-make_short_interface(SourceFileName, _, ModuleName - Items) -->
+make_short_interface(SourceFileName, _, _, ModuleName - Items) -->
 	make_short_interface(SourceFileName, ModuleName, Items).
 
-:- pred make_private_interface(file_name, maybe(timestamp),
+:- pred make_private_interface(file_name, module_name, maybe(timestamp),
 		pair(module_name, item_list), io__state, io__state).
-:- mode make_private_interface(in, in, in, di, uo) is det.
+:- mode make_private_interface(in, in, in, in, di, uo) is det.
 
-make_private_interface(SourceFileName, MaybeTimestamp, ModuleName - Items) -->
-	make_private_interface(SourceFileName, ModuleName,
-		MaybeTimestamp, Items).
+make_private_interface(SourceFileName, SourceFileModuleName,
+		MaybeTimestamp, ModuleName - Items) -->
+	make_private_interface(SourceFileName, SourceFileModuleName,
+		ModuleName, MaybeTimestamp, Items).
 
 :- pred halt_at_module_error(bool, module_error).
 :- mode halt_at_module_error(in, in) is semidet.
@@ -930,24 +1025,25 @@
 	% The initial arrangement has the stage numbers increasing by three
 	% so that new stages can be slotted in without too much trouble.
 
-:- pred compile(file_name, pair(module_name, list(module_name)),
+:- pred compile(file_name, module_name, list(module_name),
 	maybe(timestamp), read_modules, find_timestamp_file_names,
 	pair(module_name, item_list), io__state, io__state).
-:- mode compile(in, in, in, in, in(find_timestamp_file_names),
+:- mode compile(in, in, in, in, in, in(find_timestamp_file_names),
 	in, di, uo) is det.
 
-compile(SourceFileName, RootModuleName - NestedSubModules0,
+compile(SourceFileName, SourceFileModuleName, NestedSubModules0,
 		MaybeTimestamp, ReadModules, FindTimestampFiles,
 		ModuleName - Items) -->
 	check_for_no_exports(Items, ModuleName),
-	grab_imported_modules(SourceFileName, ModuleName, ReadModules,
-		MaybeTimestamp, Items, Module, Error2),
+	{ ModuleName = SourceFileModuleName ->
+		NestedSubModules = NestedSubModules0
+	;
+		NestedSubModules = []
+	},
+	grab_imported_modules(SourceFileName, SourceFileModuleName, ModuleName,
+		NestedSubModules, ReadModules, MaybeTimestamp,
+		Items, Module, Error2),
 	( { Error2 \= fatal_module_errors } ->
-		{ ModuleName = RootModuleName ->
-			NestedSubModules = NestedSubModules0
-		;
-			NestedSubModules = []
-		},
 		mercury_compile(Module, NestedSubModules, FindTimestampFiles)
 	;
 		[]
@@ -1039,8 +1135,9 @@
 				{ HasMain = mercury_compile__mlds_has_main(
 					MLDS) },
 				mercury_compile__mlds_to_il_assembler(MLDS),
-				mercury_compile__il_assemble(ModuleName,
-					HasMain)
+				io__output_stream(OutputStream),
+				mercury_compile__il_assemble(OutputStream,
+					ModuleName, HasMain, _Succeeded)
 			)
 		    ; { Target = java } ->
 			{ HLDS = HLDS50 },
@@ -1049,7 +1146,9 @@
 			( { TargetCodeOnly = yes } ->
 				[]
 			;
-				mercury_compile__compile_java_file(ModuleName)
+				io__output_stream(OutputStream),
+				mercury_compile__compile_java_file(
+					OutputStream, ModuleName, _Succeeded)
 			)
 		    ; { Target = asm } ->
 		    	% compile directly to assembler using the gcc back-end
@@ -1074,12 +1173,16 @@
 						".c", no, CCode_C_File),
 					globals__io_lookup_string_option(
 						object_file_extension, Obj),
-					module_name_to_file_name(ModuleName,
-						"__c_code" ++ Obj,
+					{ ForeignModuleName =
+						foreign_language_module_name(
+							ModuleName, c) },
+					module_name_to_file_name(
+						ForeignModuleName, Obj,
 						yes, CCode_O_File),
-					mercury_compile__single_c_to_obj(
-						CCode_C_File, CCode_O_File,
-						_CompileOK),
+					io__output_stream(OutputStream),
+					mercury_compile__compile_c_file(
+						OutputStream, CCode_C_File,
+						CCode_O_File, _CompileOK),
 					% add this object file to the list
 					% of extra object files to link in
 					globals__io_lookup_accumulating_option(
@@ -1104,7 +1207,8 @@
 					object_file_extension, Obj),
 				module_name_to_file_name(ModuleName, Obj, yes,
 					O_File),
-				mercury_compile__single_c_to_obj(
+				io__output_stream(OutputStream),
+				mercury_compile__compile_c_file(OutputStream,
 					C_File, O_File, _CompileOK)
 			)
 		    ;
@@ -1134,15 +1238,15 @@
 	).
 
 	% return `yes' iff this module defines the main/2 entry point.
-:- func mercury_compile__mlds_has_main(mlds) = bool.
+:- func mercury_compile__mlds_has_main(mlds) = has_main.
 mercury_compile__mlds_has_main(MLDS) =
 	(
 		MLDS = mlds(_, _, _, Defns),
 		defns_contain_main(Defns)
 	->
-		yes
+		has_main
 	;
-		no
+		no_main
 	).
 
 %-----------------------------------------------------------------------------%
@@ -1154,11 +1258,14 @@
 :- mode mercury_compile__pre_hlds_pass(in, in, out, out, out, out, out, out,
 		di, uo) is det.
 
-mercury_compile__pre_hlds_pass(ModuleImports0, DontWriteDFile,
+mercury_compile__pre_hlds_pass(ModuleImports0, DontWriteDFile0,
 		HLDS1, QualInfo, MaybeTimestamps,
 		UndefTypes, UndefModes, FoundError) -->
 	globals__io_lookup_bool_option(statistics, Stats),
 	globals__io_lookup_bool_option(verbose, Verbose),
+	globals__io_lookup_bool_option(generate_mmake_module_dependencies,
+		WriteDFile),
+	{ DontWriteDFile = DontWriteDFile0 `or` not(WriteDFile) },
 
 	{ module_imports_get_module_name(ModuleImports0, Module) },
 
@@ -1203,7 +1310,15 @@
 	;
 		{ module_info_get_all_deps(HLDS0, AllDeps) },
 		write_dependency_file(ModuleImports0, AllDeps,
-			MaybeTransOptDeps)
+			MaybeTransOptDeps),
+		globals__io_lookup_bool_option(
+			generate_mmc_make_module_dependencies,
+			OutputMMCMakeDeps),
+		( { OutputMMCMakeDeps = yes } ->
+			make__write_module_dep_file(ModuleImports0)
+		;
+			[]
+		)
 	),
 
 	% Only stop on syntax errors in .opt files.
@@ -1297,13 +1412,10 @@
 			% not creating the .opt or .trans opt file, then import
 			% the trans_opt files for all the modules that are
 			% imported (or used), and for all ancestor modules.
-			{ Imports0 = module_imports(_File, _Module, Ancestors,
-				InterfaceImports, ImplementationImports,
-				_IndirectImports, _PublicChildren, _FactDeps,
-				_ForeignCode, _ForeignImports, _Items,
-				_Error, _Timestamps) },
-			{ list__condense([Ancestors, InterfaceImports,
-				ImplementationImports], TransOptFiles) },
+			{ list__condense(
+				[Imports0 ^ parent_deps, Imports0 ^ int_deps,
+					Imports0 ^ impl_deps],
+				TransOptFiles) },
 			trans_opt__grab_optfiles(Imports1, TransOptFiles,
 				Imports, Error2)
 		;
@@ -1556,7 +1668,7 @@
 			module_name_to_file_name(ModuleName,
 				".opt", no, OptName),
 			search_for_file(IntermodDirs, OptName, Found),
-			( { Found = yes } ->
+			( { Found = yes(_) } ->
 				{ UpdateStatus = yes },
 				io__seen
 			;
@@ -2379,11 +2491,13 @@
 		{ module_info_name(ModuleInfo0, ModuleName) },
 		module_name_to_file_name(ModuleName, ".dependency_graph", yes,
 			FileName),
-		io__tell(FileName, Res),
-		( { Res = ok } ->
+		io__open_output(FileName, Res),
+		( { Res = ok(FileStream) } ->
+			io__set_output_stream(FileStream, OutputStream),
 			dependency_graph__write_dependency_graph(ModuleInfo0,
 							ModuleInfo),
-			io__told,
+			io__set_output_stream(OutputStream, _),
+			io__close_output(FileStream),
 			maybe_write_string(Verbose, " done.\n")
 		;
 			report_error("unable to write dependency graph."),
@@ -2414,13 +2528,15 @@
 		{ module_info_name(ModuleInfo0, ModuleName) },
 		module_name_to_file_name(ModuleName, ".prof", yes,
 						ProfFileName),
-		io__tell(ProfFileName, Res),
+		io__open_output(ProfFileName, Res),
 		(
-			{ Res = ok }
+			{ Res = ok(FileStream) }
 		->
+			io__set_output_stream(FileStream, OutputStream),
 			dependency_graph__write_prof_dependency_graph(
 						ModuleInfo0, ModuleInfo),
-			io__told
+			io__set_output_stream(OutputStream, _),
+			io__close_output(FileStream)
 		;
 			report_error("unable to write profiling static call graph."),
 			{ ModuleInfo = ModuleInfo0 }
@@ -3086,7 +3202,9 @@
 	%
 	globals__io_lookup_bool_option(target_code_only, TargetCodeOnly),
 	( { TargetCodeOnly = no } ->
-		mercury_compile__c_to_obj(ModuleName, NumChunks, CompileOK),
+		io__output_stream(OutputStream),
+		mercury_compile__c_to_obj(OutputStream,
+			ModuleName, NumChunks, CompileOK),
 		{ bool__not(CompileOK, CompileErrors) }
 	;
 		{ CompileErrors = no }
@@ -3373,17 +3491,26 @@
 	maybe_write_string(Verbose, "% Finished converting MLDS to IL.\n"),
 	maybe_report_stats(Stats).
 
-:- pred mercury_compile__il_assemble(module_name, bool, io__state, io__state).
-:- mode mercury_compile__il_assemble(in, in, di, uo) is det.
-
-mercury_compile__il_assemble(ModuleName, HasMain) -->
+mercury_compile__il_assemble(ErrorStream, ModuleName,
+			HasMain, Succeeded) -->
 	module_name_to_file_name(ModuleName, ".il", no, IL_File),
-	module_name_to_file_name(ModuleName, ".dll", no, DLL_File),
-	module_name_to_file_name(ModuleName, ".exe", no, EXE_File),
+	( { HasMain = has_main } ->
+		module_name_to_file_name(ModuleName, ".exe", no, TargetFile)
+	;	
+		module_name_to_file_name(ModuleName, ".dll", no, TargetFile)
+	),
+	mercury_compile__il_assemble(ErrorStream, IL_File, TargetFile,
+		HasMain, Succeeded).
+	
+mercury_compile__il_assemble(ErrorStream, IL_File, TargetFile,
+		HasMain, Succeeded) -->
 	globals__io_lookup_bool_option(verbose, Verbose),
 	maybe_write_string(Verbose, "% Assembling `"),
 	maybe_write_string(Verbose, IL_File),
 	maybe_write_string(Verbose, "':\n"),
+	globals__io_lookup_string_option(il_assembler, ILASM),
+	globals__io_lookup_accumulating_option(ilasm_flags, ILASMFlagsList),
+	{ join_string_list(ILASMFlagsList, "", "", " ", ILASMFlags) },
 	{ Verbose = yes ->
 		VerboseOpt = ""
 	;
@@ -3395,50 +3522,110 @@
 	;
 		DebugOpt = ""
 	},
-	{ HasMain = yes ->
-		TargetOpt = "",
-		TargetFile = EXE_File
+	{ HasMain = has_main ->
+		TargetOpt = ""
 	;	
-		TargetOpt = "/dll ",
-		TargetFile = DLL_File
+		TargetOpt = "/dll "
+	},
+	{ string__append_list([ILASM, " ", VerboseOpt, DebugOpt, TargetOpt,
+		ILASMFlags, " /out=", TargetFile, " ", IL_File], Command) },
+	invoke_system_command(ErrorStream, verbose_commands,
+		Command, Succeeded).
+
+mercury_compile__compile_managed_cplusplus_file(ErrorStream,
+		MCPPFileName, DLLFileName, Succeeded) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	maybe_write_string(Verbose, "% Compiling `"),
+	maybe_write_string(Verbose, MCPPFileName),
+	maybe_write_string(Verbose, "':\n"),
+	globals__io_lookup_string_option(mcpp_compiler, MCPP),
+	globals__io_lookup_accumulating_option(mcpp_flags, MCPPFlagsList),
+	{ join_string_list(MCPPFlagsList, "", "", " ", MCPPFlags) },
+	globals__io_lookup_bool_option(target_debug, Debug),
+	{ Debug = yes ->
+		DebugOpt = "" % XXX
+	;
+		DebugOpt = ""
 	},
-	{ OutputOpt = "/out=" },
-	{ string__append_list(["ilasm ", VerboseOpt, DebugOpt, TargetOpt,
-		OutputOpt, TargetFile, " ", IL_File], Command) },
-	invoke_system_command(Command, Succeeded),
-	( { Succeeded = no } ->
-		report_error("problem assembling IL file.")
+
+	% XXX Should we introduce a `--mcpp-include-directory' option?
+	globals__io_lookup_accumulating_option(c_include_directory,
+	 	C_Incl_Dirs),
+	{ InclOpts = string__append_list(list__condense(list__map(
+	 	(func(C_INCL) = ["-I", C_INCL, " "]), C_Incl_Dirs))) },
+
+	% XXX Should we use a separate dll_directories options?
+	globals__io_lookup_accumulating_option(link_library_directories,
+	 	DLLDirs),
+	{ DLLDirOpts = string__append_list(list__condense(list__map(
+	 	(func(DLLDir) = ["-AI", DLLDir, " "]), DLLDirs))) },
+
+	{ string__append_list([MCPP, " -CLR ", DebugOpt, InclOpts,
+		DLLDirOpts, MCPPFlags, " ", MCPPFileName,
+		"-link -noentry mscoree.lib -dll -out:", DLLFileName],
+		Command) },
+	invoke_system_command(ErrorStream, verbose_commands,
+		Command, Succeeded).
+
+mercury_compile__compile_csharp_file(ErrorStream,
+		CSharpFileName, DLLFileName, Succeeded) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	maybe_write_string(Verbose, "% Compiling `"),
+	maybe_write_string(Verbose, CSharpFileName),
+	maybe_write_string(Verbose, "':\n"),
+	globals__io_lookup_string_option(csharp_compiler, CSC),
+	globals__io_lookup_accumulating_option(csharp_flags, CSCFlagsList),
+	{ join_string_list(CSCFlagsList, "", "", " ", CSCFlags) },
+	globals__io_lookup_bool_option(target_debug, Debug),
+	{ Debug = yes ->
+		DebugOpt = "" % XXX
 	;
-		[]
-	).
+		DebugOpt = ""
+	},
 
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
+	% XXX Should we use a separate dll_directories options?
+	globals__io_lookup_accumulating_option(link_library_directories,
+	 	DLLDirs),
+	{ DLLDirOpts = string__append_list(list__condense(list__map(
+	 	(func(DLLDir) = ["/lib:", DLLDir, " "]), DLLDirs))) },
+
+	{ string__append_list([CSC, " -CLR ", DebugOpt,
+		" /t:library ", DLLDirOpts, CSCFlags, " ",
+		" /out:", DLLFileName, CSharpFileName], Command) },
+	invoke_system_command(ErrorStream, verbose_commands,
+		Command, Succeeded).
 
-:- type compiler_type ---> gcc ; lcc ; unknown.
+%-----------------------------------------------------------------------------%
 
-:- pred mercury_compile__c_to_obj(module_name, int, bool, io__state, io__state).
-:- mode mercury_compile__c_to_obj(in, in, out, di, uo) is det.
+:- pred mercury_compile__c_to_obj(io__output_stream, module_name,
+		int, bool, io__state, io__state).
+:- mode mercury_compile__c_to_obj(in, in, in, out, di, uo) is det.
 
-mercury_compile__c_to_obj(ModuleName, NumChunks, Succeeded) -->
+mercury_compile__c_to_obj(ErrorStream, ModuleName, NumChunks, Succeeded) -->
 	globals__io_lookup_bool_option(split_c_files, SplitFiles),
 	( { SplitFiles = yes } ->
-		mercury_compile__c_to_obj_list(ModuleName, 0, NumChunks,
-			Succeeded)
+		mercury_compile__split_c_to_obj(ErrorStream, ModuleName,
+			NumChunks, Succeeded)
 	;
 		globals__io_lookup_string_option(object_file_extension, Obj),
 		module_name_to_file_name(ModuleName, ".c", no, C_File),
 		module_name_to_file_name(ModuleName, Obj, yes, O_File),
-		mercury_compile__single_c_to_obj(C_File, O_File, Succeeded)
+		mercury_compile__compile_c_file(ErrorStream,
+			C_File, O_File, Succeeded)
 	).
 
-:- pred mercury_compile__c_to_obj_list(module_name, int, int, bool,
-					io__state, io__state).
-:- mode mercury_compile__c_to_obj_list(in, in, in, out, di, uo) is det.
+mercury_compile__split_c_to_obj(ErrorStream, ModuleName,
+		NumChunks, Succeeded) -->
+	mercury_compile__split_c_to_obj(ErrorStream, ModuleName,
+		0, NumChunks, Succeeded).
 
 	% compile each of the C files in `<module>.dir'
+:- pred mercury_compile__split_c_to_obj(io__output_stream, module_name,
+		int, int, bool, io__state, io__state).
+:- mode mercury_compile__split_c_to_obj(in, in, in, in, out, di, uo) is det.
 
-mercury_compile__c_to_obj_list(ModuleName, Chunk, NumChunks, Succeeded) -->
+mercury_compile__split_c_to_obj(ErrorStream, ModuleName,
+		Chunk, NumChunks, Succeeded) -->
 	( { Chunk > NumChunks } ->
 		{ Succeeded = yes }
 	;
@@ -3447,24 +3634,29 @@
 			".c", C_File),
 		module_name_to_split_c_file_name(ModuleName, Chunk,
 			Obj, O_File),
-		mercury_compile__single_c_to_obj(C_File, O_File, Succeeded0),
+		mercury_compile__compile_c_file(ErrorStream,
+			C_File, O_File, Succeeded0),
 		( { Succeeded0 = no } ->
 			{ Succeeded = no }
 		;
 			{ Chunk1 is Chunk + 1 },
-			mercury_compile__c_to_obj_list(ModuleName,
-				Chunk1, NumChunks, Succeeded)
+			mercury_compile__split_c_to_obj(ErrorStream,
+				ModuleName, Chunk1, NumChunks, Succeeded)
 		)
 	).
 
-:- pred mercury_compile__single_c_to_obj(string, string, bool,
-					io__state, io__state).
-:- mode mercury_compile__single_c_to_obj(in, in, out, di, uo) is det.
-
 % WARNING: The code here duplicates the functionality of scripts/mgnuc.in.
 % Any changes there may also require changes here, and vice versa.
 
-mercury_compile__single_c_to_obj(C_File, O_File, Succeeded) -->
+:- type compiler_type ---> gcc ; lcc ; unknown.
+
+mercury_compile__compile_c_file(ErrorStream, ModuleName, Succeeded) -->
+	module_name_to_file_name(ModuleName, ".c", yes, C_File),
+	globals__io_lookup_string_option(object_file_extension, ObjExt),
+	module_name_to_file_name(ModuleName, ObjExt, yes, O_File),
+	compile_c_file(ErrorStream, C_File, O_File, Succeeded).
+
+mercury_compile__compile_c_file(ErrorStream, C_File, O_File, Succeeded) -->
 	globals__io_lookup_bool_option(verbose, Verbose),
 	globals__io_lookup_string_option(c_flag_to_name_object_file,
 			NameObjectFile),
@@ -3700,17 +3892,12 @@
 		UseTrailOpt, MinimalModelOpt, TypeLayoutOpt,
 		InlineAllocOpt, WarningOpt, CFLAGS,
 		" -c ", C_File, " ", NameObjectFile, O_File], Command) },
-	invoke_system_command(Command, Succeeded),
-	( { Succeeded = no } ->
-		report_error("problem compiling C file.")
-	;
-		[]
-	).
+	invoke_system_command(ErrorStream, verbose_commands,
+		Command, Succeeded).
 
-:- pred mercury_compile__compile_java_file(module_name, io__state, io__state).
-:- mode mercury_compile__compile_java_file(in, di, uo) is det.
+%-----------------------------------------------------------------------------%
 
-mercury_compile__compile_java_file(ModuleName) -->
+mercury_compile__compile_java_file(ErrorStream, ModuleName, Succeeded) -->
 	module_name_to_file_name(ModuleName, ".java", no, JavaFile),
 	globals__io_lookup_bool_option(verbose, Verbose),
 	maybe_write_string(Verbose, "% Compiling `"),
@@ -3742,18 +3929,18 @@
 	% Also be careful that each option is separated by spaces.
 	{ string__append_list([JavaCompiler, " ", InclOpt,
 		Target_DebugOpt, JAVAFLAGS, JavaFile], Command) },
-	invoke_system_command(Command, Succeeded),
-	( { Succeeded = no } ->
-		report_error("problem compiling Java file.")
-	;
-		[]
-	).
+	invoke_system_command(ErrorStream, verbose_commands,
+		Command, Succeeded).
 
-:- pred mercury_compile__asm_to_obj(string, string, bool,
-					io__state, io__state).
-:- mode mercury_compile__asm_to_obj(in, in, out, di, uo) is det.
+%-----------------------------------------------------------------------------%
+
+mercury_compile__assemble(ErrorStream, ModuleName, Succeeded) -->
+	globals__io_lookup_bool_option(pic, Pic),
+	{ AsmExt = (Pic = yes -> ".pic_s" ; ".s") },
+	module_name_to_file_name(ModuleName, AsmExt, no, AsmFile),
+	globals__io_lookup_string_option(object_file_extension, Obj),
+	module_name_to_file_name(ModuleName, Obj, yes, ObjFile),
 
-mercury_compile__asm_to_obj(AsmFile, ObjFile, Succeeded) -->
 	globals__io_lookup_bool_option(verbose, Verbose),
 	maybe_write_string(Verbose, "% Assembling `"),
 	maybe_write_string(Verbose, AsmFile),
@@ -3769,21 +3956,16 @@
 	% Also be careful that each option is separated by spaces.
 	{ string__append_list([CC, " ", CFLAGS,
 		" -c ", AsmFile, " ", NameObjectFile, ObjFile], Command) },
-	invoke_system_command(Command, Succeeded),
-	( { Succeeded = no } ->
-		report_error("problem assembling the assembler file.")
-	;
-		[]
-	).
+	invoke_system_command(ErrorStream, verbose_commands,
+		Command, Succeeded).
 
 %-----------------------------------------------------------------------------%
 
-:- pred mercury_compile__link_module_list(list(string), io__state, io__state).
-:- mode mercury_compile__link_module_list(in, di, uo) is det.
+:- pred mercury_compile__link_module_list(list(string),
+		bool, io__state, io__state).
+:- mode mercury_compile__link_module_list(in, out, di, uo) is det.
 
-mercury_compile__link_module_list(Modules) -->
-	globals__io_lookup_bool_option(verbose, Verbose),
-	globals__io_lookup_bool_option(statistics, Stats),
+mercury_compile__link_module_list(Modules, Succeeded) -->
 	globals__io_lookup_string_option(output_file_name, OutputFileName0),
 	( { OutputFileName0 = "" } ->
 	    ( { Modules = [Module | _] } ->
@@ -3795,124 +3977,254 @@
 	    { OutputFileName = OutputFileName0 }
 	),
 
-	{ file_name_to_module_name(OutputFileName, ModuleName) },
-	globals__io_lookup_string_option(object_file_extension, Obj),
-	{ string__append("_init", Obj, InitObj) },
-	module_name_to_file_name(ModuleName, "_init.c", yes, InitCFileName),
-	module_name_to_file_name(ModuleName, InitObj, yes, InitObjFileName),
+	{ file_name_to_module_name(OutputFileName, MainModuleName) },
 
+	globals__io_lookup_string_option(object_file_extension, Obj),
 	globals__io_get_target(Target),
 	globals__io_lookup_bool_option(split_c_files, SplitFiles),
+	io__output_stream(OutputStream),
 	( { Target = asm } ->
 	    % for --target asm, we generate everything into a single object file
 	    ( { Modules = [FirstModule | _] } ->
-		join_module_list([FirstModule], Obj, [], ObjectsList),
-		{ string__append_list(ObjectsList, Objects) }
+		join_module_list([FirstModule], Obj, [], ObjectsList)
 	    ;
 		{ error("link_module_list: no modules") }
 	    ),
 	    { MakeLibCmdOK = yes }
 	; { SplitFiles = yes } ->
-	    module_name_to_file_name(ModuleName, ".a", yes, SplitLibFileName),
+	    globals__io_lookup_string_option(library_extension, LibExt),
+	    module_name_to_file_name(MainModuleName, LibExt,
+	    	yes, SplitLibFileName),
 	    { string__append(".dir/*", Obj, DirObj) },
 	    join_module_list(Modules, DirObj, [], ObjectList),
-	    { list__append(
-		["ar cr ", SplitLibFileName, " " | ObjectList],
-		[" && ranlib ", SplitLibFileName],
-		MakeLibCmdList) },
-	    { string__append_list(MakeLibCmdList, MakeLibCmd) },
-	    invoke_system_command(MakeLibCmd, MakeLibCmdOK),
-	    { Objects = SplitLibFileName }
+	    create_archive(OutputStream, SplitLibFileName,
+	    	ObjectList, MakeLibCmdOK),
+	    { ObjectsList = [SplitLibFileName] }
 	;
 	    { MakeLibCmdOK = yes },
-	    join_module_list(Modules, Obj, [], ObjectsList),
-	    { string__append_list(ObjectsList, Objects) }
+	    join_module_list(Modules, Obj, [], ObjectsList)
 	),
 	( { MakeLibCmdOK = no } ->
-	    report_error("creation of object file library failed.")
+    	    { Succeeded = no }
 	;
-	    % create the initialization C file
-	    maybe_write_string(Verbose, "% Creating initialization file...\n"),
-	    globals__io_get_trace_level(TraceLevel),
-            { trace_level_is_none(TraceLevel) = no ->
-		TraceOpt = "--trace "
+	    { list__map(
+	    	(pred(ModuleStr::in, ModuleName::out) is det :-
+			dir__basename(ModuleStr, ModuleStrBase),
+			file_name_to_module_name(ModuleStrBase, ModuleName)
+		),
+		Modules, ModuleNames) },
+	    { MustCompile = yes },
+	    mercury_compile__make_init_obj_file(OutputStream,
+	    	MustCompile, MainModuleName, ModuleNames, InitObjResult),
+	    (
+	    	{ InitObjResult = yes(InitObjFileName) },
+		globals__io_lookup_accumulating_option(link_objects,
+			ExtraLinkObjectsList),
+	        mercury_compile__link(OutputStream, executable, MainModuleName,
+	    	    [InitObjFileName | ObjectsList] ++ ExtraLinkObjectsList,
+		    Succeeded)
 	    ;
+		{ InitObjResult = no },
+		{ Succeeded = no }
+	    )
+	).
+
+mercury_compile__make_init_obj_file(ErrorStream,
+		ModuleName, ModuleNames, Result) -->
+	{ MustCompile = no },
+	mercury_compile__make_init_obj_file(ErrorStream,
+		MustCompile, ModuleName, ModuleNames, Result).
+
+:- pred mercury_compile__make_init_obj_file(io__output_stream, bool,
+	module_name, list(module_name), maybe(file_name),
+	io__state, io__state).
+:- mode mercury_compile__make_init_obj_file(in,
+	in, in, in, out, di, uo) is det.
+
+mercury_compile__make_init_obj_file(ErrorStream, MustCompile, ModuleName,
+		ModuleNames, Result) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	globals__io_lookup_bool_option(statistics, Stats),
+	maybe_write_string(Verbose, "% Creating initialization file...\n"),
+
+	globals__io_get_trace_level(TraceLevel),
+	{ trace_level_is_none(TraceLevel) = no ->
+		TraceOpt = "--trace "
+	;
 		TraceOpt = ""
-	    },
-	    globals__io_get_globals(Globals),
-	    { compute_grade(Globals, Grade) },
-
-	    globals__io_lookup_accumulating_option(init_file_directories,
-			InitFileDirsList),
-	    { join_string_list(InitFileDirsList, "-I ", "",
-			" ", InitFileDirs) },
-
-	    globals__io_lookup_accumulating_option(init_files,
-			InitFileNamesList),
-	    { join_string_list(InitFileNamesList, "", "",
-			" ", InitFileNames) },
-
-	    join_module_list(Modules, ".c", [], CFileNames),
-	    { MkInitCmd = string__append_list(
-	    	["c2init --grade ", Grade, " ", TraceOpt,
-		" --init-c-file ", InitCFileName, " ", InitFileDirs, " ",
-		InitFileNames, " " | CFileNames]) },
-	    invoke_shell_command(MkInitCmd, MkInitOK),
-	    maybe_report_stats(Stats),
-	    ( { MkInitOK = no } ->
-		report_error("creation of init file failed.")
-	    ;
-		% compile it
-		maybe_write_string(Verbose,
+	},
+	globals__io_get_globals(Globals),
+	{ compute_grade(Globals, Grade) },
+
+	globals__io_lookup_string_option(object_file_extension, Obj),
+	{ string__append("_init", Obj, InitObj) },
+	module_name_to_file_name(ModuleName, "_init.c", yes, InitCFileName),
+	module_name_to_file_name(ModuleName, InitObj, yes, InitObjFileName),
+
+	list__map_foldl(
+	    (pred(ThisModuleName::in, CFileName::out, di, uo) is det -->
+		module_name_to_file_name(ThisModuleName, ".c", no,
+			CFileName)
+	    ), ModuleNames, CFileNameList),
+	{ join_string_list(CFileNameList, "", "", " ", CFileNames) },
+
+	globals__io_lookup_accumulating_option(link_flags, LinkFlagsList),
+	{ join_string_list(LinkFlagsList, "", "", " ", LinkFlags) },
+
+	globals__io_lookup_accumulating_option(init_file_directories,
+		InitFileDirsList),
+	{ join_string_list(InitFileDirsList, "-I ", "", " ", InitFileDirs) },
+
+	globals__io_lookup_accumulating_option(init_files, InitFileNamesList),
+	{ join_string_list(InitFileNamesList, "", "", " ", InitFileNames) },
+
+	{ TmpInitCFileName = InitCFileName ++ ".tmp" },
+	{ MkInitCmd = string__append_list(
+		["c2init --grade ", Grade, " ", TraceOpt, LinkFlags,
+		" --init-c-file ", TmpInitCFileName, " ",
+		InitFileDirs, " ", InitFileNames, " ", CFileNames]) },
+	invoke_shell_command(ErrorStream, verbose, MkInitCmd, MkInitOK0),
+	maybe_report_stats(Stats),
+	( { MkInitOK0 = yes } ->
+	    update_interface(InitCFileName, MkInitOK1),
+	    (
+	    	{ MkInitOK1 = yes },
+
+		(
+		    { MustCompile = yes },
+		    { Compile = yes }
+		;
+		    { MustCompile = no },
+		    io__file_modification_time(InitCFileName,
+				InitCModTimeResult),
+		    io__file_modification_time(InitObjFileName,
+				InitObjModTimeResult),
+		    {
+			InitObjModTimeResult = ok(InitObjModTime),
+			InitCModTimeResult = ok(InitCModTime),
+			compare(TimeCompare, InitObjModTime, InitCModTime),
+			( TimeCompare = (=)
+			; TimeCompare = (>)
+			)
+		    ->
+			Compile = no
+		    ;
+			Compile = yes
+		    }
+		),
+
+		(
+		    { Compile = yes },
+		    maybe_write_string(Verbose,
 			"% Compiling initialization file...\n"),
-		mercury_compile__single_c_to_obj(InitCFileName, InitObjFileName,
-			CompileOK),
+
+		    compile_c_file(ErrorStream, InitCFileName,
+		    	InitObjFileName, CompileOK),
+		    maybe_report_stats(Stats),
+		    ( { CompileOK = no } ->
+			{ Result = no }
+		    ;
+			{ Result = yes(InitObjFileName) }
+		    )
+	        ;
+		    { Compile = no },
+		    { Result = yes(InitObjFileName) }
+		)
+	    ;
+	    	{ MkInitOK1 = no },
+		{ Result = no }
+	    )
+	;
+	    { Result = no }
+	).
+
+mercury_compile__link(ErrorStream, LinkTargetType, ModuleName,
+		ObjectsList, Succeeded) -->
+	globals__io_lookup_bool_option(verbose, Verbose),
+	globals__io_lookup_bool_option(statistics, Stats),
+
+	globals__io_get_trace_level(TraceLevel),
+	{ trace_level_is_none(TraceLevel) = no ->
+		TraceOpt = "--trace "
+	;
+		TraceOpt = ""
+	},
+	globals__io_get_globals(Globals),
+	{ compute_grade(Globals, Grade) },
+
+	maybe_write_string(Verbose, "% Linking...\n"),
+	( { LinkTargetType = static_library } ->
+	    	globals__io_lookup_string_option(library_extension, LibExt),
+		module_name_to_file_name(ModuleName, LibExt, yes, LibName),
+		create_archive(ErrorStream, LibName, ObjectsList, ArCmdOK),
 		maybe_report_stats(Stats),
-		( { CompileOK = no } ->
-		    report_error("compilation of init file failed.")
+		( { ArCmdOK = no } ->
+			{ Succeeded = no }
 		;
-		    maybe_write_string(Verbose, "% Linking...\n"),
-		    globals__io_lookup_bool_option(target_debug, Target_Debug),
-		    { Target_Debug = yes ->
-		    	Target_Debug_Opt = "--no-strip "
-		    ;
-		    	Target_Debug_Opt = ""
-		    },
-		    globals__io_lookup_accumulating_option(link_flags,
+			{ Succeeded = yes }
+		)
+	;
+		{ LinkTargetType = shared_library ->
+			SharedLibOpt = "--make-shared-lib ",
+			FileExtOpt = shared_library_extension
+		;
+			SharedLibOpt = "",
+			FileExtOpt = executable_file_extension
+		},
+		globals__io_lookup_string_option(FileExtOpt, OutputFileExt),
+		module_name_to_file_name(ModuleName, OutputFileExt,
+			yes, OutputFileName),
+		globals__io_lookup_bool_option(target_debug, Target_Debug),
+		{ Target_Debug = yes ->
+			Target_Debug_Opt = "--no-strip "
+		;
+			Target_Debug_Opt = ""
+		},
+		{ join_string_list(ObjectsList, "", "", " ", Objects) },
+		globals__io_lookup_accumulating_option(link_flags,
 				LinkFlagsList),
-		    { join_string_list(LinkFlagsList, "", "", " ", LinkFlags) },
-		    globals__io_lookup_accumulating_option(
+		{ join_string_list(LinkFlagsList, "", "", " ", LinkFlags) },
+		globals__io_lookup_accumulating_option(
 				link_library_directories,
 				LinkLibraryDirectoriesList),
-		    { join_string_list(LinkLibraryDirectoriesList, "-L", "",
+		{ join_string_list(LinkLibraryDirectoriesList, "-L", "",
 				" ", LinkLibraryDirectories) },
-		    globals__io_lookup_accumulating_option(link_libraries,
+		globals__io_lookup_accumulating_option(link_libraries,
 				LinkLibrariesList),
-		    { join_string_list(LinkLibrariesList, "-l", "", " ",
+		{ join_string_list(LinkLibrariesList, "-l", "", " ",
 				LinkLibraries) },
-		    globals__io_lookup_accumulating_option(link_objects,
-				LinkObjectsList),
-		    { join_string_list(LinkObjectsList, "", "", " ",
-				LinkObjects) },
-		    { string__append_list(
-			["ml --grade ", Grade, " ",
+		{ string__append_list(
+			["ml --grade ", Grade, " ", SharedLibOpt,
 			Target_Debug_Opt, TraceOpt, LinkFlags,
-			" -o ", OutputFileName, " ",
-			InitObjFileName, " ", Objects, " ",
-			LinkObjects, " ",
+			" -o ", OutputFileName, " ", Objects, " ", 
 			LinkLibraryDirectories, " ", LinkLibraries],
 			LinkCmd) },
-		    invoke_shell_command(LinkCmd, LinkCmdOK),
-		    maybe_report_stats(Stats),
-		    ( { LinkCmdOK = no } ->
-			report_error("link failed.")
-		    ;
-			[]
-		    )
-		)
-	    )
+		invoke_shell_command(ErrorStream, verbose_commands,
+			LinkCmd, Succeeded),
+		maybe_report_stats(Stats)
 	).
 
+:- pred create_archive(io__output_stream, file_name, list(file_name),
+		bool, io__state, io__state).
+:- mode create_archive(in, in, in, out, di, uo) is det.
+
+create_archive(ErrorStream, LibFileName, ObjectList, MakeLibCmdOK) -->
+	globals__io_lookup_string_option(create_archive_command, ArCmd),
+	globals__io_lookup_accumulating_option(
+		create_archive_command_flags, ArFlagsList),
+	{ join_string_list(ArFlagsList, "", "", " ", ArFlags) },
+	globals__io_lookup_string_option(
+		create_archive_command_output_flag, ArOutputFlag),
+	globals__io_lookup_string_option(ranlib_command, RanLib),
+	{ list__append(
+		[ArCmd, " ", ArFlags, " ", ArOutputFlag, " ",
+		LibFileName, " " | ObjectList],
+		[" && ", RanLib, " ", LibFileName],
+		MakeLibCmdList) },
+	{ string__append_list(MakeLibCmdList, MakeLibCmd) },
+	invoke_system_command(ErrorStream, verbose_commands,
+		MakeLibCmd, MakeLibCmdOK).
+
 	% join_string_list(Strings, Prefix, Suffix, Serarator, Result)
 	%
 	% Appends the strings in the list `Strings' together into the
@@ -3996,10 +4308,12 @@
 	maybe_write_string(Verbose, DumpFile),
 	maybe_write_string(Verbose, "'..."),
 	maybe_flush_output(Verbose),
-	io__tell(DumpFile, Res),
-	( { Res = ok } ->
+	io__open_output(DumpFile, Res),
+	( { Res = ok(FileStream) } ->
+		io__set_output_stream(FileStream, OutputStream),
 		hlds_out__write_hlds(0, HLDS),
-		io__told,
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream),
 		maybe_write_string(Verbose, " done.\n"),
 		maybe_report_stats(Stats)
 	;
@@ -4052,11 +4366,13 @@
 	maybe_write_string(Verbose, DumpFile),
 	maybe_write_string(Verbose, "'..."),
 	maybe_flush_output(Verbose),
-	io__tell(DumpFile, Res),
-	( { Res = ok } ->
+	io__open_output(DumpFile, Res),
+	( { Res = ok(FileStream) } ->
+		io__set_output_stream(FileStream, OutputStream),
 		pprint__write(80, pprint__to_doc(MLDS)),
 		io__nl,
-		io__told,
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream),
 		maybe_write_string(Verbose, " done.\n"),
 		maybe_report_stats(Stats)
 	;
@@ -4082,11 +4398,13 @@
 		maybe_write_string(Verbose, DumpFile),
 		maybe_write_string(Verbose, "'..."),
 		maybe_flush_output(Verbose),
-		io__tell(DumpFile, Res),
-		( { Res = ok } ->
+		io__open_output(DumpFile, Res),
+		( { Res = ok(FileStream) } ->
+			io__set_output_stream(FileStream, OutputStream),
 			list__foldl(rl_dump__write_procedure(ModuleInfo), 
 				Procs),
-			io__told,
+			io__set_output_stream(OutputStream, _),
+			io__close_output(FileStream),
 			maybe_write_string(Verbose, " done.\n")
 		;
 			maybe_write_string(Verbose, "\n"),
Index: compiler/mercury_to_mercury.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mercury_to_mercury.m,v
retrieving revision 1.202
diff -u -u -r1.202 mercury_to_mercury.m
--- compiler/mercury_to_mercury.m	25 Jan 2002 05:57:35 -0000	1.202
+++ compiler/mercury_to_mercury.m	26 Jan 2002 18:44:03 -0000
@@ -336,18 +336,19 @@
 %-----------------------------------------------------------------------------%
 
 convert_to_mercury(ModuleName, OutputFileName, Items) -->
-	io__stderr_stream(StdErr),
-	io__tell(OutputFileName, Res),
-	( { Res = ok } ->
+	io__open_output(OutputFileName, Res),
+	( { Res = ok(FileStream) } ->
 		globals__io_lookup_bool_option(verbose, Verbose),
 		( { Verbose = yes } ->
-			io__write_string(StdErr, "% Writing output to "),
-			io__write_string(StdErr, OutputFileName),
-			io__write_string(StdErr, "..."),
-			io__flush_output(StdErr)
+			io__write_string("% Writing output to "),
+			io__write_string(OutputFileName),
+			io__write_string("..."),
+			io__flush_output
 		;
 			[]
 		),
+
+		io__set_output_stream(FileStream, OutputStream),
 		io__write_string(":- module "),
 		mercury_output_bracketed_sym_name(ModuleName),
 		io__write_string(".\n"),
@@ -356,16 +357,18 @@
 		% declaration above.
 		{ UnqualifiedItemNames = yes },
 		mercury_output_item_list(UnqualifiedItemNames, Items),
+		io__set_output_stream(OutputStream, _),
+		io__close_output(FileStream),
+
 		( { Verbose = yes } ->
-			io__write_string(StdErr, " done\n")
+			io__write_string(" done\n")
 		;
 			[]
-		),
-		io__told
+		)
 	;
-		io__write_string(StdErr, "Error: couldn't open file `"),
-		io__write_string(StdErr, OutputFileName),
-		io__write_string(StdErr, "' for output.\n")
+		io__write_string("Error: couldn't open file `"),
+		io__write_string(OutputFileName),
+		io__write_string("' for output.\n")
 	).
 
 %-----------------------------------------------------------------------------%
@@ -1522,11 +1525,8 @@
 :- mode mercury_output_type_defn(in, in, in, in, in, di, uo) is det.
 
 mercury_output_type_defn(_VarSet, _Name, _Args, uu_type(_Body), Context) -->
-	io__stderr_stream(StdErr),
-	io__set_output_stream(StdErr, OldStream),
 	prog_out__write_context(Context),
-	io__write_string("warning: undiscriminated union types not yet supported.\n"),
-	io__set_output_stream(OldStream, _).
+	io__write_string("warning: undiscriminated union types not yet supported.\n").
 
 mercury_output_type_defn(VarSet, Name, Args, abstract_type, Context) -->
 	io__write_string(":- type "),
Index: compiler/modes.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/modes.m,v
retrieving revision 1.254
diff -u -u -r1.254 modes.m
--- compiler/modes.m	20 Jul 2001 14:14:05 -0000	1.254
+++ compiler/modes.m	2 Jan 2002 14:52:36 -0000
@@ -338,15 +338,11 @@
 modecheck(Module0, Module, UnsafeToContinue) -->
 	globals__io_lookup_bool_option(statistics, Statistics),
 	globals__io_lookup_bool_option(verbose, Verbose),
-	io__stderr_stream(StdErr),
-	io__set_output_stream(StdErr, OldStream),
 
 	maybe_write_string(Verbose, "% Mode-checking clauses...\n"),
 	check_pred_modes(check_modes, may_change_called_proc,
 		Module0, Module, UnsafeToContinue),
-	maybe_report_stats(Statistics),
-
-	io__set_output_stream(OldStream, _).
+	maybe_report_stats(Statistics).
 
 %-----------------------------------------------------------------------------%
 	
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list