[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 14:00:52 AEST 2016
On Wed, Apr 20, 2016 at 01:22:42PM +1000, Peter Wang wrote:
> On Wed, 20 Apr 2016 12:44:38 +1000, Paul Bone <paul at bone.id.au> wrote:
> > For review by Peter Wang who suggested this change.
>
> Hi Paul,
>
> Can you resend with diff -w? Some parts are hard to follow.
Okay, I reflowed some things, especially comments, as indentation levels
changed, so they'll still be part of the diff.
>From 6f03058105c31e75fdcb88e010ea50b427f304bd Mon Sep 17 00:00:00 2001
From: Paul Bone <paul at bone.id.au>
Date: Wed, 20 Apr 2016 12:23:23 +1000
Subject: [PATCH] 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 | 60 ++++++++++---
compiler/fact_table.m | 31 +++++--
compiler/make.module_target.m | 32 +++++--
compiler/make.util.m | 16 +++-
compiler/module_cmds.m | 30 +++++--
compiler/prog_event.m | 28 ++++--
compiler/write_deps_file.m | 189 ++++++++++++++++++++++------------------
deep_profiler/conf.m | 13 ++-
library/io.m | 190 +++++++++++++++++++++++------------------
9 files changed, 385 insertions(+), 204 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,7 +1254,9 @@ invoke_mkinit(Globals, InitFileStream, Verbosity,
% mkinit expects unquoted file names.
join_string_list(FileNames, "", "\n", "", TargetFileNames),
- io.make_temp(TmpFile, !IO),
+ io.make_temp_res(TmpFileResult, !IO),
+ (
+ TmpFileResult = ok(TmpFile),
io.open_output(TmpFile, OpenResult, !IO),
(
OpenResult = ok(TmpStream),
@@ -1274,7 +1276,15 @@ invoke_mkinit(Globals, InitFileStream, Verbosity,
MkInitOK = no
)
;
- OpenResult = error(_),
+ OpenResult = error(Error),
+ io.format(io.stderr_stream, "%s: %s\n",
+ [s(TmpFile), s(error_message(Error))], !IO),
+ MkInitOK = no
+ )
+ ;
+ TmpFileResult = error(Error),
+ io.format(io.stderr_stream, "Could not create temporary file: %s\n",
+ [s(error_message(Error))], !IO),
MkInitOK = no
).
@@ -1977,8 +1987,12 @@ 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),
+ 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.
@@ -1990,6 +2004,15 @@ link_exe_or_shared_lib(Globals, ErrorStream, LinkTargetType, ModuleName,
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,
MaybeDeleteTmpArchive = no,
@@ -3043,7 +3066,9 @@ 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.make_temp_res(".", "mtmp", "", TempFileNameResult, !IO),
+ (
+ TempFileNameResult = ok(TempFileName),
io.open_output(TempFileName, OpenResult, !IO),
(
OpenResult = ok(Stream),
@@ -3053,8 +3078,8 @@ create_java_exe_or_lib(Globals, ErrorStream, LinkTargetType, MainModuleName,
Cmd = string.append_list(
[Jar, " cf ", JarFileName, " @", TempFileName]),
- invoke_system_command(Globals, ErrorStream, cmd_verbose_commands, Cmd,
- Succeeded0, !IO),
+ invoke_system_command(Globals, ErrorStream,
+ cmd_verbose_commands, Cmd, Succeeded0, !IO),
io.remove_file(TempFileName, _, !IO),
(
Succeeded0 = yes
@@ -3064,9 +3089,14 @@ create_java_exe_or_lib(Globals, ErrorStream, LinkTargetType, MainModuleName,
)
;
OpenResult = error(Error),
- io.error_message(Error, ErrorMsg),
io.format(ErrorStream, "Error creating `%s': %s\n",
- [s(TempFileName), s(ErrorMsg)], !IO),
+ [s(TempFileName), s(error_message(Error))], !IO),
+ Succeeded0 = no
+ )
+ ;
+ TempFileNameResult = error(Error),
+ io.format(ErrorStream, "Could not create temporary file: %s\n",
+ [s(error_message(Error))], !IO),
Succeeded0 = no
),
( if
@@ -3463,7 +3493,9 @@ 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.make_temp_res(TmpFileResult, !IO),
+ (
+ TmpFileResult = ok(TmpFile),
io.open_output(TmpFile, OpenResult, !IO),
(
OpenResult = ok(TmpStream),
@@ -3504,7 +3536,15 @@ invoke_long_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
Succeeded = no
)
;
- OpenResult = error(_),
+ OpenResult = error(Error),
+ io.format(stderr_stream, "%s: %s\n",
+ [s(TmpFile), s(error_message(Error))], !IO),
+ Succeeded = no
+ )
+ ;
+ 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,16 +309,28 @@ 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),
+ 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),
+ 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),
C_HeaderCode = C_HeaderCode0,
@@ -967,7 +979,9 @@ 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.make_temp_res(SortFileNameResult, !IO),
+ (
+ SortFileNameResult = ok(SortFileName),
io.open_output(SortFileName, Result, !IO),
(
Result = ok(Stream),
@@ -980,6 +994,13 @@ open_sort_files([ProcID | ProcIDs], ProcStreams, !Errors, !IO) :-
string.format("Error opening file `%s' for output: %s.",
[s(SortFileName), s(Message)], Msg),
add_error_report([words(Msg)], !Errors)
+ )
+ ;
+ SortFileNameResult = error(Error),
+ ProcStreams = [],
+ string.format("Could not create temporary file: %s.",
+ [s(error_message(Error))], Msg),
+ add_error_report([words(Msg)], !Errors)
).
% close_sort_files(ProcStreams, ProcFiles, !IO):
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,18 +362,30 @@ 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 :-
+
+ (
+ 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),
+ list.foldl2(make_remove_file(Globals, very_verbose),
+ TouchedFiles, !MakeInfo, !IO),
(
MaybeArgFileName = yes(ArgFileName2),
io.remove_file(ArgFileName2, _, !IO)
@@ -407,6 +419,12 @@ build_target(Globals, CompilationTask, TargetFile, Imports, TouchedTargetFiles,
)
;
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,7 +1074,9 @@ 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.make_temp_res(ErrorFileNameResult, !IO),
+ (
+ ErrorFileNameResult = ok(ErrorFileName),
io.open_output(ErrorFileName, ErrorFileRes, !IO),
(
ErrorFileRes = ok(ErrorOutputStream),
@@ -1084,6 +1086,12 @@ redirect_output(_ModuleName, MaybeErrorStream, !Info, !IO) :-
MaybeErrorStream = no,
with_locked_stdout(!.Info,
write_error_opening_output(ErrorFileName, IOError), !IO)
+ )
+ ;
+ ErrorFileNameResult = error(IOError),
+ MaybeErrorStream = no,
+ 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,7 +575,9 @@ 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),
+ io.make_temp_res(TmpFileResult, !IO),
+ (
+ 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!
@@ -600,7 +602,8 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
)
;
Result = ok(signalled(Signal)),
- report_error_to_stream(ErrorStream, "system command received 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
@@ -616,6 +619,13 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
Result = error(Error),
report_error_to_stream(ErrorStream, io.error_message(Error), !IO),
CommandSucceeded = no
+ )
+ ;
+ TmpFileResult = error(Error),
+ report_error_to_stream(ErrorStream,
+ "Could not create temporary file: " ++ error_message(Error), !IO),
+ TmpFile = "",
+ CommandSucceeded = no
),
( if
@@ -623,7 +633,9 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
not use_dotnet,
MaybeProcessOutput = yes(ProcessOutput)
then
- io.make_temp(ProcessedTmpFile, !IO),
+ io.make_temp_res(ProcessedTmpFileResult, !IO),
+ (
+ ProcessedTmpFileResult = ok(ProcessedTmpFile),
% XXX we should get rid of use_win32
( if use_win32 then
@@ -659,8 +671,9 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
)
;
ProcessOutputResult = ok(signalled(ProcessOutputSignal)),
- % Make sure the current process gets the signal. Some systems
- % (e.g. Linux) ignore SIGINT during a call to system().
+ % 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 "
@@ -672,6 +685,13 @@ invoke_system_command_maybe_filter_output(Globals, ErrorStream, Verbosity,
io.error_message(ProcessOutputError), !IO),
ProcessOutputSucceeded = no
)
+ ;
+ ProcessedTmpFileResult = error(ProcessTmpError),
+ report_error_to_stream(ErrorStream,
+ io.error_message(ProcessTmpError), !IO),
+ ProcessOutputSucceeded = no,
+ ProcessedTmpFile = ""
+ )
else
ProcessOutputSucceeded = yes,
ProcessedTmpFile = TmpFile
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,7 +92,9 @@ 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),
+ 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),
@@ -101,7 +103,8 @@ read_event_set(SpecsFileName, EventSetName, EventSpecMap, ErrorSpecs, !IO) :-
io.read(TermStream, TermReadRes, !IO),
(
TermReadRes = ok(EventSetTerm),
- EventSetTerm = event_set_spec(EventSetName, EventSpecsTerm),
+ EventSetTerm = event_set_spec(EventSetName,
+ EventSpecsTerm),
convert_list_to_spec_map(SpecsFileName, EventSpecsTerm,
map.init, EventSpecMap, [], ErrorSpecs)
;
@@ -130,9 +133,12 @@ read_event_set(SpecsFileName, EventSetName, EventSpecMap, ErrorSpecs, !IO) :-
TermOpenRes = error(TermOpenError),
EventSetName = "",
EventSpecMap = map.init,
- Pieces = [words(io.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)])]),
+ 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]
)
else
@@ -143,7 +149,17 @@ read_event_set(SpecsFileName, EventSetName, EventSpecMap, ErrorSpecs, !IO) :-
[error_msg(no, do_not_treat_as_first, 0, [always(Pieces)])]),
ErrorSpecs = [ErrorSpec]
),
- io.remove_file(TermFileName, _RemoveRes, !IO).
+ io.remove_file(TermFileName, _RemoveRes, !IO)
+ ;
+ TermFileNameResult= error(TermFileNameError),
+ EventSetName = "",
+ EventSpecMap = map.init,
+ 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]
+ ).
:- 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,8 +159,14 @@ 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),
+ io.make_temp_res(dir.dirname(DependencyFileName), "tmp_d",
+ "", TmpDependencyFileNameRes, !IO),
+ (
+ TmpDependencyFileNameRes = error(Error),
+ Message = "Could not create temporary file: " ++ error_message(Error),
+ report_error(Message, !IO)
+ ;
+ TmpDependencyFileNameRes = ok(TmpDependencyFileName),
maybe_write_string(Verbose, "% Writing auto-dependency file `", !IO),
maybe_write_string(Verbose, DependencyFileName, !IO),
maybe_write_string(Verbose, "'...", !IO),
@@ -244,8 +250,9 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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.
+ % 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",
@@ -292,8 +299,9 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
),
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.
+ % 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),
@@ -383,7 +391,8 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
else
bool.not(UseOptFiles, BuildOptFiles),
get_opt_deps(Globals, BuildOptFiles, IntermodDirs, ".opt",
- [ModuleName | set.to_sorted_list(LongDeps)], OptDeps, !IO),
+ [ModuleName | set.to_sorted_list(LongDeps)],
+ OptDeps, !IO),
OptInt0Deps = set.union_list(
list.map(get_ancestors_set, OptDeps)),
write_dependencies_list(Globals, DepStream, ".opt",
@@ -401,10 +410,10 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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.
+ % 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",
@@ -416,14 +425,15 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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.
+ % 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),
@@ -453,18 +463,18 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
"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.
+ % 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.
+ % 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),
@@ -473,22 +483,26 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
io.write_strings(DepStream, [
"\n\n", DateFileName, " ", Date0FileName
], !IO),
- write_dependencies_set(Globals, DepStream, ".date", ParentDeps, !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, ".int0", ParentDeps,
+ !IO),
write_dependencies_set(Globals, DepStream, ".int3", LongDeps, !IO),
- write_dependencies_set(Globals, DepStream, ".int3", ShortDeps, !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),
+ 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.
+ % 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),
(
@@ -526,11 +540,11 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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
+ % 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(
@@ -574,12 +588,13 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
% `:- pragma foreign_import_module' declarations.
set.filter_map(
- ( pred(ForeignImportMod::in, ImportModuleName::out) is semidet :-
+ ( 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.
+ % 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
@@ -600,24 +615,27 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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.
+ % 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 :-
+ ( 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),
+ set.to_sorted_list(ForeignImportedModuleNames),
+ !IO),
io.write_string(DepStream, "\n\n", !IO)
),
- list.foldl(WriteForeignImportTarget, ForeignImportTargets, !IO)
+ list.foldl(WriteForeignImportTarget, ForeignImportTargets,
+ !IO)
),
module_name_to_file_name(Globals, ModuleName, ".int",
@@ -633,21 +651,21 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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.
+ % 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.)
+ % 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",
@@ -670,7 +688,8 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
UseSubdirs = yes,
io.nl(DepStream, !IO),
list.foldl(
- write_subdirs_shorthand_rule(Globals, DepStream, ModuleName),
+ write_subdirs_shorthand_rule(Globals, DepStream,
+ ModuleName),
[".c", ".$O", ".pic_o", ".java", ".class", ".dll"], !IO)
;
UseSubdirs = no
@@ -679,20 +698,21 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
( 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 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.
+ % 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.
+ % scripts/Mmake.rules. See that file for documentation on
+ % these rules.
io.write_strings(DepStream, [
"\n",
@@ -723,8 +743,8 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
),
io.close_output(DepStream, !IO),
- io.rename_file(TmpDependencyFileName, DependencyFileName, Result3,
- !IO),
+ io.rename_file(TmpDependencyFileName, DependencyFileName,
+ Result3, !IO),
(
Result3 = error(_),
% On some systems, we need to remove the existing file
@@ -735,8 +755,8 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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),
+ string.append_list(["can't remove file `",
+ DependencyFileName, "': ", ErrorMsg], Message),
report_error(Message, !IO)
;
Result4 = ok,
@@ -748,8 +768,8 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
maybe_flush_output(Verbose, !IO),
io.error_message(Error5, ErrorMsg),
string.append_list(["can't rename file `",
- TmpDependencyFileName, "' as `", DependencyFileName,
- "': ", ErrorMsg], Message),
+ TmpDependencyFileName, "' as `",
+ DependencyFileName, "': ", ErrorMsg], Message),
report_error(Message, !IO)
;
Result5 = ok,
@@ -760,6 +780,7 @@ write_dependency_file(Globals, ModuleAndImports, AllDeps,
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,7 +82,8 @@ 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),
+ io.make_temp_res(TmpFileResult, !IO),
+ ( TmpFileResult = ok(TmpFile),
hostname_cmd(HostnameCmd),
ServerRedirectCmd =
string.format("%s > %s", [s(HostnameCmd), s(TmpFile)]),
@@ -102,11 +103,13 @@ server_name_2(ServerName, !IO) :-
then
ServerName = ServerNamePrime
else
- unexpected($module, $pred, "malformed server name")
+ unexpected($module, $pred,
+ "malformed server name")
)
;
TmpReadRes = error(_, _),
- unexpected($module, $pred, "cannot read server's name")
+ unexpected($module, $pred,
+ "cannot read server's name")
),
io.close_input(TmpStream, !IO)
;
@@ -123,6 +126,10 @@ server_name_2(ServerName, !IO) :-
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