[m-dev.] For review: io.m

Thomas Charles CONWAY conway at cs.mu.oz.au
Tue Jun 3 10:53:02 AEST 1997


ON
> Thomas Charles CONWAY, you wrote:
> > 
> > Can someone please review this small change to io.m?
> 
> > library/io.m:
> > 	add io__tmpnam(Dir, Prefix, Name, IO0, IO) which interfaces to
> > 	tempnam. Fix the implementation of io__tmpnam/3 so that it
> > 	respects the TMPDIR environment variable. (The stdio implementation
> > 	on linux DIDN'T)
> 
> This change is fine, except for one thing: it relies on tempnam(),
> and that is not an ANSI C function.  (tmpnam() is ANSI, tempnam() is not.)
> 
> Hence, before committing this you should add a check for tempnam()
> in configure.in & runtime/conf.h.in, and do something appropriate
> if the system doesn't have tempnam().
> 

Urk! This required C programming. :-( ;-)
I would welcome comments on the generation of tmp file names.

-- 
ZZ:wq!
^X^C
Thomas Conway               				      conway at cs.mu.oz.au
AD DEUM ET VINUM	  			      Every sword has two edges.

configure.in:
	add a check for tempnam

library/io.m:
	add io__tmpnam(Dir, Prefix, Name, IO0, IO) which interfaces to
	tempnam. Fix the implementation of io__tmpnam/3 so that it
	respects the TMPDIR environment variable. (The stdio implementation
	on linux DIDN'T)
	If tempnam doesn't exist then create a new temporary file name from
	the prefix, dir, the pid and a counter.

cvs diff: Diffing .
Index: configure.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/configure.in,v
retrieving revision 1.90
diff -u -r1.90 configure.in
--- configure.in	1997/04/26 07:56:41	1.90
+++ configure.in	1997/06/03 00:13:50
@@ -868,6 +868,27 @@
 fi
 AC_SUBST(MR_LITTLE_ENDIAN)
 #-----------------------------------------------------------------------------#
+AC_MSG_CHECKING(for tempnam)
+AC_CACHE_VAL(mercury_cv_has_tempnam,
+	AC_TRY_RUN([
+	#include <stdio.h>
+	int main() {
+		char	*name;
+
+		name = tempnam("/tmp", "foobie");
+
+		exit(name == NULL);
+	}],
+	[mercury_cv_has_tempnam=yes],
+	[mercury_cv_has_tempnam=no],
+	[mercury_cv_has_tempnam=no])
+)
+AC_MSG_RESULT($mercury_cv_has_tempnam)
+if test "$mercury_cv_has_tempnam" = yes; then
+	AC_DEFINE(IO_HAVE_TEMPNAM)
+fi
+AC_SUBST(IO_HAVE_TEMPNAM)
+#-----------------------------------------------------------------------------#
 #
 # For Irix 5, gcc labels don't work with shared libraries,
 # so if we're using gcc labels, we need to use non-shared libraries,
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
cvs diff: Diffing library
Index: library/io.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/io.m,v
retrieving revision 1.122
diff -u -r1.122 io.m
--- io.m	1997/05/26 23:06:10	1.122
+++ io.m	1997/06/03 00:21:40
@@ -792,13 +792,26 @@
 
 %-----------------------------------------------------------------------------%
 
-% returns a unique temporary filename.
 :- pred io__tmpnam(string, io__state, io__state).
 :- mode io__tmpnam(out, di, uo) is det.
+	% io__tmpnam(Name, IO0, IO) binds `Name' to a temporary
+	% file name which is unique on the filesystem.
+	% It will reside in /tmp if the TMPDIR environment variable
+	% is not set, or in the directory specified by TMPDIR if it
+	% is set.
+
+:- pred io__tmpnam(string, string, string, io__state, io__state).
+:- mode io__tmpnam(in, in, out, di, uo) is det.
+	% io__tmpnam(Dir, Prefix, Name, IO0, IO) binds `Name' to a
+	% temporary file name which is unique. It will reside in the
+	% directory specified by `Dir' and have a prefix using up to the
+	% first 5 characters of `Prefix'.
 
-% deletes a file
 :- pred io__remove_file(string, io__res, io__state, io__state).
 :- mode io__remove_file(in, out, di, uo) is det.
+	% io__remove_file(FileName, Result, IO0, IO) attempts to remove the
+	% file `FileName', binding Result to ok/0 if it succeeds, or
+	% error/1 if it fails.
 
 %-----------------------------------------------------------------------------%
 
@@ -2514,8 +2527,23 @@
 ").
 
 /*---------------------------------------------------------------------------*/
+
+	% We need to do an explicit check of TMPDIR because not all
+	% systems check TMPDIR for us (eg Linux #$%*@&).
+io__tmpnam(Name) -->
+	io__get_environment_var("TMPDIR", Result),
+	(
+		{ Result = yes(Dir) },
+		io__tmpnam(Dir, "mtmp", Name)
+	;
+		{ Result = no },
+		io__tmpnam_2(Name)
+	).
+
+:- pred io__tmpnam_2(string::out, io__state::di, io__state::uo) is det.
+
 %#include <stdio.h>
-:- pragma(c_code, io__tmpnam(FileName::out, IO0::di, IO::uo), "{
+:- pragma(c_code, io__tmpnam_2(FileName::out, IO0::di, IO::uo), "{
 	Word tmp;
 
 	incr_hp_atomic(tmp, (L_tmpnam + sizeof(Word)) / sizeof(Word));
@@ -2526,6 +2554,73 @@
 	}
 	FileName = (char *)tmp;
 	update_io(IO0, IO);
+}").
+
+/*---------------------------------------------------------------------------*/
+
+%#include <stdio.h>
+
+:- pragma c_header_code("
+#ifndef IO_HAVE_TEMPNAM
+	#include <sys/stat.h>
+	#include <unistd.h>
+	extern int	mercury_io_tempnam_counter;
+#endif
+").
+
+:- pragma c_code("
+#ifndef IO_HAVE_TEMPNAM
+	int	mercury_io_tempnam_counter = 0;
+#endif
+").
+
+:- pragma(c_code, io__tmpnam(Dir::in, Prefix::in, FileName::out,
+		IO0::di, IO::uo), "{
+#ifdef	IO_HAVE_TEMPNAM
+	String tmp;
+
+	tmp = (String) tempnam(Dir, Prefix);
+	if (tmp  == NULL) {
+		fprintf(stderr,
+		  ""Mercury runtime: unable to create temporary filename\\n"");
+		exit(1);
+	}
+	incr_saved_hp_atomic((Word *) FileName,
+		(strlen((String) tmp) + sizeof(Word)) / sizeof(Word));
+	strcpy(FileName, tmp);
+	free(tmp);
+	update_io(IO0, IO);
+#else
+	/*
+	** tempnam was unavailable, so construct a temporary name by
+	** concatenating Dir, `/', the first 5 chars of Prefix, and
+	** a three digit number. The three digit number is generated
+	** by starting with the pid of this process.
+	** Stat is used to check that the file does not exist.
+	*/
+	int	len, err;
+	char	countstr[256];
+	struct stat buf;
+
+	len = strlen(Dir) + 5 + 3 + 1; /* Dir + Prefix + counter + \\0 */
+	incr_saved_hp_atomic((Word *)FileName,
+		(len + sizeof(Word)) / sizeof(Word));
+	if (mercury_io_tempnam_counter == 0)
+		mercury_io_tempnam_counter = getpid();
+	sprintf(countstr, ""%0d"", mercury_io_tempnam_counter % 1000);
+	mercury_io_tempnam_counter++;
+	strcpy(FileName, Dir);
+	strcat(FileName, ""/"");
+	strncat(FileName, Prefix, 5);
+	strncat(FileName, countstr, 3);
+	err = stat(FileName, &buf);
+	if (err != -1 && errno != ENOENT) {
+		fprintf(stderr,
+		  ""Mercury runtime: unable to create temporary filename\\n"");
+		exit(1);
+	}
+	update_io(IO0, IO);
+#endif
 }").
 
 /*---------------------------------------------------------------------------*/
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
Index: runtime/conf.h.in
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/conf.h.in,v
retrieving revision 1.16
diff -u -r1.16 conf.h.in
--- conf.h.in	1997/05/30 15:29:03	1.16
+++ conf.h.in	1997/06/03 00:14:05
@@ -158,4 +158,11 @@
 #undef	MR_BIG_ENDIAN
 #undef	MR_LITTLE_ENDIAN
 
+/*
+** The following macro specifies whether the non-ANSI, non-POSIX,
+** but usually available standard library function `tempnam' is
+** available.
+*/
+#undef	IO_HAVE_TEMPNAM
+
 #endif /* CONF_H */
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/diff
cvs diff: Diffing scripts
cvs diff: Diffing tools
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list