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

Thomas Charles CONWAY conway at cs.mu.oz.au
Tue Jun 10 09:18:20 AEST 1997


ON
> Thomas Charles CONWAY, you wrote:
> > 
> > -% 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 different to the name of any existing file.
> > +	% 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'.
> 
> Please change "unique" here too.
> 
> > +#ifdef	IO_HAVE_TEMPNAM
> > +	String tmp;
> > +
> > +	tmp = tempnam(Dir, Prefix);
> > +	if (tmp  == NULL) {
> > +		fatal_error(""unable to create temporary filename"");
> > +	}
> > +	incr_saved_hp_atomic(LVALUE_CAST(Word *,FileName),
> > +		(strlen((String) tmp) + sizeof(Word)) / sizeof(Word));
> 
> The cast to (String) here is unnecessary.  `tmp' is already a String.
> 
> > +	i=0;
> 
> s/i=0/i = 0/
> 
> Also, a more meaningful variable name would be better:
> s/i/num_tries/g
> 
> Otherwise that looks good.

Here is the diff with those issues fixed.

-- 
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.92
diff -u -r1.92 configure.in
--- configure.in	1997/06/06 08:46:34	1.92
+++ configure.in	1997/06/09 22:14:44
@@ -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.123
diff -u -r1.123 io.m
--- io.m	1997/06/04 09:59:29	1.123
+++ io.m	1997/06/09 23:07:16
@@ -792,13 +792,27 @@
 
 %-----------------------------------------------------------------------------%
 
-% 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 different to the name of any existing file.
+	% 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 different to the name of any
+	% existing file. 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,18 +2528,100 @@
 ").
 
 /*---------------------------------------------------------------------------*/
+
+	% 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));
 	if (tmpnam((char *)tmp) == NULL) {
-		fprintf(stderr,
-		  ""Mercury runtime: unable to create temporary filename\\n"");
-		exit(1);
+		fatal_error(""unable to create temporary filename"");
 	}
 	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	ML_io_tempnam_counter;
+	#define	MAX_TEMPNAME_TRIES	5
+#endif
+").
+
+:- pragma c_code("
+#ifndef IO_HAVE_TEMPNAM
+	int	ML_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 = tempnam(Dir, Prefix);
+	if (tmp  == NULL) {
+		fatal_error(""unable to create temporary filename"");
+	}
+	incr_saved_hp_atomic(LVALUE_CAST(Word *,FileName),
+		(strlen(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, num_tries;
+	char	countstr[256];
+	struct stat buf;
+
+	len = strlen(Dir) + 1+ 5 + 3 + 1; /* Dir + / + Prefix + counter + \\0 */
+	incr_saved_hp_atomic(LVALUE_CAST(Word *,FileName),
+		(len + sizeof(Word)) / sizeof(Word));
+	if (ML_io_tempnam_counter == 0)
+		ML_io_tempnam_counter = getpid();
+	num_tries=0;
+	do {
+		sprintf(countstr, ""%0d"", ML_io_tempnam_counter % 1000);
+		ML_io_tempnam_counter++;
+		strcpy(FileName, Dir);
+		strcat(FileName, ""/"");
+		strncat(FileName, Prefix, 5);
+		strncat(FileName, countstr, 3);
+		err = stat(FileName, &buf);
+		num_tries++;
+	} while (err != -1 && errno != ENOENT
+		&& num_tries < MAX_TEMPNAME_TRIES);
+	if (err != -1 && errno != ENOENT) {
+		fatal_error(""unable to create temporary filename"");
+	}
+	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