[m-rev.] for review: io.make_temp now reterns a result rather than throw exceptions
Paul Bone
paul at bone.id.au
Wed Apr 20 12:44:38 AEST 2016
For review by Peter Wang who suggested this change.
---
io.make_temp now reterns a result rather than throw exceptions
The make_temp predicates would throw an exception if they were unsuccessful,
New versions of make_temp/3 and make_temp/5 have been created (named
make_temp_res) to avoid braking code. make_temp/3 and make_temp/5 have been
marked as obsolete. make_temp_directory/3 and make_temp_directory/5 have
been modified directly as they are very new. This closes bug #408
Some routines in compiler/compile_target_code.m used the name returned by
make_temp and added a suffix before using the resulting file, this sould
create unnecessary temporary files that I beleive were never cleaned up. So
I've added a suffix argument to make_temp_res/5 and make_temp_directory/5
(now they're make_temp_res/6 and make_temp_directory/6).
library/io.m:
As above.
Remove out-of-date comment.
compiler/compile_target_code.m:
Conform to changes in io.m.
Use the new suffix argument to reduce the number of temporary files
created during linking.
compiler/fact_table.m:
compiler/make.module_target.m:
compiler/make.util.m:
compiler/module_cmds.m:
compiler/prog_event.m:
compiler/write_deps_file.m:
deep_profiler/conf.m:
Conform to changes in io.m.
---
compiler/compile_target_code.m | 200 +++++---
compiler/fact_table.m | 57 ++-
compiler/make.module_target.m | 96 ++--
compiler/make.util.m | 28 +-
compiler/module_cmds.m | 172 ++++---
compiler/prog_event.m | 82 +--
compiler/write_deps_file.m | 1105 ++++++++++++++++++++--------------------
deep_profiler/conf.m | 73 +--
library/io.m | 190 ++++---
9 files changed, 1092 insertions(+), 911 deletions(-)
diff --git a/compiler/compile_target_code.m b/compiler/compile_target_code.m
index 48453b4..ce11561 100644
--- a/compiler/compile_target_code.m
+++ b/compiler/compile_target_code.m
@@ -1254,27 +1254,37 @@ invoke_mkinit(Globals, InitFileStream, Verbosity,
% mkinit expects unquoted file names.
join_string_list(FileNames, "", "\n", "", TargetFileNames),
- io.make_temp(TmpFile, !IO),
- io.open_output(TmpFile, OpenResult, !IO),
+ io.make_temp_res(TmpFileResult, !IO),
(
- OpenResult = ok(TmpStream),
- io.write_string(TmpStream, TargetFileNames, !IO),
- io.close_output(TmpStream, !IO),
+ TmpFileResult = ok(TmpFile),
+ io.open_output(TmpFile, OpenResult, !IO),
+ (
+ OpenResult = ok(TmpStream),
+ io.write_string(TmpStream, TargetFileNames, !IO),
+ io.close_output(TmpStream, !IO),
- MkInitCmd = string.append_list([MkInit, " ", Args, " -f ", TmpFile]),
- invoke_system_command(Globals, InitFileStream, Verbosity,
- MkInitCmd, MkInitOK0, !IO),
+ MkInitCmd = string.append_list([MkInit, " ", Args, " -f ", TmpFile]),
+ invoke_system_command(Globals, InitFileStream, Verbosity,
+ MkInitCmd, MkInitOK0, !IO),
- io.remove_file(TmpFile, RemoveResult, !IO),
- (
- RemoveResult = ok,
- MkInitOK = MkInitOK0
+ io.remove_file(TmpFile, RemoveResult, !IO),
+ (
+ RemoveResult = ok,
+ MkInitOK = MkInitOK0
+ ;
+ RemoveResult = error(_),
+ MkInitOK = no
+ )
;
- RemoveResult = error(_),
+ OpenResult = error(Error),
+ io.format(io.stderr_stream, "%s: %s\n",
+ [s(TmpFile), s(error_message(Error))], !IO),
MkInitOK = no
)
;
- OpenResult = error(_),
+ TmpFileResult = error(Error),
+ io.format(io.stderr_stream, "Could not create temporary file: %s\n",
+ [s(error_message(Error))], !IO),
MkInitOK = no
).
@@ -1977,18 +1987,31 @@ link_exe_or_shared_lib(Globals, ErrorStream, LinkTargetType, ModuleName,
% and thus overflow the command line, so in this case
% we first create an archive of all of the object files.
RestrictedCommandLine = yes,
- io.make_temp(TmpFile, !IO),
globals.lookup_string_option(Globals, library_extension, LibExt),
- TmpArchive = TmpFile ++ LibExt,
- % Only include actual object files in the temporary archive,
- % not other files such as other archives.
- filter_object_files(Globals, ObjectsList,
- ProperObjectFiles, NonObjectFiles),
- create_archive(Globals, ErrorStream, TmpArchive, yes,
- ProperObjectFiles, ArchiveSucceeded, !IO),
- MaybeDeleteTmpArchive = yes(TmpArchive),
- join_quoted_string_list([TmpArchive | NonObjectFiles],
- "", "", " ", Objects)
+ io.get_temp_directory(TempDir, !IO),
+ io.make_temp_res(TempDir, "", "." ++ LibExt, TmpFileResult, !IO),
+ (
+ TmpFileResult = ok(TmpFile),
+ % XXX: This is why my /tmp directory is always full of crap.
+ TmpArchive = TmpFile ++ LibExt,
+ % Only include actual object files in the temporary archive,
+ % not other files such as other archives.
+ filter_object_files(Globals, ObjectsList,
+ ProperObjectFiles, NonObjectFiles),
+ create_archive(Globals, ErrorStream, TmpArchive, yes,
+ ProperObjectFiles, ArchiveSucceeded, !IO),
+ MaybeDeleteTmpArchive = yes(TmpArchive),
+ join_quoted_string_list([TmpArchive | NonObjectFiles],
+ "", "", " ", Objects)
+ ;
+ TmpFileResult = error(Error),
+ io.format(stderr_stream,
+ "Could not create temporary file: %s\n",
+ [s(error_message(Error))], !IO),
+ ArchiveSucceeded = no,
+ MaybeDeleteTmpArchive = no,
+ join_quoted_string_list(ObjectsList, "", "", " ", Objects)
+ )
;
RestrictedCommandLine = no,
ArchiveSucceeded = yes,
@@ -3043,30 +3066,37 @@ create_java_exe_or_lib(Globals, ErrorStream, LinkTargetType, MainModuleName,
% extremely long. We create the temporary file in the current directory to
% avoid problems under Cygwin, where absolute paths will be interpreted
% incorrectly when passed to a non-Cygwin jar program.
- io.make_temp(".", "mtmp", TempFileName, !IO),
- io.open_output(TempFileName, OpenResult, !IO),
- (
- OpenResult = ok(Stream),
- list.foldl(write_jar_class_argument(Stream, ClassSubDir),
- ListClassFiles, !IO),
- io.close_output(Stream, !IO),
-
- Cmd = string.append_list(
- [Jar, " cf ", JarFileName, " @", TempFileName]),
- invoke_system_command(Globals, ErrorStream, cmd_verbose_commands, Cmd,
- Succeeded0, !IO),
- io.remove_file(TempFileName, _, !IO),
+ io.make_temp_res(".", "mtmp", "", TempFileNameResult, !IO),
+ (
+ TempFileNameResult = ok(TempFileName),
+ io.open_output(TempFileName, OpenResult, !IO),
(
- Succeeded0 = yes
+ OpenResult = ok(Stream),
+ list.foldl(write_jar_class_argument(Stream, ClassSubDir),
+ ListClassFiles, !IO),
+ io.close_output(Stream, !IO),
+
+ Cmd = string.append_list(
+ [Jar, " cf ", JarFileName, " @", TempFileName]),
+ invoke_system_command(Globals, ErrorStream,
+ cmd_verbose_commands, Cmd, Succeeded0, !IO),
+ io.remove_file(TempFileName, _, !IO),
+ (
+ Succeeded0 = yes
+ ;
+ Succeeded0 = no,
+ io.remove_file(JarFileName, _, !IO)
+ )
;
- Succeeded0 = no,
- io.remove_file(JarFileName, _, !IO)
+ OpenResult = error(Error),
+ io.format(ErrorStream, "Error creating `%s': %s\n",
+ [s(TempFileName), s(error_message(Error))], !IO),
+ Succeeded0 = no
)
;
- OpenResult = error(Error),
- io.error_message(Error, ErrorMsg),
- io.format(ErrorStream, "Error creating `%s': %s\n",
- [s(TempFileName), s(ErrorMsg)], !IO),
+ TempFileNameResult = error(Error),
+ io.format(ErrorStream, "Could not create temporary file: %s\n",
+ [s(error_message(Error))], !IO),
Succeeded0 = no
),
( if
@@ -3463,48 +3493,58 @@ invoke_long_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
RestrictedCommandLine = yes,
% Avoid generating very long command lines by using @files.
- io.make_temp(TmpFile, !IO),
- io.open_output(TmpFile, OpenResult, !IO),
+ io.make_temp_res(TmpFileResult, !IO),
(
- OpenResult = ok(TmpStream),
-
- % We need to escape any \ before writing them to the file,
- % otherwise we lose them.
- TmpFileArgs = string.replace_all(Args, "\\", "\\\\"),
-
- io.write_string(TmpStream, TmpFileArgs, !IO),
- io.close_output(TmpStream, !IO),
-
- globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
- AtFileName = at_file_name(Globals, TmpFile),
+ TmpFileResult = ok(TmpFile),
+ io.open_output(TmpFile, OpenResult, !IO),
(
- VeryVerbose = yes,
- io.format("%% Args placed in %s: `%s'\n",
- [s(AtFileName), s(TmpFileArgs)], !IO),
- io.flush_output(!IO)
- ;
- VeryVerbose = no
- ),
-
- ( if NonAtArgs = "" then
- FullCmd = Cmd ++ " " ++ AtFileName
- else
- string.append_list([Cmd, " ", NonAtArgs, " ", AtFileName],
- FullCmd)
- ),
- invoke_system_command_maybe_filter_output(Globals, ErrorStream,
- Verbosity, FullCmd, MaybeProcessOutput, Succeeded0, !IO),
+ OpenResult = ok(TmpStream),
+
+ % We need to escape any \ before writing them to the file,
+ % otherwise we lose them.
+ TmpFileArgs = string.replace_all(Args, "\\", "\\\\"),
+
+ io.write_string(TmpStream, TmpFileArgs, !IO),
+ io.close_output(TmpStream, !IO),
+
+ globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
+ AtFileName = at_file_name(Globals, TmpFile),
+ (
+ VeryVerbose = yes,
+ io.format("%% Args placed in %s: `%s'\n",
+ [s(AtFileName), s(TmpFileArgs)], !IO),
+ io.flush_output(!IO)
+ ;
+ VeryVerbose = no
+ ),
- io.remove_file(TmpFile, RemoveResult, !IO),
- (
- RemoveResult = ok,
- Succeeded = Succeeded0
+ ( if NonAtArgs = "" then
+ FullCmd = Cmd ++ " " ++ AtFileName
+ else
+ string.append_list([Cmd, " ", NonAtArgs, " ", AtFileName],
+ FullCmd)
+ ),
+ invoke_system_command_maybe_filter_output(Globals, ErrorStream,
+ Verbosity, FullCmd, MaybeProcessOutput, Succeeded0, !IO),
+
+ io.remove_file(TmpFile, RemoveResult, !IO),
+ (
+ RemoveResult = ok,
+ Succeeded = Succeeded0
+ ;
+ RemoveResult = error(_),
+ Succeeded = no
+ )
;
- RemoveResult = error(_),
+ OpenResult = error(Error),
+ io.format(stderr_stream, "%s: %s\n",
+ [s(TmpFile), s(error_message(Error))], !IO),
Succeeded = no
)
;
- OpenResult = error(_),
+ TmpFileResult = error(Error),
+ io.format(stderr_stream, "Could not create temporary file: %s\n",
+ [s(error_message(Error))], !IO),
Succeeded = no
)
;
diff --git a/compiler/fact_table.m b/compiler/fact_table.m
index cf01d59..7b4559a 100644
--- a/compiler/fact_table.m
+++ b/compiler/fact_table.m
@@ -309,15 +309,27 @@ fact_table_compile_facts_2(PredName, Arity, FileName, !PredInfo, Context,
infer_determinism_pass_2(ProcFiles, Globals, ExistsAllInMode,
ProcTable0, ProcTable, !IO),
pred_info_set_proc_table(ProcTable, !PredInfo),
- io.make_temp(DataFileName, !IO),
- write_fact_table_arrays(ProcFiles, DataFileName, StructName,
- ProcTable, ModuleInfo, NumFacts, FactArgInfos, WriteHashTables,
- WriteDataAfterSorting, OutputStream, C_HeaderCode1,
- PrimaryProcID, !IO),
- write_fact_table_numfacts(PredName, NumFacts, OutputStream,
- C_HeaderCode3, !IO),
- string.append_list([C_HeaderCode0, C_HeaderCode1,
- C_HeaderCode2, C_HeaderCode3], C_HeaderCode)
+ io.make_temp_res(DataFileNameResult, !IO),
+ (
+ DataFileNameResult = ok(DataFileName),
+ write_fact_table_arrays(ProcFiles, DataFileName, StructName,
+ ProcTable, ModuleInfo, NumFacts, FactArgInfos,
+ WriteHashTables, WriteDataAfterSorting, OutputStream,
+ C_HeaderCode1, PrimaryProcID, !IO),
+ write_fact_table_numfacts(PredName, NumFacts, OutputStream,
+ C_HeaderCode3, !IO),
+ string.append_list([C_HeaderCode0, C_HeaderCode1,
+ C_HeaderCode2, C_HeaderCode3], C_HeaderCode)
+ ;
+ DataFileNameResult = error(Error),
+ ErrorReport = no - [
+ words("Could not create temporary file:"),
+ quote(error_message(Error))],
+ print_error_reports(Globals, [ErrorReport], !IO),
+ C_HeaderCode = C_HeaderCode0,
+ PrimaryProcID = invalid_proc_id,
+ DataFileName = ""
+ )
;
OpenCompileErrors = [_ | _],
print_error_reports(Globals, OpenCompileErrors, !IO),
@@ -967,18 +979,27 @@ fact_table_mode_type([Mode | Modes], ModuleInfo, ModeType) :-
open_sort_files([], [], !Errors, !IO).
open_sort_files([ProcID | ProcIDs], ProcStreams, !Errors, !IO) :-
- io.make_temp(SortFileName, !IO),
- io.open_output(SortFileName, Result, !IO),
+ io.make_temp_res(SortFileNameResult, !IO),
(
- Result = ok(Stream),
- open_sort_files(ProcIDs, ProcStreams0, !Errors, !IO),
- ProcStreams = [proc_stream(ProcID, Stream) | ProcStreams0]
+ SortFileNameResult = ok(SortFileName),
+ io.open_output(SortFileName, Result, !IO),
+ (
+ Result = ok(Stream),
+ open_sort_files(ProcIDs, ProcStreams0, !Errors, !IO),
+ ProcStreams = [proc_stream(ProcID, Stream) | ProcStreams0]
+ ;
+ Result = error(ErrorCode),
+ ProcStreams = [],
+ io.error_message(ErrorCode, Message),
+ string.format("Error opening file `%s' for output: %s.",
+ [s(SortFileName), s(Message)], Msg),
+ add_error_report([words(Msg)], !Errors)
+ )
;
- Result = error(ErrorCode),
+ SortFileNameResult = error(Error),
ProcStreams = [],
- io.error_message(ErrorCode, Message),
- string.format("Error opening file `%s' for output: %s.",
- [s(SortFileName), s(Message)], Msg),
+ string.format("Could not create temporary file: %s.",
+ [s(error_message(Error))], Msg),
add_error_report([words(Msg)], !Errors)
).
diff --git a/compiler/make.module_target.m b/compiler/make.module_target.m
index 6d1f22f..0a9d037 100644
--- a/compiler/make.module_target.m
+++ b/compiler/make.module_target.m
@@ -362,51 +362,69 @@ build_target(Globals, CompilationTask, TargetFile, Imports, TouchedTargetFiles,
% We need a temporary file to pass the arguments to the mmc process
% which will do the compilation. It is created here (not in invoke_mmc)
% so it can be cleaned up by build_with_check_for_interrupt.
- io.make_temp(ArgFileName, !IO),
- MaybeArgFileName = yes(ArgFileName)
+ io.make_temp_res(ArgFileNameResult, !IO),
+ (
+ ArgFileNameResult = ok(ArgFileName),
+ MaybeArgFileName = yes(ArgFileName),
+ ArgFileNameSuccess = ok `with_type` io.res
+ ;
+ ArgFileNameResult = error(Error),
+ MaybeArgFileName = no,
+ ArgFileNameSuccess = error(Error)
+ )
else
- MaybeArgFileName = no
+ MaybeArgFileName = no,
+ ArgFileNameSuccess = ok
),
- Cleanup =
- ( pred(!.MakeInfo::in, !:MakeInfo::out, !.IO::di, !:IO::uo) is det :-
- % XXX Remove `.int.tmp' files.
- list.foldl2(make_remove_target_file(Globals, very_verbose),
- TouchedTargetFiles, !MakeInfo, !IO),
- list.foldl2(make_remove_file(Globals, very_verbose), TouchedFiles,
- !MakeInfo, !IO),
- (
- MaybeArgFileName = yes(ArgFileName2),
- io.remove_file(ArgFileName2, _, !IO)
- ;
- MaybeArgFileName = no
- )
- ),
-
- get_real_milliseconds(Time0, !IO),
- globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
- build_with_check_for_interrupt(VeryVerbose,
- build_with_module_options_and_output_redirect(Globals, ModuleName,
- ExtraOptions ++ TaskOptions,
- build_target_2(ModuleName, Task, MaybeArgFileName, Imports)),
- Cleanup, Succeeded, !Info, !IO),
- record_made_target_2(Globals, Succeeded, TargetFile, TouchedTargetFiles,
- TouchedFiles, !Info, !IO),
- get_real_milliseconds(Time, !IO),
- globals.lookup_bool_option(Globals, show_make_times, ShowMakeTimes),
(
- ShowMakeTimes = yes,
- DiffSecs = float(Time - Time0) / 1000.0,
- % Avoid cluttering the screen with short running times.
- ( if DiffSecs >= 0.4 then
- io.write_string("Making ", !IO),
- make_write_target_file(Globals, TargetFile, !IO),
- io.format(" took %.2fs\n", [f(DiffSecs)], !IO)
- else
- true
+ ArgFileNameSuccess = ok,
+ Cleanup = (pred(!.MakeInfo::in, !:MakeInfo::out, !.IO::di, !:IO::uo)
+ is det :-
+ % XXX Remove `.int.tmp' files.
+ list.foldl2(make_remove_target_file(Globals, very_verbose),
+ TouchedTargetFiles, !MakeInfo, !IO),
+ list.foldl2(make_remove_file(Globals, very_verbose),
+ TouchedFiles, !MakeInfo, !IO),
+ (
+ MaybeArgFileName = yes(ArgFileName2),
+ io.remove_file(ArgFileName2, _, !IO)
+ ;
+ MaybeArgFileName = no
+ )
+ ),
+
+ get_real_milliseconds(Time0, !IO),
+ globals.lookup_bool_option(Globals, very_verbose, VeryVerbose),
+ build_with_check_for_interrupt(VeryVerbose,
+ build_with_module_options_and_output_redirect(Globals, ModuleName,
+ ExtraOptions ++ TaskOptions,
+ build_target_2(ModuleName, Task, MaybeArgFileName, Imports)),
+ Cleanup, Succeeded, !Info, !IO),
+ record_made_target_2(Globals, Succeeded, TargetFile, TouchedTargetFiles,
+ TouchedFiles, !Info, !IO),
+ get_real_milliseconds(Time, !IO),
+
+ globals.lookup_bool_option(Globals, show_make_times, ShowMakeTimes),
+ (
+ ShowMakeTimes = yes,
+ DiffSecs = float(Time - Time0) / 1000.0,
+ % Avoid cluttering the screen with short running times.
+ ( if DiffSecs >= 0.4 then
+ io.write_string("Making ", !IO),
+ make_write_target_file(Globals, TargetFile, !IO),
+ io.format(" took %.2fs\n", [f(DiffSecs)], !IO)
+ else
+ true
+ )
+ ;
+ ShowMakeTimes = no
)
;
- ShowMakeTimes = no
+ ArgFileNameSuccess = error(ArgFileError),
+ io.format(stderr_stream, "Could not create temporary file: %s\n",
+ [s(error_message(ArgFileError))], !IO),
+ Succeeded = no
).
:- pred build_target_2(module_name::in, compilation_task_type::in,
diff --git a/compiler/make.util.m b/compiler/make.util.m
index 4b2abc1..7488416 100644
--- a/compiler/make.util.m
+++ b/compiler/make.util.m
@@ -1074,16 +1074,24 @@ redirect_output(_ModuleName, MaybeErrorStream, !Info, !IO) :-
% the part of the error file that relates to the current command. It will
% be appended to the error file later.
- io.make_temp(ErrorFileName, !IO),
- io.open_output(ErrorFileName, ErrorFileRes, !IO),
+ io.make_temp_res(ErrorFileNameResult, !IO),
(
- ErrorFileRes = ok(ErrorOutputStream),
- MaybeErrorStream = yes(ErrorOutputStream)
+ ErrorFileNameResult = ok(ErrorFileName),
+ io.open_output(ErrorFileName, ErrorFileRes, !IO),
+ (
+ ErrorFileRes = ok(ErrorOutputStream),
+ MaybeErrorStream = yes(ErrorOutputStream)
+ ;
+ ErrorFileRes = error(IOError),
+ MaybeErrorStream = no,
+ with_locked_stdout(!.Info,
+ write_error_opening_output(ErrorFileName, IOError), !IO)
+ )
;
- ErrorFileRes = error(IOError),
+ ErrorFileNameResult = error(IOError),
MaybeErrorStream = no,
- with_locked_stdout(!.Info,
- write_error_opening_output(ErrorFileName, IOError), !IO)
+ with_locked_stdout(!.Info, write_error_creating_temp_file(IOError),
+ !IO)
).
unredirect_output(Globals, ModuleName, ErrorOutputStream, !Info, !IO) :-
@@ -1182,6 +1190,12 @@ write_error_opening_file(FileName, Error, !IO) :-
io.format("Error opening `%s': %s\n",
[s(FileName), s(io.error_message(Error))], !IO).
+:- pred write_error_creating_temp_file(io.error::in, io::di, io::uo) is det.
+
+write_error_creating_temp_file(Error, !IO) :-
+ io.format("Error creating temporary file: %s\n",
+ [s(io.error_message(Error))], !IO).
+
%-----------------------------------------------------------------------------%
get_timestamp_file_timestamp(Globals, target_file(ModuleName, FileType),
diff --git a/compiler/module_cmds.m b/compiler/module_cmds.m
index 2e56455..b54a199 100644
--- a/compiler/module_cmds.m
+++ b/compiler/module_cmds.m
@@ -575,46 +575,56 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
% the output from the command would go to the current C output
% and error streams.
- io.make_temp(TmpFile, !IO),
- ( if use_dotnet then
- % XXX can't use Bourne shell syntax to redirect on .NET
- % XXX the output will go to the wrong place!
- CommandRedirected = Command
- else if use_win32 then
- % On windows we can't in general redirect standard error in the
- % shell.
- CommandRedirected = Command ++ " > " ++ TmpFile
- else
- CommandRedirected =
- string.append_list([Command, " > ", TmpFile, " 2>&1"])
- ),
- io.call_system_return_signal(CommandRedirected, Result, !IO),
+ io.make_temp_res(TmpFileResult, !IO),
(
- Result = ok(exited(Status)),
- maybe_write_string(PrintCommand, "% done.\n", !IO),
- ( if Status = 0 then
- CommandSucceeded = yes
+ TmpFileResult = ok(TmpFile),
+ ( if use_dotnet then
+ % XXX can't use Bourne shell syntax to redirect on .NET
+ % XXX the output will go to the wrong place!
+ CommandRedirected = Command
+ else if use_win32 then
+ % On windows we can't in general redirect standard error in the
+ % shell.
+ CommandRedirected = Command ++ " > " ++ TmpFile
else
- % The command should have produced output describing the error.
+ 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),
+ ( if Status = 0 then
+ CommandSucceeded = yes
+ else
+ % The command should have produced output describing the error.
+ CommandSucceeded = no
+ )
+ ;
+ Result = ok(signalled(Signal)),
+ report_error_to_stream(ErrorStream,
+ "system command received signal "
+ ++ int_to_string(Signal) ++ ".", !IO),
+ % Also report the error to standard output, because if we raise the
+ % signal this error may not ever been seen, the process stops and
+ % the user is confused.
+ report_error("system command received signal "
+ ++ int_to_string(Signal) ++ ".", !IO),
+
+ % Make sure the current process gets the signal. Some systems (e.g.
+ % Linux) ignore SIGINT during a call to system().
+ raise_signal(Signal, !IO),
+ CommandSucceeded = no
+ ;
+ Result = error(Error),
+ report_error_to_stream(ErrorStream, io.error_message(Error), !IO),
CommandSucceeded = no
)
;
- Result = ok(signalled(Signal)),
- report_error_to_stream(ErrorStream, "system command received signal "
- ++ int_to_string(Signal) ++ ".", !IO),
- % Also report the error to standard output, because if we raise the
- % signal this error may not ever been seen, the process stops and
- % the user is confused.
- report_error("system command received signal "
- ++ int_to_string(Signal) ++ ".", !IO),
-
- % Make sure the current process gets the signal. Some systems (e.g.
- % Linux) ignore SIGINT during a call to system().
- raise_signal(Signal, !IO),
- CommandSucceeded = no
- ;
- Result = error(Error),
- report_error_to_stream(ErrorStream, io.error_message(Error), !IO),
+ TmpFileResult = error(Error),
+ report_error_to_stream(ErrorStream,
+ "Could not create temporary file: " ++ error_message(Error), !IO),
+ TmpFile = "",
CommandSucceeded = no
),
@@ -623,54 +633,64 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
not use_dotnet,
MaybeProcessOutput = yes(ProcessOutput)
then
- io.make_temp(ProcessedTmpFile, !IO),
-
- % XXX we should get rid of use_win32
- ( if use_win32 then
- get_system_env_type(Globals, SystemEnvType),
- ( if SystemEnvType = env_type_powershell then
- ProcessOutputRedirected = string.append_list(
- ["Get-Content ", TmpFile, " | ", ProcessOutput,
- " > ", ProcessedTmpFile, " 2>&1"])
+ io.make_temp_res(ProcessedTmpFileResult, !IO),
+ (
+ ProcessedTmpFileResult = ok(ProcessedTmpFile),
+
+ % XXX we should get rid of use_win32
+ ( if use_win32 then
+ get_system_env_type(Globals, SystemEnvType),
+ ( if SystemEnvType = env_type_powershell then
+ ProcessOutputRedirected = string.append_list(
+ ["Get-Content ", TmpFile, " | ", ProcessOutput,
+ " > ", ProcessedTmpFile, " 2>&1"])
+ else
+ % On windows we can't in general redirect standard
+ % error in the shell.
+ ProcessOutputRedirected = string.append_list(
+ [ProcessOutput, " < ", TmpFile, " > ",
+ ProcessedTmpFile])
+ )
else
- % On windows we can't in general redirect standard
- % error in the shell.
ProcessOutputRedirected = string.append_list(
[ProcessOutput, " < ", TmpFile, " > ",
- ProcessedTmpFile])
- )
- else
- 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),
- ( if ProcessOutputStatus = 0 then
- ProcessOutputSucceeded = yes
- else
- % The command should have produced output
- % describing the error.
+ 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),
+ ( if ProcessOutputStatus = 0 then
+ ProcessOutputSucceeded = yes
+ else
+ % 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
)
;
- 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),
+ ProcessedTmpFileResult = error(ProcessTmpError),
report_error_to_stream(ErrorStream,
- io.error_message(ProcessOutputError), !IO),
- ProcessOutputSucceeded = no
+ io.error_message(ProcessTmpError), !IO),
+ ProcessOutputSucceeded = no,
+ ProcessedTmpFile = ""
)
else
ProcessOutputSucceeded = yes,
diff --git a/compiler/prog_event.m b/compiler/prog_event.m
index 65a72c0..717c06c 100644
--- a/compiler/prog_event.m
+++ b/compiler/prog_event.m
@@ -92,58 +92,74 @@ read_event_set(SpecsFileName, EventSetName, EventSpecMap, ErrorSpecs, !IO) :-
% those tools are not yet mature enough. When they are, we should switch
% to using them.
- io.make_temp(TermFileName, !IO),
- read_specs_file(SpecsFileName, TermFileName, Problem, !IO),
- ( if Problem = "" then
- io.open_input(TermFileName, TermOpenRes, !IO),
- (
- TermOpenRes = ok(TermStream),
- io.read(TermStream, TermReadRes, !IO),
+ io.make_temp_res(TermFileNameResult, !IO),
+ (
+ TermFileNameResult = ok(TermFileName),
+ read_specs_file(SpecsFileName, TermFileName, Problem, !IO),
+ ( if Problem = "" then
+ io.open_input(TermFileName, TermOpenRes, !IO),
(
- TermReadRes = ok(EventSetTerm),
- EventSetTerm = event_set_spec(EventSetName, EventSpecsTerm),
- convert_list_to_spec_map(SpecsFileName, EventSpecsTerm,
- map.init, EventSpecMap, [], ErrorSpecs)
+ TermOpenRes = ok(TermStream),
+ io.read(TermStream, TermReadRes, !IO),
+ (
+ TermReadRes = ok(EventSetTerm),
+ EventSetTerm = event_set_spec(EventSetName,
+ EventSpecsTerm),
+ convert_list_to_spec_map(SpecsFileName, EventSpecsTerm,
+ map.init, EventSpecMap, [], ErrorSpecs)
+ ;
+ TermReadRes = eof,
+ EventSetName = "",
+ EventSpecMap = map.init,
+ Pieces = [words("eof in term specification file"), nl],
+ ErrorSpec = error_spec(severity_error,
+ phase_term_to_parse_tree,
+ [error_msg(no, do_not_treat_as_first, 0,
+ [always(Pieces)])]),
+ ErrorSpecs = [ErrorSpec]
+ ;
+ TermReadRes = error(TermReadMsg, LineNumber),
+ EventSetName = "",
+ EventSpecMap = map.init,
+ Pieces = [words(TermReadMsg), nl],
+ ErrorSpec = error_spec(severity_error,
+ phase_term_to_parse_tree,
+ [simple_msg(context(TermFileName, LineNumber),
+ [always(Pieces)])]),
+ ErrorSpecs = [ErrorSpec]
+ ),
+ io.close_input(TermStream, !IO)
;
- TermReadRes = eof,
+ TermOpenRes = error(TermOpenError),
EventSetName = "",
EventSpecMap = map.init,
- Pieces = [words("eof in term specification file"), nl],
+ Pieces = [words("Could not open"), quote(TermFileName),
+ words(":"), words_quote(error_message(TermOpenError)), nl],
ErrorSpec = error_spec(severity_error,
phase_term_to_parse_tree,
[error_msg(no, do_not_treat_as_first, 0,
[always(Pieces)])]),
ErrorSpecs = [ErrorSpec]
- ;
- TermReadRes = error(TermReadMsg, LineNumber),
- EventSetName = "",
- EventSpecMap = map.init,
- Pieces = [words(TermReadMsg), nl],
- ErrorSpec = error_spec(severity_error,
- phase_term_to_parse_tree,
- [simple_msg(context(TermFileName, LineNumber),
- [always(Pieces)])]),
- ErrorSpecs = [ErrorSpec]
- ),
- io.close_input(TermStream, !IO)
- ;
- TermOpenRes = error(TermOpenError),
+ )
+ else
EventSetName = "",
EventSpecMap = map.init,
- Pieces = [words(io.error_message(TermOpenError)), nl],
+ Pieces = [words(Problem), nl],
ErrorSpec = error_spec(severity_error, phase_term_to_parse_tree,
[error_msg(no, do_not_treat_as_first, 0, [always(Pieces)])]),
ErrorSpecs = [ErrorSpec]
- )
- else
+ ),
+ io.remove_file(TermFileName, _RemoveRes, !IO)
+ ;
+ TermFileNameResult= error(TermFileNameError),
EventSetName = "",
EventSpecMap = map.init,
- Pieces = [words(Problem), nl],
+ Pieces = [words("Could not create temporary file:"),
+ words_quote(error_message(TermFileNameError)), nl],
ErrorSpec = error_spec(severity_error, phase_term_to_parse_tree,
[error_msg(no, do_not_treat_as_first, 0, [always(Pieces)])]),
ErrorSpecs = [ErrorSpec]
- ),
- io.remove_file(TermFileName, _RemoveRes, !IO).
+ ).
:- pred read_specs_file(string::in, string::in, string::out,
io::di, io::uo) is det.
diff --git a/compiler/write_deps_file.m b/compiler/write_deps_file.m
index e661e06..caac87b 100644
--- a/compiler/write_deps_file.m
+++ b/compiler/write_deps_file.m
@@ -159,606 +159,627 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
% 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),
+ io.make_temp_res(dir.dirname(DependencyFileName), "tmp_d",
+ "", TmpDependencyFileNameRes, !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),
+ TmpDependencyFileNameRes = error(Error),
+ Message = "Could not create temporary file: " ++ error_message(Error),
report_error(Message, !IO)
;
- Result = ok(DepStream),
- set.union(IntDeps, ImpDeps, LongDeps0),
- ShortDeps0 = IndirectDeps,
- set.delete(ModuleName, LongDeps0, LongDeps),
- set.difference(ShortDeps0, LongDeps, ShortDeps1),
- set.delete(ModuleName, ShortDeps1, ShortDeps),
- list.sort_and_remove_dups(FactDeps0, FactDeps),
-
+ TmpDependencyFileNameRes = ok(TmpDependencyFileName),
+ 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),
(
- MaybeTransOptDeps = yes(TransOptDeps0),
- set.intersect(set.list_to_set(TransOptDeps0), LongDeps,
- TransOptDateDeps),
-
- % Note that maybe_read_dependency_file searches for
- % this exact pattern.
- io.write_strings(DepStream, [TransOptDateFileName, " :"], !IO),
- write_dependencies_set(Globals, DepStream, ".trans_opt",
- TransOptDateDeps, !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)
;
- MaybeTransOptDeps = no
- ),
+ Result = ok(DepStream),
+ set.union(IntDeps, ImpDeps, LongDeps0),
+ ShortDeps0 = IndirectDeps,
+ set.delete(ModuleName, LongDeps0, LongDeps),
+ set.difference(ShortDeps0, LongDeps, ShortDeps1),
+ set.delete(ModuleName, ShortDeps1, ShortDeps),
+ list.sort_and_remove_dups(FactDeps0, FactDeps),
- (
- FactDeps = [_ | _],
- io.write_strings(DepStream,
- ["\n\n", MakeVarName, ".fact_tables ="], !IO),
- write_file_dependencies_list(DepStream, "", FactDeps, !IO),
- io.nl(DepStream, !IO),
- globals.lookup_bool_option(Globals, assume_gmake, AssumeGmake),
(
- 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)
+ MaybeTransOptDeps = yes(TransOptDeps0),
+ set.intersect(set.list_to_set(TransOptDeps0), LongDeps,
+ TransOptDateDeps),
+
+ % Note that maybe_read_dependency_file searches for
+ % this exact pattern.
+ io.write_strings(DepStream, [TransOptDateFileName, " :"], !IO),
+ write_dependencies_set(Globals, DepStream, ".trans_opt",
+ TransOptDateDeps, !IO)
;
- AssumeGmake = no,
- io.write_strings(DepStream,
- [MakeVarName, ".fact_tables.cs ="], !IO),
- write_fact_table_dependencies_list(Globals, DepStream,
- ".c", ModuleName, FactDeps, !IO),
- io.write_strings(DepStream, ["\n\n", MakeVarName,
- ".fact_tables.os ="], !IO),
- write_fact_table_dependencies_list(Globals, DepStream,
- ".$O", ModuleName, FactDeps, !IO),
- io.nl(DepStream, !IO)
- )
- ;
- FactDeps = []
- ),
-
- ( if string.remove_suffix(SourceFileName, ".m", SourceFileBase) then
- ErrFileName = SourceFileBase ++ ".err"
- else
- unexpected($module, $pred, "source file doesn't end in `.m'")
- ),
- module_name_to_file_name(Globals, ModuleName, ".optdate",
- do_not_create_dirs, OptDateFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".c_date",
- do_not_create_dirs, CDateFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".$O",
- do_not_create_dirs, ObjFileName, !IO),
- module_name_to_file_name(Globals, 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(Globals, ModuleName, ".pic_o",
- do_not_create_dirs, PicObjFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".int0",
- do_not_create_dirs, Int0FileName, !IO),
- io.write_strings(DepStream, ["\n\n",
- OptDateFileName, " ",
- TransOptDateFileName, " ",
- ErrFileName, " ",
- CDateFileName, " ",
- JavaDateFileName
- ], !IO),
- io.write_strings(DepStream, [" : ", SourceFileName], !IO),
- % If the module contains nested sub-modules then the `.int0' file
- % must first be built.
- ( if set.is_empty(InclDeps) then
- true
- else
- io.write_strings(DepStream, [" ", Int0FileName], !IO)
- ),
- write_dependencies_set(Globals, DepStream, ".int0", ParentDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int", LongDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int2", ShortDeps, !IO),
-
- NestedExts = [
- ".optdate",
- ".trans_opt_date",
- ".c_date",
- ".dir/*.$O",
- ".java_date"],
-
- % If a module contains nested-submodules then we need to build
- % the nested children before attempting to build the parent module.
- ( if set.is_empty(NestedDeps) then
- true
- else
- Write = (pred(Ext::in, !.LIO::di, !:LIO::uo) is det :-
- module_name_to_file_name(Globals, ModuleName, Ext,
- do_not_create_dirs, ExtName, !LIO),
- io.write_strings(DepStream, ["\n\n", ExtName, " : "], !LIO),
- write_dependencies_set(Globals, DepStream, Ext, NestedDeps,
- !LIO)
+ MaybeTransOptDeps = no
),
- list.foldl(Write, NestedExts, !IO)
- ),
-
- ForeignIncludeFiles = cord.list(ForeignIncludeFilesCord),
- % This is conservative: a target file for foreign language A does not
- % does not truly depend on a file included for foreign language B.
- write_foreign_include_file_dependencies_list(DepStream,
- SourceFileName, ForeignIncludeFiles, !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.lookup_bool_option(Globals, use_opt_files, UseOptFiles),
- globals.lookup_bool_option(Globals, intermodule_optimization,
- Intermod),
- globals.lookup_accumulating_option(Globals, intermod_directories,
- IntermodDirs),
+ (
+ FactDeps = [_ | _],
+ io.write_strings(DepStream,
+ ["\n\n", MakeVarName, ".fact_tables ="], !IO),
+ write_file_dependencies_list(DepStream, "", FactDeps, !IO),
+ io.nl(DepStream, !IO),
+ globals.lookup_bool_option(Globals, assume_gmake, AssumeGmake),
+ (
+ 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(Globals, DepStream,
+ ".c", ModuleName, FactDeps, !IO),
+ io.write_strings(DepStream, ["\n\n", MakeVarName,
+ ".fact_tables.os ="], !IO),
+ write_fact_table_dependencies_list(Globals, DepStream,
+ ".$O", ModuleName, FactDeps, !IO),
+ io.nl(DepStream, !IO)
+ )
+ ;
+ FactDeps = []
+ ),
- % 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(Globals, DepStream, ".mh",
- set.to_sorted_list(AllDeps), !IO)
- ;
- Intermod = no
- ),
- ( if
- ( Intermod = yes
- ; UseOptFiles = yes
- )
- then
- io.write_strings(DepStream, [
- "\n\n",
+ ( if string.remove_suffix(SourceFileName, ".m", SourceFileBase) then
+ ErrFileName = SourceFileBase ++ ".err"
+ else
+ unexpected($module, $pred, "source file doesn't end in `.m'")
+ ),
+ module_name_to_file_name(Globals, ModuleName, ".optdate",
+ do_not_create_dirs, OptDateFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".c_date",
+ do_not_create_dirs, CDateFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".$O",
+ do_not_create_dirs, ObjFileName, !IO),
+ module_name_to_file_name(Globals, 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(Globals, ModuleName, ".pic_o",
+ do_not_create_dirs, PicObjFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".int0",
+ do_not_create_dirs, Int0FileName, !IO),
+ io.write_strings(DepStream, ["\n\n",
+ OptDateFileName, " ",
TransOptDateFileName, " ",
ErrFileName, " ",
CDateFileName, " ",
- JavaDateFileName, " : "
+ JavaDateFileName
], !IO),
+ io.write_strings(DepStream, [" : ", SourceFileName], !IO),
+ % If the module contains nested sub-modules then the `.int0' file
+ % must first be built.
+ ( if set.is_empty(InclDeps) then
+ true
+ else
+ io.write_strings(DepStream, [" ", Int0FileName], !IO)
+ ),
+ write_dependencies_set(Globals, DepStream, ".int0", ParentDeps, !IO),
+ write_dependencies_set(Globals, DepStream, ".int", LongDeps, !IO),
+ write_dependencies_set(Globals, DepStream, ".int2", ShortDeps, !IO),
+
+ NestedExts = [
+ ".optdate",
+ ".trans_opt_date",
+ ".c_date",
+ ".dir/*.$O",
+ ".java_date"],
+
+ % If a module contains nested-submodules then we need to build
+ % the nested children before attempting to build the parent module.
+ ( if set.is_empty(NestedDeps) then
+ true
+ else
+ Write = (pred(Ext::in, !.LIO::di, !:LIO::uo) is det :-
+ module_name_to_file_name(Globals, ModuleName, Ext,
+ do_not_create_dirs, ExtName, !LIO),
+ io.write_strings(DepStream, ["\n\n", ExtName, " : "], !LIO),
+ write_dependencies_set(Globals, DepStream, Ext, NestedDeps,
+ !LIO)
+ ),
+ list.foldl(Write, NestedExts, !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.lookup_bool_option(Globals, transitive_optimization,
- TransOpt),
- globals.lookup_bool_option(Globals, use_trans_opt_files,
- UseTransOpt),
+ ForeignIncludeFiles = cord.list(ForeignIncludeFilesCord),
+ % This is conservative: a target file for foreign language A
+ % does not does not truly depend on a file included for foreign
+ % language B.
+ write_foreign_include_file_dependencies_list(DepStream,
+ SourceFileName, ForeignIncludeFiles, !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.lookup_bool_option(Globals, use_opt_files, UseOptFiles),
+ globals.lookup_bool_option(Globals, intermodule_optimization,
+ Intermod),
+ globals.lookup_accumulating_option(Globals, intermod_directories,
+ IntermodDirs),
+ % 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(Globals, DepStream, ".mh",
+ set.to_sorted_list(AllDeps), !IO)
+ ;
+ Intermod = no
+ ),
( if
- ( TransOpt = yes
- ; UseTransOpt = yes
+ ( Intermod = yes
+ ; UseOptFiles = yes
)
then
- bool.not(UseTransOpt, BuildOptFiles),
- get_both_opt_deps(Globals, BuildOptFiles, IntermodDirs,
- [ModuleName | set.to_sorted_list(LongDeps)],
- OptDeps, TransOptDeps, !IO),
- OptInt0Deps = set.union_list(
- list.map(get_ancestors_set, OptDeps)),
- write_dependencies_list(Globals, DepStream, ".opt",
- OptDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int0",
- OptInt0Deps, !IO),
-
io.write_strings(DepStream, [
"\n\n",
+ TransOptDateFileName, " ",
ErrFileName, " ",
CDateFileName, " ",
JavaDateFileName, " : "
], !IO),
- write_dependencies_list(Globals, DepStream, ".trans_opt",
- TransOptDeps, !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.lookup_bool_option(Globals, transitive_optimization,
+ TransOpt),
+ globals.lookup_bool_option(Globals, use_trans_opt_files,
+ UseTransOpt),
+
+ ( if
+ ( TransOpt = yes
+ ; UseTransOpt = yes
+ )
+ then
+ bool.not(UseTransOpt, BuildOptFiles),
+ get_both_opt_deps(Globals, BuildOptFiles, IntermodDirs,
+ [ModuleName | set.to_sorted_list(LongDeps)],
+ OptDeps, TransOptDeps, !IO),
+ OptInt0Deps = set.union_list(
+ list.map(get_ancestors_set, OptDeps)),
+ write_dependencies_list(Globals, DepStream, ".opt",
+ OptDeps, !IO),
+ write_dependencies_set(Globals, DepStream, ".int0",
+ OptInt0Deps, !IO),
+
+ io.write_strings(DepStream, [
+ "\n\n",
+ ErrFileName, " ",
+ CDateFileName, " ",
+ JavaDateFileName, " : "
+ ], !IO),
+ write_dependencies_list(Globals, DepStream, ".trans_opt",
+ TransOptDeps, !IO)
+ else
+ bool.not(UseOptFiles, BuildOptFiles),
+ get_opt_deps(Globals, BuildOptFiles, IntermodDirs, ".opt",
+ [ModuleName | set.to_sorted_list(LongDeps)],
+ OptDeps, !IO),
+ OptInt0Deps = set.union_list(
+ list.map(get_ancestors_set, OptDeps)),
+ write_dependencies_list(Globals, DepStream, ".opt",
+ OptDeps, !IO),
+ write_dependencies_set(Globals, DepStream, ".int0",
+ OptInt0Deps, !IO)
+ )
else
- bool.not(UseOptFiles, BuildOptFiles),
- get_opt_deps(Globals, BuildOptFiles, IntermodDirs, ".opt",
- [ModuleName | set.to_sorted_list(LongDeps)], OptDeps, !IO),
- OptInt0Deps = set.union_list(
- list.map(get_ancestors_set, OptDeps)),
- write_dependencies_list(Globals, DepStream, ".opt",
- OptDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int0",
- OptInt0Deps, !IO)
- )
- else
- true
- ),
+ true
+ ),
+
+ globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
+ globals.get_target(Globals, CompilationTarget),
+ ( if
+ HighLevelCode = yes,
+ CompilationTarget = target_c
+ then
+ % 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.
- globals.lookup_bool_option(Globals, highlevel_code, HighLevelCode),
- globals.get_target(Globals, CompilationTarget),
- ( if
- HighLevelCode = yes,
- CompilationTarget = target_c
- then
- % 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_set(Globals, DepStream, ".mih", AllDeps, !IO)
+ else
+ 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(Globals, ModuleName, ".c",
+ do_not_create_dirs, CFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".mh",
+ do_not_create_dirs, HeaderFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".mih",
+ do_not_create_dirs, HeaderFileName2, !IO),
io.write_strings(DepStream, [
"\n\n",
- PicObjFileName, " ",
- ObjFileName, " :"
+ HeaderFileName, " ", HeaderFileName2, " : ", CFileName, "\n"
], !IO),
- write_dependencies_set(Globals, DepStream, ".mih", AllDeps, !IO)
- else
- 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(Globals, ModuleName, ".c",
- do_not_create_dirs, CFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".mh",
- do_not_create_dirs, HeaderFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".mih",
- do_not_create_dirs, HeaderFileName2, !IO),
- io.write_strings(DepStream, [
- "\n\n",
- HeaderFileName, " ", HeaderFileName2, " : ", CFileName, "\n"
- ], !IO),
-
- % The `.module_dep' file is made as a side effect of
- % creating the `.c', `.s', or `.java'.
-
- module_name_to_file_name(Globals, ModuleName, ".java",
- do_not_create_dirs, JavaFileName, !IO),
- module_name_to_file_name(Globals, ModuleName,
- make_module_dep_file_extension, do_not_create_dirs,
- ModuleDepFileName, !IO),
- io.write_strings(DepStream, [
- "\n\n",
- "ifeq ($(findstring java,$(GRADE)),java)\n",
- ModuleDepFileName, " : ", JavaFileName, "\n",
- "else\n",
- ModuleDepFileName, " : ", CFileName, "\n",
- "endif\n"
- ], !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(Globals, ModuleName, ".date",
- do_not_create_dirs, DateFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".date0",
- do_not_create_dirs, Date0FileName, !IO),
- io.write_strings(DepStream, [
- "\n\n", DateFileName, " ", Date0FileName
- ], !IO),
- write_dependencies_set(Globals, DepStream, ".date", ParentDeps, !IO),
- io.write_strings(DepStream, [" : ", SourceFileName], !IO),
- write_dependencies_set(Globals, DepStream, ".int0", ParentDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int3", LongDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int3", ShortDeps, !IO),
-
- io.write_strings(DepStream, ["\n\n", Date0FileName], !IO),
- write_dependencies_set(Globals, DepStream, ".date0", ParentDeps, !IO),
- io.write_strings(DepStream, [" : ", SourceFileName], !IO),
- write_dependencies_set(Globals, DepStream, ".int3", LongDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int3", ShortDeps, !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_stem(SourceFileModuleName, ModuleArg)
- ;
- HaveMap = no,
- ModuleArg = SourceFileName
- ),
- globals.get_target(Globals, Target),
- module_name_to_file_name(Globals, ModuleName, ".class",
- do_not_create_dirs, ClassFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".beam",
- do_not_create_dirs, BeamFileName, !IO),
+ % The `.module_dep' file is made as a side effect of
+ % creating the `.c', `.s', or `.java'.
- (
- ContainsForeignCode = contains_foreign_code(_LangSet),
- ForeignImportModules = ForeignImportModules0
- ;
- ContainsForeignCode = contains_foreign_code_unknown,
- get_foreign_code_indicators_from_item_blocks(Globals,
- SrcItemBlocks,
- _SrcLangSet, SrcForeignImportModules, _, _),
- % XXX ITEM_LIST DirectIntItemBlocksCord should not be needed
- % XXX ITEM_LIST IndirectIntItemBlocksCord should not be needed
- IntItemBlocksCord =
- DirectIntItemBlocksCord ++ IndirectIntItemBlocksCord,
- get_foreign_code_indicators_from_item_blocks(Globals,
- cord.list(IntItemBlocksCord),
- _IntLangSet, IntForeignImportModules, _, _),
- get_foreign_code_indicators_from_item_blocks(Globals,
- cord.list(OptItemBlocksCord),
- _OptLangSet, OptForeignImportModules, _, _),
- get_foreign_code_indicators_from_item_blocks(Globals,
- cord.list(IntForOptItemBlocksCord),
- _IntForOptLangSet, IntForOptForeignImportModules, _, _),
- % If we are generating the `.dep' file, ForeignImportModuless0
- % will contain a conservative approximation to the set of
- % foreign imports needed which will include imports
- % required by imported modules.
- % XXX ITEM_LIST What is the correctness argument that supports
- % the above assertion?
- ( if
- ForeignImportModules0 = foreign_import_modules(
- C0, CSharp0, Java0, Erlang0),
- set.is_empty(C0),
- set.is_empty(CSharp0),
- set.is_empty(Java0),
- set.is_empty(Erlang0)
- then
- SrcForeignImportModules = foreign_import_modules(
- SrcC, SrcCSharp, SrcJava, SrcErlang),
- IntForeignImportModules = foreign_import_modules(
- IntC, IntCSharp, IntJava, IntErlang),
- OptForeignImportModules = foreign_import_modules(
- OptC, OptCSharp, OptJava, OptErlang),
- IntForOptForeignImportModules = foreign_import_modules(
- IntForOptC, IntForOptCSharp, IntForOptJava,
- IntForOptErlang),
- C = set.union_list([
- SrcC, IntC, OptC, IntForOptC]),
- CSharp = set.union_list([
- SrcCSharp, IntCSharp, OptCSharp, IntForOptCSharp]),
- Java= set.union_list([
- SrcJava, IntJava, OptJava, IntForOptJava]),
- Erlang = set.union_list([
- SrcErlang, IntErlang, OptErlang, IntForOptErlang]),
- ForeignImportModules = foreign_import_modules(
- C, CSharp, Java, Erlang)
- else
- ForeignImportModules = ForeignImportModules0
- )
- ;
- ContainsForeignCode = contains_no_foreign_code,
- ForeignImportModules = ForeignImportModules0
- ),
-
- ForeignImports =
- get_all_foreign_import_module_infos(ForeignImportModules),
+ module_name_to_file_name(Globals, ModuleName, ".java",
+ do_not_create_dirs, JavaFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName,
+ make_module_dep_file_extension, do_not_create_dirs,
+ ModuleDepFileName, !IO),
+ io.write_strings(DepStream, [
+ "\n\n",
+ "ifeq ($(findstring java,$(GRADE)),java)\n",
+ ModuleDepFileName, " : ", JavaFileName, "\n",
+ "else\n",
+ ModuleDepFileName, " : ", CFileName, "\n",
+ "endif\n"
+ ], !IO),
- % Handle dependencies introduced by
- % `:- pragma foreign_import_module' declarations.
+ % 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(Globals, ModuleName, ".date",
+ do_not_create_dirs, DateFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".date0",
+ do_not_create_dirs, Date0FileName, !IO),
+ io.write_strings(DepStream, [
+ "\n\n", DateFileName, " ", Date0FileName
+ ], !IO),
+ write_dependencies_set(Globals, DepStream, ".date", ParentDeps,
+ !IO),
+ io.write_strings(DepStream, [" : ", SourceFileName], !IO),
+ write_dependencies_set(Globals, DepStream, ".int0", ParentDeps,
+ !IO),
+ write_dependencies_set(Globals, DepStream, ".int3", LongDeps, !IO),
+ write_dependencies_set(Globals, DepStream, ".int3", ShortDeps,
+ !IO),
+
+ io.write_strings(DepStream, ["\n\n", Date0FileName], !IO),
+ write_dependencies_set(Globals, DepStream, ".date0", ParentDeps,
+ !IO),
+ io.write_strings(DepStream, [" : ", SourceFileName], !IO),
+ write_dependencies_set(Globals, DepStream, ".int3", LongDeps, !IO),
+ write_dependencies_set(Globals, DepStream, ".int3", ShortDeps, !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_stem(SourceFileModuleName, ModuleArg)
+ ;
+ HaveMap = no,
+ ModuleArg = SourceFileName
+ ),
- set.filter_map(
- ( pred(ForeignImportMod::in, ImportModuleName::out) is semidet :-
- ImportModuleName = foreign_import_module_name_from_module(
- ForeignImportMod, SourceFileModuleName),
+ globals.get_target(Globals, Target),
+ module_name_to_file_name(Globals, ModuleName, ".class",
+ do_not_create_dirs, ClassFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".beam",
+ do_not_create_dirs, BeamFileName, !IO),
- % XXX We can't include mercury.dll as mmake can't find it,
- % but we know that it exists.
- ImportModuleName \= unqualified("mercury")
- ), ForeignImports, ForeignImportedModuleNames),
- ( if set.is_empty(ForeignImportedModuleNames) then
- true
- else
(
- Target = target_csharp,
- % XXX don't know enough about C# yet
- ForeignImportTargets = [],
- ForeignImportExt = ".cs"
- ;
- Target = target_java,
- ForeignImportTargets = [ClassFileName],
- ForeignImportExt = ".java"
+ ContainsForeignCode = contains_foreign_code(_LangSet),
+ ForeignImportModules = ForeignImportModules0
;
- Target = target_erlang,
- ForeignImportTargets = [BeamFileName],
- ForeignImportExt = ".hrl"
+ ContainsForeignCode = contains_foreign_code_unknown,
+ get_foreign_code_indicators_from_item_blocks(Globals,
+ SrcItemBlocks,
+ _SrcLangSet, SrcForeignImportModules, _, _),
+ % XXX ITEM_LIST DirectIntItemBlocksCord should not be needed
+ % XXX ITEM_LIST IndirectIntItemBlocksCord should not be needed
+ IntItemBlocksCord =
+ DirectIntItemBlocksCord ++ IndirectIntItemBlocksCord,
+ get_foreign_code_indicators_from_item_blocks(Globals,
+ cord.list(IntItemBlocksCord),
+ _IntLangSet, IntForeignImportModules, _, _),
+ get_foreign_code_indicators_from_item_blocks(Globals,
+ cord.list(OptItemBlocksCord),
+ _OptLangSet, OptForeignImportModules, _, _),
+ get_foreign_code_indicators_from_item_blocks(Globals,
+ cord.list(IntForOptItemBlocksCord),
+ _IntForOptLangSet, IntForOptForeignImportModules, _, _),
+ % If we are generating the `.dep' file,
+ % ForeignImportModuless0 will contain a conservative
+ % approximation to the set of foreign imports needed which
+ % will include imports required by imported modules. XXX
+ % ITEM_LIST What is the correctness argument that supports
+ % the above assertion?
+ ( if
+ ForeignImportModules0 = foreign_import_modules(
+ C0, CSharp0, Java0, Erlang0),
+ set.is_empty(C0),
+ set.is_empty(CSharp0),
+ set.is_empty(Java0),
+ set.is_empty(Erlang0)
+ then
+ SrcForeignImportModules = foreign_import_modules(
+ SrcC, SrcCSharp, SrcJava, SrcErlang),
+ IntForeignImportModules = foreign_import_modules(
+ IntC, IntCSharp, IntJava, IntErlang),
+ OptForeignImportModules = foreign_import_modules(
+ OptC, OptCSharp, OptJava, OptErlang),
+ IntForOptForeignImportModules = foreign_import_modules(
+ IntForOptC, IntForOptCSharp, IntForOptJava,
+ IntForOptErlang),
+ C = set.union_list([
+ SrcC, IntC, OptC, IntForOptC]),
+ CSharp = set.union_list([
+ SrcCSharp, IntCSharp, OptCSharp, IntForOptCSharp]),
+ Java= set.union_list([
+ SrcJava, IntJava, OptJava, IntForOptJava]),
+ Erlang = set.union_list([
+ SrcErlang, IntErlang, OptErlang, IntForOptErlang]),
+ ForeignImportModules = foreign_import_modules(
+ C, CSharp, Java, Erlang)
+ else
+ ForeignImportModules = ForeignImportModules0
+ )
;
- Target = target_c,
- % NOTE: for C 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"
+ ContainsForeignCode = contains_no_foreign_code,
+ ForeignImportModules = ForeignImportModules0
),
- 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(Globals, DepStream,
- ForeignImportExt,
- set.to_sorted_list(ForeignImportedModuleNames), !IO),
- io.write_string(DepStream, "\n\n", !IO)
- ),
- list.foldl(WriteForeignImportTarget, ForeignImportTargets, !IO)
- ),
- module_name_to_file_name(Globals, ModuleName, ".int",
- do_not_create_dirs, IntFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".int2",
- do_not_create_dirs, Int2FileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".int3",
- do_not_create_dirs, Int3FileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".opt",
- do_not_create_dirs, OptFileName, !IO),
- module_name_to_file_name(Globals, ModuleName, ".trans_opt",
- do_not_create_dirs, TransOptFileName, !IO),
- module_name_to_file_name(Globals, 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.)
+ ForeignImports =
+ get_all_foreign_import_module_infos(ForeignImportModules),
- 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.lookup_bool_option(Globals, use_subdirs, UseSubdirs),
- (
- UseSubdirs = yes,
- io.nl(DepStream, !IO),
- list.foldl(
- write_subdirs_shorthand_rule(Globals, DepStream, ModuleName),
- [".c", ".$O", ".pic_o", ".java", ".class", ".dll"], !IO)
- ;
- UseSubdirs = no
- ),
+ % Handle dependencies introduced by
+ % `:- pragma foreign_import_module' declarations.
- ( if SourceFileName = default_source_file(ModuleName) then
- true
- else
- % 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.
+ set.filter_map(
+ ( pred(ForeignImportMod::in, ImportModuleName::out)
+ is semidet :-
+ ImportModuleName = 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.
+ ImportModuleName \= unqualified("mercury")
+ ), ForeignImports, ForeignImportedModuleNames),
+ ( if set.is_empty(ForeignImportedModuleNames) then
+ true
+ else
+ (
+ Target = target_csharp,
+ % XXX don't know enough about C# yet
+ ForeignImportTargets = [],
+ ForeignImportExt = ".cs"
+ ;
+ Target = target_java,
+ ForeignImportTargets = [ClassFileName],
+ ForeignImportExt = ".java"
+ ;
+ Target = target_erlang,
+ ForeignImportTargets = [BeamFileName],
+ ForeignImportExt = ".hrl"
+ ;
+ Target = target_c,
+ % NOTE: for C 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"
+ ),
+ 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(Globals, DepStream,
+ ForeignImportExt,
+ set.to_sorted_list(ForeignImportedModuleNames),
+ !IO),
+ io.write_string(DepStream, "\n\n", !IO)
+ ),
+ list.foldl(WriteForeignImportTarget, ForeignImportTargets,
+ !IO)
+ ),
+
+ module_name_to_file_name(Globals, ModuleName, ".int",
+ do_not_create_dirs, IntFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".int2",
+ do_not_create_dirs, Int2FileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".int3",
+ do_not_create_dirs, Int3FileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".opt",
+ do_not_create_dirs, OptFileName, !IO),
+ module_name_to_file_name(Globals, ModuleName, ".trans_opt",
+ do_not_create_dirs, TransOptFileName, !IO),
+ module_name_to_file_name(Globals, 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.
%
- % Any changes here will require corresponding changes to
- % scripts/Mmake.rules. See that file for documentation
- % on these rules.
+ % 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",
- 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",
- JavaDateFileName, " : ", SourceFileName, "\n",
- "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
- "--java-only ", ModuleArg,
- " $(ERR_REDIRECT)\n"
- ], !IO)
- ),
+ 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),
- 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),
+ globals.lookup_bool_option(Globals, use_subdirs, UseSubdirs),
(
- 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)
+ UseSubdirs = yes,
+ io.nl(DepStream, !IO),
+ list.foldl(
+ write_subdirs_shorthand_rule(Globals, DepStream,
+ ModuleName),
+ [".c", ".$O", ".pic_o", ".java", ".class", ".dll"], !IO)
;
- Result4 = ok,
- io.rename_file(TmpDependencyFileName, DependencyFileName,
- Result5, !IO),
+ UseSubdirs = no
+ ),
+
+ ( if SourceFileName = default_source_file(ModuleName) then
+ true
+ else
+ % 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",
+ JavaDateFileName, " : ", SourceFileName, "\n",
+ "\t$(MCG) $(ALL_GRADEFLAGS) $(ALL_MCGFLAGS) ",
+ "--java-only ", ModuleArg,
+ " $(ERR_REDIRECT)\n"
+ ], !IO)
+ ),
+
+ 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),
(
- Result5 = error(Error5),
+ Result4 = error(Error4),
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),
+ io.error_message(Error4, ErrorMsg),
+ string.append_list(["can't remove file `",
+ DependencyFileName, "': ", ErrorMsg], Message),
report_error(Message, !IO)
;
- Result5 = ok,
- maybe_write_string(Verbose, " done.\n", !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)
)
- ;
- Result3 = ok,
- maybe_write_string(Verbose, " done.\n", !IO)
)
).
diff --git a/deep_profiler/conf.m b/deep_profiler/conf.m
index dc42450..11bdd1c 100644
--- a/deep_profiler/conf.m
+++ b/deep_profiler/conf.m
@@ -82,47 +82,54 @@ server_name(ServerName, !IO) :-
:- pred server_name_2(string::out, io::di, io::uo) is det.
server_name_2(ServerName, !IO) :-
- io.make_temp(TmpFile, !IO),
- hostname_cmd(HostnameCmd),
- ServerRedirectCmd =
- string.format("%s > %s", [s(HostnameCmd), s(TmpFile)]),
- io.call_system(ServerRedirectCmd, Res1, !IO),
- (
- Res1 = ok(ResCode),
- ( if ResCode = 0 then
- io.open_input(TmpFile, TmpRes, !IO),
- (
- TmpRes = ok(TmpStream),
- io.read_file_as_string(TmpStream, TmpReadRes, !IO),
+ io.make_temp_res(TmpFileResult, !IO),
+ ( TmpFileResult = ok(TmpFile),
+ hostname_cmd(HostnameCmd),
+ ServerRedirectCmd =
+ string.format("%s > %s", [s(HostnameCmd), s(TmpFile)]),
+ io.call_system(ServerRedirectCmd, Res1, !IO),
+ (
+ Res1 = ok(ResCode),
+ ( if ResCode = 0 then
+ io.open_input(TmpFile, TmpRes, !IO),
(
- TmpReadRes = ok(ServerNameNl),
- ( if
- string.remove_suffix(ServerNameNl, "\n",
- ServerNamePrime)
- then
- ServerName = ServerNamePrime
- else
- unexpected($module, $pred, "malformed server name")
- )
+ TmpRes = ok(TmpStream),
+ io.read_file_as_string(TmpStream, TmpReadRes, !IO),
+ (
+ TmpReadRes = ok(ServerNameNl),
+ ( if
+ string.remove_suffix(ServerNameNl, "\n",
+ ServerNamePrime)
+ then
+ ServerName = ServerNamePrime
+ else
+ unexpected($module, $pred,
+ "malformed server name")
+ )
+ ;
+ TmpReadRes = error(_, _),
+ unexpected($module, $pred,
+ "cannot read server's name")
+ ),
+ io.close_input(TmpStream, !IO)
;
- TmpReadRes = error(_, _),
- unexpected($module, $pred, "cannot read server's name")
+ TmpRes = error(_),
+ unexpected($module, $pred,
+ "cannot open file to find the server's name")
),
- io.close_input(TmpStream, !IO)
- ;
- TmpRes = error(_),
+ io.remove_file(TmpFile, _, !IO)
+ else
unexpected($module, $pred,
- "cannot open file to find the server's name")
- ),
- io.remove_file(TmpFile, _, !IO)
- else
+ "cannot execute cmd to find the server's name")
+ )
+ ;
+ Res1 = error(_),
unexpected($module, $pred,
"cannot execute cmd to find the server's name")
)
;
- Res1 = error(_),
- unexpected($module, $pred,
- "cannot execute cmd to find the server's name")
+ TmpFileResult = error(_),
+ unexpected($module, $pred, "Cannot create temporary file")
).
:- pred maybe_server_port(maybe(string)::out, io::di, io::uo) is det.
diff --git a/library/io.m b/library/io.m
index 41a3f10..a944075 100644
--- a/library/io.m
+++ b/library/io.m
@@ -1319,46 +1319,54 @@
% File handling predicates.
%
- % make_temp(Name, !IO) creates an empty file whose name is different
- % to the name of any existing file. Name is bound to the name of the file.
- % It is the responsibility of the caller to delete the file when it
- % is no longer required.
+ % make_temp(Result, !IO) creates an empty file whose name is different
+ % to the name of any existing file. If successful Result returns the name
+ % of the file. It is the responsibility of the caller to delete the file
+ % when it is no longer required.
%
% The file is placed in the directory returned by get_temp_directory/3.
%
- % Throws an io.error exception if the temporary file could not be created.
- %
% On the Erlang and Java backends, this does not attempt to create the file
% with restrictive permissions (600 on Unix-like systems) and therefore
% should not be used when security is required.
%
+:- pred make_temp_res(io.res(string)::out, io::di, io::uo) is det.
+
+ % Like make_temp_res/3 except it throws an io.error exception if the
+ % temporary file could not be created.
+ %
+:- pragma obsolete(make_temp/3).
:- pred make_temp(string::out, io::di, io::uo) is det.
- % make_temp(Dir, Prefix, Name, !IO) creates an empty file whose
+ % make_temp(Dir, Prefix, Suffix, Result, !IO) creates an empty file whose
% name is different to the name of any existing file. The file will reside
% in the directory specified by Dir and will have a prefix using up to
- % the first 5 characters of Prefix. Name is bound to the name of the
- % file. It is the responsibility of the caller to delete the file when it
- % is no longer required.
- %
- % Throws an io.error exception if the temporary file could not be created.
+ % the first 5 characters of Prefix. If successful, Result returns the name
+ % of the file. It is the responsibility of the caller to delete the file
+ % when it is no longer required.
%
% The C# backend has the following limitations:
% - Dir is ignored.
% - Prefix is ignored.
+ % - Suffix is ignored.
+ %
+ % On the Erlang backend Suffix is ignored.
%
% On the Erlang and Java backends, this does not attempt to create the file
% with restrictive permissions (600 on Unix-like systems) and therefore
% should not be used when security is required.
%
-:- pred make_temp(string::in, string::in, string::out, io::di, io::uo)
- is det.
+:- pred make_temp_res(string::in, string::in, string::in, io.res(string)::out,
+ io::di, io::uo) is det.
- % make_temp_directory(DirName, !IO) creates an empty directory whose name
- % is different from the name of any existing directory.
+ % Same as make_temp_res except it does not take a suffix argument and
+ % throws an io.error exception if the temporary file could not be created.
%
- % Throws an io.error exception if the temporary directory could not be
- % created.
+:- pragma obsolete(make_temp/5).
+:- pred make_temp(string::in, string::in, string::out, io::di, io::uo) is det.
+
+ % make_temp_directory(Result, !IO) creates an empty directory whose name
+ % is different from the name of any existing directory.
%
% On the C# backend this is insecure as the file permissions are not set
% and this call does not test for an existing directory.
@@ -1367,31 +1375,29 @@
%
% This is unimplemented on the Erlang backend.
%
-:- pred make_temp_directory(string::out, io::di, io::uo) is det.
+:- pred make_temp_directory(io.res(string)::out, io::di, io::uo) is det.
- % make_temp_directory(Dir, Prefix, DirName, !IO) creates an empty directory
- % whose name is different from the name of any existing directory. The new
- % directory will reside in the existing directory specified by `Dir' and
- % will have a prefix using up to the first 5 characters of `Prefix'.
- % DirName is bound to the name of the new directory. It is the
- % responsibility of the program to delete the directory when it is no
- % longer needed.
- %
- % Throws an io.error exception if the temporary directory could not be
- % created.
+ % make_temp_directory(Dir, Prefix, Suffix, Result, !IO) creates an empty
+ % directory whose name is different from the name of any existing
+ % directory. The new directory will reside in the existing directory
+ % specified by Dir and will have a prefix using up to the first 5
+ % characters of Prefix and a Suffix. Result returns the name of the
+ % new directory. It is the responsibility of the program to delete the
+ % directory when it is no longer needed.
%
% The C# backend has the following limitations:
% - It does not attempt to create the file with restrictive permissions
% (600 on Unix-like systems) and therefore should not be used when
% security is required.
% - Prefix is ignored.
+ % - Suffix is ignored.
%
% On the Java backend this is insecure as the file permissions are not set.
%
% This is unimplemented on the Erlang backend.
%
-:- pred make_temp_directory(string::in, string::in, string::out,
- io::di, io::uo) is det.
+:- pred make_temp_directory(string::in, string::in, string::in,
+ io.res(string)::out, io::di, io::uo) is det.
% Test if the make_temp_directory predicates are available. This is false
% for the Erlang backends and either C backend without support for
@@ -10399,32 +10405,52 @@ command_line_argument(_, "") :-
%---------------------------------------------------------------------------%
-make_temp(Name, !IO) :-
+make_temp_res(Result, !IO) :-
get_temp_directory(Dir, !IO),
- make_temp(Dir, "mtmp", Name, !IO).
+ make_temp_res(Dir, "mtmp", "", Result, !IO).
-make_temp(Dir, Prefix, Name, !IO) :-
- do_make_temp(Dir, Prefix, char_to_string(dir.directory_separator),
+make_temp(Name, !IO) :-
+ make_temp_res(Result, !IO),
+ (
+ Result = ok(Name)
+ ;
+ Result = error(Error),
+ throw(Error)
+ ).
+
+make_temp_res(Dir, Prefix, Suffix, Result, !IO) :-
+ do_make_temp(Dir, Prefix, Suffix, char_to_string(dir.directory_separator),
Name, Okay, Message, !IO),
(
- Okay = yes
+ Okay = yes,
+ Result = ok(Name)
;
Okay = no,
- throw_io_error(Message)
+ Result = error(make_io_error(Message))
).
-make_temp_directory(DirName, !IO) :-
+make_temp(Dir, Prefix, Name, !IO) :-
+ make_temp_res(Dir, Prefix, "", Result, !IO),
+ (
+ Result = ok(Name)
+ ;
+ Result = error(Error),
+ throw(Error)
+ ).
+
+make_temp_directory(Result, !IO) :-
get_temp_directory(Dir, !IO),
- make_temp_directory(Dir, "mtmp", DirName, !IO).
+ make_temp_directory(Dir, "mtmp", "", Result, !IO).
-make_temp_directory(Dir, Prefix, DirName, !IO) :-
- do_make_temp_directory(Dir, Prefix,
+make_temp_directory(Dir, Prefix, Suffix, Result, !IO) :-
+ do_make_temp_directory(Dir, Prefix, Suffix,
char_to_string(dir.directory_separator), DirName, Okay, Message, !IO),
(
- Okay = yes
+ Okay = yes,
+ Result = ok(DirName)
;
Okay = no,
- throw_io_error(Message)
+ Result = error(make_io_error(Message))
).
%-----------------------------------------------------------------------%
@@ -10440,12 +10466,11 @@ import java.util.Random;
"
public static Random ML_rand = new Random();
- public static String makeTempName(String prefix)
+ public static String makeTempName(String prefix, String suffix)
{
StringBuilder sb = new StringBuilder();
sb.append(prefix);
-
// Make an 8-digit mixed case alpha-numeric code.
for (int i = 0; i < 8; i++) {
char c;
@@ -10460,13 +10485,14 @@ import java.util.Random;
c = (char)c_num;
sb.append(c);
}
+ sb.append(suffix);
return sb.toString();
}
").
:- pred do_make_temp(string::in, string::in, string::in,
- string::out, bool::out, string::out, io::di, io::uo) is det.
+ string::in, string::out, bool::out, string::out, io::di, io::uo) is det.
% XXX The code for io.make_temp assumes POSIX. It uses the functions open(),
% close(), and getpid() and the macros EEXIST, O_WRONLY, O_CREAT, and O_EXCL.
@@ -10491,7 +10517,7 @@ import java.util.Random;
").
:- pragma foreign_proc("C",
- do_make_temp(Dir::in, Prefix::in, Sep::in, FileName::out,
+ do_make_temp(Dir::in, Prefix::in, Suffix::in, Sep::in, FileName::out,
Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io,
does_not_affect_liveness],
@@ -10499,8 +10525,8 @@ import java.util.Random;
#ifdef MR_HAVE_MKSTEMP
int err, fd;
- FileName = MR_make_string(MR_ALLOC_ID, ""%s%s%.5sXXXXXX"",
- Dir, Sep, Prefix);
+ FileName = MR_make_string(MR_ALLOC_ID, ""%s%s%.5sXXXXXX%s"",
+ Dir, Sep, Prefix, Suffix);
fd = mkstemp(FileName);
if (fd == -1) {
ML_maybe_make_err_msg(MR_TRUE, errno,
@@ -10519,18 +10545,18 @@ import java.util.Random;
#else
/*
** Constructs a temporary name by concatenating Dir, `/', the first 5 chars
- ** of Prefix, three hex digits, '.', and 3 more hex digits. The six digit
- ** hex number is generated by starting with the pid of this process.
- ** Uses `open(..., O_CREATE | O_EXCL, ...)' to create the file, checking
- ** that there was no existing file with that name.
+ ** of Prefix, six hex digits, and Suffix. The six digit hex number is
+ ** generated by starting with the pid of this process. Uses
+ ** `open(..., O_CREATE | O_EXCL, ...)' to create the file, checking that
+ ** there was no existing file with that name.
*/
int len, err, fd, num_tries;
char countstr[256];
MR_Word filename_word;
int flags;
- len = strlen(Dir) + 1 + 5 + 3 + 1 + 3 + 1;
- /* Dir + / + Prefix + counter_high + . + counter_low + \\0 */
+ len = strlen(Dir) + 1 + 5 + 6 + strlen(Suffix) + 1;
+ /* Dir + / + Prefix + counter + Suffix + \\0 */
MR_offset_incr_hp_atomic_msg(filename_word, 0,
(len + sizeof(MR_Word)) / sizeof(MR_Word),
MR_ALLOC_ID, ""string.string/0"");
@@ -10544,9 +10570,8 @@ import java.util.Random;
strcpy(FileName, Dir);
strcat(FileName, Sep);
strncat(FileName, Prefix, 5);
- strncat(FileName, countstr, 3);
- strcat(FileName, ""."");
- strncat(FileName, countstr + 3, 3);
+ strncat(FileName, countstr, 6);
+ strcat(FileName, Suffix);
flags = O_WRONLY | O_CREAT | O_EXCL;
do {
#ifdef MR_WIN32
@@ -10577,7 +10602,7 @@ import java.util.Random;
").
:- pragma foreign_proc("C#",
- do_make_temp(_Dir::in, _Prefix::in, _Sep::in, FileName::out,
+ do_make_temp(_Dir::in, _Prefix::in, _Suffix::in, _Sep::in, FileName::out,
Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
"{
@@ -10594,11 +10619,8 @@ import java.util.Random;
}
}").
-% For the Java implementation, io.make_temp/3 is overwritten directly,
-% since Java is capable of locating the default temp directory itself.
-
:- pragma foreign_proc("Java",
- do_make_temp(Dir::in, Prefix::in, _Sep::in, FileName::out,
+ do_make_temp(Dir::in, Prefix::in, Suffix::in, _Sep::in, FileName::out,
Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
may_not_duplicate],
@@ -10612,7 +10634,7 @@ import java.util.Random;
Prefix = Prefix.substring(0, 5);
}
- new_file = new File(new File(Dir), makeTempName(Prefix));
+ new_file = new File(new File(Dir), makeTempName(Prefix, Suffix));
if (new_file.createNewFile()) {
FileName = new_file.getAbsolutePath();
Okay = bool.YES;
@@ -10630,13 +10652,14 @@ import java.util.Random;
").
:- pragma foreign_proc("Erlang",
- do_make_temp(Dir::in, Prefix::in, Sep::in, FileName::out,
+ do_make_temp(Dir::in, Prefix::in, Suffix::in, Sep::in, FileName::out,
Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io,
does_not_affect_liveness],
"
DirStr = binary_to_list(Dir),
PrefixStr = binary_to_list(Prefix),
+ SuffixStr = binary_to_list(Suffix),
SepStr = binary_to_list(Sep),
% Constructs a temporary name by concatenating Dir, Sep, Prefix
@@ -10658,7 +10681,7 @@ import java.util.Random;
Seed = {A1 + Pid, A2, A3},
case
- mercury__io:'ML_do_make_temp_2'(DirStr, PrefixStr, SepStr,
+ mercury__io:'ML_do_make_temp_2'(DirStr, PrefixStr, SuffixStr, SepStr,
MaxTries, Seed)
of
{ok, FileName0} ->
@@ -10673,19 +10696,19 @@ import java.util.Random;
").
:- pragma foreign_decl("Erlang", local, "
- -export(['ML_do_make_temp_2'/5]).
+ -export(['ML_do_make_temp_2'/6]).
").
:- pragma foreign_code("Erlang", "
- 'ML_do_make_temp_2'(_, _, _, 0, _) ->
+ 'ML_do_make_temp_2'(_, _, _, _, 0, _) ->
{error, ""error opening temporary file""};
- 'ML_do_make_temp_2'(Dir, Prefix, Sep, Tries, Seed0) ->
+ 'ML_do_make_temp_2'(Dir, Prefix, Suffix, Sep, Tries, Seed0) ->
{R1, Seed1} = random:uniform_s(16#1000, Seed0),
{R2, Seed} = random:uniform_s(16#1000, Seed1),
- FileName = lists:flatten(io_lib:format(""~s~s~s~3.16.0B.~3.16.0B"",
- [Dir, Sep, Prefix, R1, R2])),
+ FileName = lists:flatten(io_lib:format(""~s~s~s~3.16.0B.~3.16.0B~s"",
+ [Dir, Sep, Prefix, R1, R2, Suffix])),
case filelib:is_file(FileName) of
true ->
- 'ML_do_make_temp_2'(Dir, Prefix, Sep, Tries - 1, Seed);
+ 'ML_do_make_temp_2'(Dir, Prefix, Suffix, Sep, Tries - 1, Seed);
false ->
case file:open(FileName, [write, {encoding, utf8}]) of
{ok, IoDevice} ->
@@ -10696,27 +10719,28 @@ import java.util.Random;
{error, file:format_error(Reason)}
end;
{error, _} ->
- 'ML_do_make_temp_2'(Dir, Prefix, Sep, Tries - 1, Seed)
+ 'ML_do_make_temp_2'(Dir, Prefix, Suffix, Sep,
+ Tries - 1, Seed)
end
end.
").
%-----------------------------------------------------------------------%
-:- pred do_make_temp_directory(string::in, string::in, string::in,
+:- pred do_make_temp_directory(string::in, string::in, string::in, string::in,
string::out, bool::out, string::out, io::di, io::uo) is det.
:- pragma foreign_proc("C",
- do_make_temp_directory(Dir::in, Prefix::in, Sep::in, DirName::out,
- Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
+ do_make_temp_directory(Dir::in, Prefix::in, Suffix::in, Sep::in,
+ DirName::out, Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io,
does_not_affect_liveness],
"
#ifdef MR_HAVE_MKDTEMP
int err;
- DirName = MR_make_string(MR_ALLOC_ID, ""%s%s%.5sXXXXXX"",
- Dir, Sep, Prefix);
+ DirName = MR_make_string(MR_ALLOC_ID, ""%s%s%.5sXXXXXX%s"",
+ Dir, Sep, Prefix, Suffix);
DirName = mkdtemp(DirName);
if (DirName == NULL) {
ML_maybe_make_err_msg(MR_TRUE, errno,
@@ -10737,8 +10761,8 @@ import java.util.Random;
").
:- pragma foreign_proc("C#",
- do_make_temp_directory(Dir::in, _Prefix::in, _Sep::in, DirName::out,
- Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
+ do_make_temp_directory(Dir::in, _Prefix::in, _Suffix::in, _Sep::in,
+ DirName::out, Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe],
"{
try {
@@ -10761,8 +10785,8 @@ import java.util.Random;
}").
:- pragma foreign_proc("Java",
- do_make_temp_directory(Dir::in, Prefix::in, _Sep::in, DirName::out,
- Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
+ do_make_temp_directory(Dir::in, Prefix::in, Suffix::in, _Sep::in,
+ DirName::out, Okay::out, ErrorMessage::out, _IO0::di, _IO::uo),
[will_not_call_mercury, promise_pure, tabled_for_io, thread_safe,
may_not_duplicate],
"
@@ -10774,7 +10798,7 @@ import java.util.Random;
Prefix = Prefix.substring(0, 5);
}
- new_dir = new File(new File(Dir), makeTempName(Prefix));
+ new_dir = new File(new File(Dir), makeTempName(Prefix, Suffix));
if (new_dir.mkdir()) {
DirName = new_dir.getAbsolutePath();
Okay = bool.YES;
--
2.8.0.rc3
More information about the reviews
mailing list