[m-rev.] for review: make the deep profiler work again

Zoltan Somogyi zs at cs.mu.OZ.AU
Mon Nov 18 15:14:35 AEDT 2002


On 17-Nov-2002, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> POSIX guarantees that those will be macros, so a configure test isn't
> needed -- you can just use
> 
> 	#ifdef O_CREAT
> 
> rather than
> 
> 	#ifdef MR_HAVE_O_CREAT

I decided to make centralize all feature tests in configure.in.

Here is an interdiff, containing both the changes I made in response to review
comments and the changes Fergus and I made together to update the installation
mechanisms of the deep profiler.

Zoltan.

diff -u Mmakefile Mmakefile
--- Mmakefile	12 Nov 2002 14:43:13 -0000
+++ Mmakefile	14 Nov 2002 07:25:53 -0000
@@ -349,6 +349,8 @@
 
 #-----------------------------------------------------------------------------#
 
+# The code of the install rule is duplicated in bindist/bindist.Makefile.in.
+
 .PHONY: install
 install: install_main install_grades
 	@echo
@@ -358,9 +360,11 @@
 	@echo "-- $(INSTALL_MAN_DIR) to your MANPATH,"
 	@echo "-- and $(INSTALL_INFO_DIR) to your INFOPATH,"
 	@if test $(ENABLE_DEEP_PROFILER) != yes || \
-		cmp -s scripts/mdprof.in $(INSTALL_CGI_DIR)/mdprof; \
+		cmp -s deep_profiler/mdprof_cgi \
+			$(INSTALL_CGI_DIR)/mdprof_cgi; \
 	then true ; else \
-		echo "-- to copy scripts/mdprof to $(INSTALL_CGI_DIR),"; \
+		echo "-- to copy deep_profiler/mdprof_cgi" \
+			"to $(INSTALL_CGI_DIR),"; \
 	fi
 	@echo "-- and to add the following lines to the \`.emacs' file"
 	@echo "-- in your home directory:"
@@ -563,6 +567,7 @@
 .PHONY: uninstall
 uninstall:
 	+cd scripts; $(SUBDIR_MMAKE) uninstall
+	+cd deep_profiler; $(SUBDIR_MMAKE) uninstall
 	+cd util; $(SUBDIR_MMAKE) uninstall
 	+cd doc; $(SUBDIR_MMAKE) uninstall
 	-rm -r $(INSTALL_LIBDIR)
diff -u configure.in configure.in
--- configure.in	12 Nov 2002 02:58:51 -0000
+++ configure.in	18 Nov 2002 02:35:58 -0000
@@ -1443,6 +1443,38 @@
 fi
 AC_SUBST(MR_LITTLE_ENDIAN)
 #-----------------------------------------------------------------------------#
+AC_MSG_CHECKING(whether we can use files as locks)
+AC_CACHE_VAL(mercury_cv_have_ocreat_oexcl,
+	AC_TRY_COMPILE([
+		#ifdef MR_HAVE_SYS_TYPES_H
+		#include <sys/types.h>
+		#endif
+		#ifdef MR_HAVE_SYS_STAT_H
+		#include <sys/stat.h>
+		#endif
+		#ifdef MR_HAVE_FCNTL_H
+		#include <fcntl.h>
+		#endif
+	],
+	[
+	#if defined(O_CREAT) && defined(O_EXCL)
+
+	#else
+	/* 
+	** As these macros are not defined the compilation must fail.
+	** Unmatched brackets should do that for us.
+	*/
+		}
+	#endif
+	], 
+	[mercury_cv_have_ocreat_oexcl=yes],
+	[mercury_cv_have_ocreat_oexcl=no])
+)
+AC_MSG_RESULT($mercury_cv_have_ocreat_oexcl)
+if test "$mercury_cv_have_ocreat_oexcl" = yes; then
+	AC_DEFINE(MR_HAVE_OCREAT_OEXCL)
+fi
+#-----------------------------------------------------------------------------#
 AC_MSG_CHECKING(return values of system)
 AC_CACHE_VAL(mercury_cv_normal_system_retval,
 	AC_TRY_RUN([
@@ -1838,18 +1870,21 @@
 enable_deep_profiler="$enableval",enable_deep_profiler=default)
 AC_MSG_CHECKING(whether to enable the deep profiler)
 
-    # This test may need to be made more specific at a later date.
-    # Currently it only distinguishes between systems which have
-    # unistd.h or not, but at a later date we may also need to test for
-    # other posix features.
-if test "$MR_HAVE_UNISTD_H" = 1 && \
+# We test for all the features needed by the deep profiler.
+if test "$MR_HAVE_SYS_TYPES_H" = 1 && \
+	test "$MR_HAVE_SYS_STAT_H" = 1 && \
+	test "$MR_HAVE_FCNTL_H" = 1 && \
+	test "$MR_HAVE_UNISTD_H" = 1 && \
 	test "$MR_HAVE_DIRENT_H" = 1 && \
 	test "$ac_cv_func_getpid" = yes && \
+	test "$ac_cv_func_fork" = yes && \
 	test "$ac_cv_func_opendir" = yes && \
 	test "$ac_cv_func_readdir" = yes && \
-	test "$ac_cv_func_closedir" = yes
+	test "$ac_cv_func_closedir" = yes && \
+	test "$mercury_cv_have_ocreat_oexcl" = yes
 then
     mercury_cv_can_enable_deep_profiler=yes
+    AC_DEFINE(MR_DEEP_PROFILER_ENABLED)
 else
     mercury_cv_can_enable_deep_profiler=no
 fi
diff -u deep_profiler/DESIGN deep_profiler/DESIGN
--- deep_profiler/DESIGN	11 Nov 2002 05:39:50 -0000
+++ deep_profiler/DESIGN	15 Nov 2002 05:30:59 -0000
@@ -110,6 +110,22 @@
 		fi
 	fi
 
+The pseudocode of the timeout handler:
+
+	try to get mutual exclusion (i.e. create mutex file)
+	if we got mutual exclusion
+		check whether any want files exist
+		if some do
+			abort the timeout
+		else
+			clean up, deleting the mutex file last
+			exit
+		fi
+	else
+		some client has the lock, they need a server,
+			so abort the timeout
+	fi
+
 The initial design of the deep profiler had two separate programs. The old
 mdprof_cgi was strictly a client: it *always* sent the query to a process
 running the other program, mdprof_server. The problem with this approach
diff -u deep_profiler/Mercury.options deep_profiler/Mercury.options
--- deep_profiler/Mercury.options	13 Nov 2002 22:52:54 -0000
+++ deep_profiler/Mercury.options	15 Nov 2002 05:31:30 -0000
@@ -19,11 +19,13 @@
 # We therefore turn off this optimization in all modules that may deal
 # with arrays. This should not cause any performance problem, since there
 # are no known duplicate calls in any performance critical predicates.
+#
+# XXX These flags should be deleted when the problem is fixed.
 
 MCFLAGS-array_util =	--no-optimize-duplicate-calls
 MCFLAGS-callgraph = 	--no-optimize-duplicate-calls
 MCFLAGS-canonical =	--no-optimize-duplicate-calls
-MCFLAGS-clique = 	--no-optimize-duplicate-calls
+MCFLAGS-cliques = 	--no-optimize-duplicate-calls
 MCFLAGS-dense_bitset = 	--no-optimize-duplicate-calls
 MCFLAGS-exclude = 	--no-optimize-duplicate-calls
 MCFLAGS-html_format = 	--no-optimize-duplicate-calls
diff -u deep_profiler/Mmakefile deep_profiler/Mmakefile
--- deep_profiler/Mmakefile	12 Nov 2002 13:03:05 -0000
+++ deep_profiler/Mmakefile	14 Nov 2002 07:37:02 -0000
@@ -20,7 +20,7 @@
 	MAIN_TARGET=all
 	MERCURY_MAIN_MODULES=mdprof_cgi mdprof_test
 	DEPEND=mdprof_cgi.depend mdprof_test.depend
-	INSTALL=install_deep
+	INSTALL=install_cgi_progs
 else
 	MAIN_TARGET=nothing
 	MERCURY_MAIN_MODULES=
@@ -113,9 +113,34 @@
 # We don't install mdprof_test, since it is not for users.
 
-.PHONY: install_deep
-install_deep: mdprof_cgi
-	-[ -d $(INSTALL_MERC_BIN_DIR) ] || mkdir -p $(INSTALL_MERC_BIN_DIR)
-	cp `vpath_find mdprof_cgi$(EXT_FOR_EXE)` \
-		$(INSTALL_MERC_BIN_DIR)/mdprof_cgi
+# The code of the install_cgi_progs target is duplicated in
+# bindist/bindist.Makefile.in, though the two rules refer to mdprof_cgi
+# by different paths.
+
+.PHONY: install_cgi_progs
+install_cgi_progs: mdprof_cgi
+	# $(INSTALL_CGI_DIR) is likely to be writeable only by root or
+	# the www system administrator, which is why we don't consider a
+	# failure of this action to be an error. If the command fails,
+	# the install action in ../Mmakefile will remind the user to do
+	# the copy later.
+	#
+	# The mv before the cp is there in case the executable is being
+	# executed when we do the install. The mv is of course expected to
+	# fail during a first-time installation.
+	-if test $(ENABLE_DEEP_PROFILER) = yes ; then \
+		mv $(INSTALL_CGI_DIR)/mdprof_cgi \
+			$(INSTALL_CGI_DIR)/mdprof_cgi.was ; \
+		cp mdprof_cgi $(INSTALL_CGI_DIR) ; \
+	fi
+
+uninstall:
+	# We try to uninstall mdprof_cgi, but failure to do so is not an
+	# error for two reasons: because we may simply lack permission to
+	# update the directory, and because the deep profiler installation
+	# may not have been enabled in the first place. (Looking at the current
+	# value of $(ENABLE_DEEP_PROFILER) to check for the latter wouldn't
+	# necessarily do any good, since its setting may have changed since
+	# the original install.)
+	-rm $(INSTALL_CGI_DIR)/mdprof_cgi
 
 #-----------------------------------------------------------------------------#
diff -u deep_profiler/conf.m deep_profiler/conf.m
--- deep_profiler/conf.m	13 Nov 2002 10:51:40 -0000
+++ deep_profiler/conf.m	16 Nov 2002 12:31:41 -0000
@@ -46,28 +46,28 @@
 	( { Res1 = ok(0) } ->
 		io__open_input(TmpFile, TmpRes),
 		( { TmpRes = ok(TmpStream) } ->
-			io__read_file(TmpStream, TmpReadRes),
-			{ TmpReadRes = ok(ServerNameChars0) ->
+			io__read_file_as_string(TmpStream, TmpReadRes),
+			{
+				TmpReadRes = ok(ServerNameNl),
 				(
-					list__remove_suffix(ServerNameChars0,
-						['\n'], ServerNameChars)
+					string__remove_suffix(ServerNameNl,
+						"\n", ServerNamePrime)
 				->
-					string__from_char_list(
-						ServerNameChars, ServerName)
+					ServerName = ServerNamePrime
 				;
 					error("malformed server name")
 				)
 			;
+				TmpReadRes = error(_, _),
 				error("cannot read server's name")
 			},
 			io__close_input(TmpStream)
 		;
-			{ error("cannot open file to out the server's name") }
+			{ error("cannot open file to find the server's name") }
 		),
-		{ RmTmpCmd = string__format("rm %s", [s(TmpFile)]) },
-		io__call_system(RmTmpCmd, _)
+		io__remove_file(TmpFile, _)
 	;
-		{ error("cannot execute cmd to find out the server's name") }
+		{ error("cannot execute cmd to find the server's name") }
 	).
 
 :- pred mkfifo_cmd(string::out) is det.
@@ -92,7 +92,7 @@
 
 :- pragma foreign_decl("C",
 "
-#ifdef	MR_HAVE_UNISTD_H
+#ifdef	MR_DEEP_PROFILER_ENABLED
 #include	<sys/types.h>
 #include	<unistd.h>
 #endif
@@ -103,14 +103,8 @@
 	[will_not_call_mercury, promise_pure],
 "
-#if	defined(MR_HAVE_UNISTD_H) && defined(MR_HAVE_GETPID)
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	Pid = getpid();
 #else
-	/*
-	** If MR_HAVE_GETPID is not defined, the deep profiler is not enabled
-	** anyway, so what the code here does doesn't matter. We still want to
-	** make it compile cleanly, though.
-	*/
-
-	Pid = 0;
+	MR_fatal_error(""the deep profiler is not supported"");
 #endif
 ").
diff -u deep_profiler/interface.m deep_profiler/interface.m
--- deep_profiler/interface.m	13 Nov 2002 17:11:16 -0000
+++ deep_profiler/interface.m	14 Nov 2002 06:59:44 -0000
@@ -474,7 +474,7 @@
 machine_datafile_cmd_pref_to_url(Machine, DataFileName, Cmd, Preferences) =
 	"http://" ++
 	Machine ++
-	"/cgi-bin/mdprof?" ++
+	"/cgi-bin/mdprof_cgi?" ++
 	cmd_to_string(Cmd) ++
 	string__char_to_string(query_separator_char) ++
 	preferences_to_string(Preferences) ++
diff -u deep_profiler/mdprof_cgi.m deep_profiler/mdprof_cgi.m
--- deep_profiler/mdprof_cgi.m	13 Nov 2002 22:06:59 -0000
+++ deep_profiler/mdprof_cgi.m	18 Nov 2002 02:54:56 -0000
@@ -24,7 +24,7 @@
 :- import_module bool, char, string, int, array, list, set.
 :- import_module require, std_util, getopt.
 
-:- import_module int, string, list, array, map, exception, require.
+:- import_module int, string, list, array, map, exception, require, library.
 
 % The web server should always set QUERY_STRING. It may also pass its contents
 % as arguments, but if any characters specials to the shell occur in the query,
@@ -69,7 +69,7 @@
 :- pred process_command_line(io__state::di, io__state::uo) is cc_multi.
 
 process_command_line -->
-	io__progname_base("mdprof_cgi", ProgName),
+	io__progname_base(mdprof_cgi_progname, ProgName),
 	io__command_line_arguments(Args0),
 	% io__write_string("Args0: "),
 	% io__write_list(Args0, " ", write_bracketed_string),
@@ -78,7 +78,25 @@
 		Args0, Args, MaybeOptions) },
 	(
 		{ MaybeOptions = ok(Options) },
-		process_args(Args, Options)
+		{ lookup_bool_option(Options, help, Help) },
+		{ lookup_bool_option(Options, version, Version) },
+	(
+			{ Help = yes },
+			write_help_message(ProgName)
+		;
+			{ Help = no }
+		),
+		(
+			{ Version = yes },
+			write_version_message(ProgName)
+		;
+			{ Version = no }
+		),
+		( { Help = no, Version = no } ->
+			process_args(ProgName, Args, Options)
+		;
+			[]
+		)
 	;
 		{ MaybeOptions = error(Msg) },
 		io__set_exit_status(1),
@@ -86,10 +104,37 @@
 			[s(ProgName), s(Msg)])
 	).
 
-:- pred process_args(list(string)::in, option_table::in,
+:- func mdprof_cgi_progname = string.
+
+mdprof_cgi_progname = "mdprof_cgi".
+
+:- pred write_version_message(string::in, io__state::di, io__state::uo) is det.
+
+write_version_message(ProgName) -->
+	{ library__version(Version) },
+	io__write_string(ProgName),
+	io__write_string(": Mercury deep profiler"),
+	io__nl,
+	io__write_string(Version),
+	io__nl.
+
+:- pred write_help_message(string::in, io__state::di, io__state::uo) is det.
+
+write_help_message(ProgName) -->
+	% The options are deliberately not documented; they change
+	% quite rapidly, based on the debugging needs of the moment.
+	% The optional filename argument is also for implementors only.
+	io__format("Usage: %s\n", [s(ProgName)]),
+	io__format("This program doesn't expect any arguments;\n", []),
+	io__format("instead it decides what to do based on the\n", []),
+	io__format("QUERY_STRING environment variable.\n", []).
+
+%-----------------------------------------------------------------------------%
+
+:- pred process_args(string::in, list(string)::in, option_table::in,
 	io__state::di, io__state::uo) is cc_multi.
 
-process_args(Args, Options) -->
+process_args(ProgName, Args, Options) -->
 	( { Args = [FileName] } ->
 		% Although this mode of usage is not intended for production
 		% use, allowing the filename and a limited range of commands
@@ -98,19 +143,20 @@
 		process_query(default_cmd(Options), no, FileName, Options)
 	;
 		io__set_exit_status(1),
-		% The options are deliberately not documented; they change
-		% quite rapidly, based on the debugging needs of the moment.
-		io__write_string("Usage: mdprof_cgi [filename]\n"),
-		io__write_list(Args, " ", write_bracketed_string)
+		write_help_message(ProgName)
+		% io__write_list(Args, " ", write_bracketed_string)
 	).
 
-:- pred write_bracketed_string(string::in, io__state::di, io__state::uo)
-	is det.
-
-write_bracketed_string(S) -->
-	io__write_string("<"),
-	io__write_string(S),
-	io__write_string(">").
+% This predicate is for debugging the command line given to mdprof_cgi by the
+% web server, should that be necessary
+%
+% :- pred write_bracketed_string(string::in, io__state::di, io__state::uo)
+% 	is det.
+% 
+% write_bracketed_string(S) -->
+% 	io__write_string("<"),
+% 	io__write_string(S),
+% 	io__write_string(">").
 
 :- pred write_html_header(io__state::di, io__state::uo) is det.
 
@@ -194,8 +240,7 @@
 		% Leave the response file to be examined.
 	;
 		{ Debug = no },
-		{ RmCmd = string__format("rm %s", [s(ResponseFileName)]) },
-		io__call_system(RmCmd, _)
+		io__remove_file(ResponseFileName, _)
 	).
 
 % Handle the given query and then become the new server. Delete the mutex
@@ -223,7 +268,7 @@
 			{ StartupStreamRes = error(_) },
 			{ error("cannot create startup file") }
 		)
-	;
+		;
 		{ RecordStartup = no },
 		{ MaybeStartupStream = no }
 		),
@@ -240,7 +285,7 @@
 			% be flushed twice, once by the parent process and
 			% once by the child process.
 			io__flush_output(StartupStream1)
-		;
+	;
 			{ MaybeStartupStream = no }
 		),
 		(
@@ -308,7 +353,17 @@
 			% want to duplicate them. We also don't want to delete
 			% the pipes we need or the startup file.
 			unregister_file_for_cleanup(MutexFile),
-			unregister_file_for_cleanup(WantFile)
+			unregister_file_for_cleanup(WantFile),
+			io__stdin_stream(StdIn),
+			io__close_input(StdIn),
+			io__stdout_stream(StdOut),
+			io__close_output(StdOut),
+			io__stderr_stream(StdErr),
+			io__close_output(StdErr),
+			io__current_binary_input_stream(BinaryStdIn),
+			io__close_binary_input(BinaryStdIn),
+			io__current_binary_output_stream(BinaryStdOut),
+			io__close_binary_output(BinaryStdOut)
 		;
 			{ ChildHasParent = child_has_no_parent },
 			% We don't actually have a parent process, so we need
@@ -460,18 +515,13 @@
 %-----------------------------------------------------------------------------%
 
 :- pragma foreign_decl("C", "
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-").
-
-:- pragma foreign_decl("C", "
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#ifdef	MR_DEEP_PROFILER_ENABLED
+  #include <sys/types.h>
+  #include <sys/stat.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <unistd.h>
+#endif
 ").
 
 :- pred check_for_existing_fifos(string::in, string::in, int::out,
@@ -482,6 +532,7 @@
 		S0::di, S::uo),
 	[will_not_call_mercury, promise_pure, tabled_for_io],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	struct stat	statbuf;
 	int		status;
 
@@ -496,6 +547,9 @@
 	}
 
 	S = S0;
+#else
+	MR_fatal_error(""deep profiling not enabled"");
+#endif
 ").
 
 :- type child_has_parent
@@ -537,6 +591,7 @@
 	raw_detach_process(ResCode::out, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "{
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	pid_t	status;
 
 	fflush(stdout);
@@ -548,15 +603,22 @@
 		ResCode = 1;
 	} else {
 #ifdef	MR_HAVE_SETPGID
-		/* detach the server process from the parent's process group */
+		/*
+		** Try to detach the server process from the parent's process
+		** group, in case it uses the number of processes in the
+		** process group to decide when the cgi `script' is done
+		*/
 		setpgid(0, 0);
 #else
-		/* hope that web server doesn't depend on the process group */
+		/* Hope that web server doesn't depend on the process group. */
 #endif
 		ResCode = 0;
 	}
 
 	S = S0;
+#else
+	MR_fatal_error(""deep profiling not enabled"");
+#endif
 }").
 
 %-----------------------------------------------------------------------------%
@@ -566,6 +628,7 @@
 	;	clique
 	;	debug
 	;	detach_process
+	;	help
 	;	modules
 	;	proc
 	;	quit
@@ -574,6 +637,7 @@
 	;	record_loop
 	;	server_process
 	;	timeout
+	;	version
 	;	write_query_string.
 
 :- type options ---> options.
@@ -598,6 +662,7 @@
 long("clique",			clique).
 long("debug",			debug).
 long("detach-process",		detach_process).
+long("help",			help).
 long("modules",			modules).
 long("proc",			proc).
 long("quit",			quit).
@@ -606,6 +671,7 @@
 long("record-loop",		record_loop).
 long("server-process",		server_process).
 long("timeout",			timeout).
+long("version",			version).
 long("write-query-string",	write_query_string).
 
 :- pred defaults(option::out, option_data::out) is nondet.
@@ -620,6 +686,7 @@
 defaults0(clique,		int(0)).
 defaults0(debug,		bool(no)).
 defaults0(detach_process,	bool(yes)).
+defaults0(help,			bool(no)).
 defaults0(modules,		bool(no)).
 defaults0(proc,			int(0)).
 defaults0(quit,			bool(no)).
@@ -628,6 +695,7 @@
 defaults0(record_startup,	bool(yes)).
 defaults0(server_process,	bool(yes)).
 defaults0(timeout,		int(30)).
+defaults0(version,		bool(no)).
 defaults0(write_query_string,	bool(yes)).
 
 :- func default_cmd(option_table) = cmd.
diff -u deep_profiler/mdprof_test.m deep_profiler/mdprof_test.m
--- deep_profiler/mdprof_test.m	12 Nov 2002 13:00:30 -0000
+++ deep_profiler/mdprof_test.m	16 Nov 2002 15:10:15 -0000
@@ -22,34 +22,33 @@
 :- import_module bool, char, string, int, array, list, set.
 :- import_module require, std_util, getopt.
 
-:- import_module int, string, list, array, exception, require.
+:- import_module int, string, list, array, exception, require, library.
 
 main -->
-	io__progname_base("mdprof_tool", ProgName),
+	io__progname_base("mdprof_test", ProgName),
 	io__command_line_arguments(Args0),
 	{ getopt__process_options(option_ops(short, long, defaults),
 		Args0, Args, MaybeOptions) },
 	(
 		{ MaybeOptions = ok(Options) },
-		( { Args = [FileName] } ->
-			{ lookup_bool_option(Options, canonical_clique,
-				Canonical) },
-			server_name(Machine),
-			read_and_startup(Machine, [FileName], Canonical, no,
-				Res),
-			(
-				{ Res = ok(Deep) },
-				main2(Options, Deep)
-			;
-				{ Res = error(Error) },
-				io__set_exit_status(1),
-				io__format("%s: error reading data file: %s\n",
-					[s(ProgName), s(Error)])
-			)
+		{ lookup_bool_option(Options, help, Help) },
+		{ lookup_bool_option(Options, version, Version) },
+		(
+			{ Help = yes },
+			write_help_message(ProgName)
 		;
-			io__set_exit_status(1),
-			io__format("Usage: %s [options*] filename\n",
-				[s(ProgName)])
+			{ Help = no }
+		),
+		(
+			{ Version = yes },
+			write_version_message(ProgName)
+		;
+			{ Version = no }
+		),
+		( { Help = no, Version = no } ->
+			main2(ProgName, Args, Options)
+		;
+			[]
 		)
 	;
 		{ MaybeOptions = error(Msg) },
@@ -58,19 +57,62 @@
 			[s(ProgName), s(Msg)])
 	).
 
-:- pred main2(option_table::in, deep::in, io__state::di, io__state::uo)
-	is cc_multi.
+:- pred main2(string::in, list(string)::in, option_table::in,
+	io__state::di, io__state::uo) is cc_multi.
 
-main2(Options, Deep) -->
-	{ lookup_bool_option(Options, test, Test) },
-	(
-		{ Test = no }
+main2(ProgName, Args, Options) -->
+	( { Args = [FileName] } ->
+		{ lookup_bool_option(Options, canonical_clique, Canonical) },
+		server_name(Machine),
+		read_and_startup(Machine, [FileName], Canonical, no, Res),
+		(
+			{ Res = ok(Deep) },
+			{ lookup_bool_option(Options, test, Test) },
+			(
+				{ Test = no }
+			;
+				{ Test = yes },
+				{ lookup_string_option(Options, test_dir,
+					TestDir) },
+				test_server(TestDir, default_preferences, Deep)
+			)
+		;
+			{ Res = error(Error) },
+			io__set_exit_status(1),
+			io__format("%s: error reading data file: %s\n",
+				[s(ProgName), s(Error)])
+		)
 	;
-		{ Test = yes },
-		{ lookup_string_option(Options, test_dir, TestDir) },
-		test_server(TestDir, default_preferences, Deep)
+		io__set_exit_status(1),
+		write_help_message(ProgName)
 	).
 
+:- pred write_version_message(string::in, io__state::di, io__state::uo) is det.
+
+write_version_message(ProgName) -->
+	{ library__version(Version) },
+	io__write_string(ProgName),
+	io__write_string(": Mercury deep profiler"),
+	io__nl,
+	io__write_string(Version),
+	io__nl.
+
+:- pred write_help_message(string::in, io__state::di, io__state::uo) is det.
+
+write_help_message(ProgName) -->
+	io__format("Usage: %s [<options>] <filename>\n", [s(ProgName)]),
+	io__format("<filename> must name a deep profiling data file.\n", []),
+	io__format("You should specify one of the following options:\n", []),
+	io__format("--help      Generate this help message.", []),
+	io__format("--version   Report the program's version number.", []),
+	io__format("--test   	Test the deep profiler, generating all\n", []),
+	io__format("            possible web pages of the popular types.", []),
+	io__format("You may also specify the following options:.", []),
+	io__format("--test-dir <dirname>\n", []),
+	io__format("            Put the generated web pages into <dirname>.\n",
+					[]).
+	% --canonical-clique is not documented because it is not yet supported
+
 %-----------------------------------------------------------------------------%
 
 :- pred test_server(string::in, preferences::in, deep::in,
@@ -117,11 +159,13 @@
 	% file may contain hundreds of thousands of cliques. We therefore put
 	% each batch of pages in a different subdirectory, thus limiting the
 	% number of files/subdirs in each directory.
+	%
+	% XXX consider splitting up this predicate
 	{ Bunch = (Num - 1) // 1000 },
 	{ string__format("%s/%s_%04d",
 		[s(DirName), s(BaseName), i(Bunch)], BunchName) },
 	( { (Num - 1) rem 1000 = 0 } ->
-		{ string__format("test -p %s || mkdir -p %s",
+		{ string__format("test -d %s || mkdir -p %s",
 			[s(BunchName), s(BunchName)], Cmd) },
 		io__call_system(Cmd, _)
 	;
@@ -147,8 +191,10 @@
 :- type option
 	--->	canonical_clique
 	;	flat
+	;	help
 	;	test
-	;	test_dir.
+	;	test_dir
+	;	version.
 
 :- type options ---> options.
 :- type option_table == (option_table(option)).
@@ -162,8 +208,10 @@
 :- pred long(string::in, option::out) is semidet.
 
 long("canonical-clique",	canonical_clique).
+long("help",			help).
 long("test",			test).
 long("test-dir",		test_dir).
+long("version",			version).
 
 :- pred defaults(option::out, option_data::out) is nondet.
 
@@ -175,6 +223,8 @@
 
 defaults0(canonical_clique,	bool(no)).
+defaults0(help,			bool(no)).
 defaults0(test,			bool(no)).
 defaults0(test_dir,		string("deep_test")).
+defaults0(version,		bool(no)).
 
 %-----------------------------------------------------------------------------%
diff -u deep_profiler/startup.m deep_profiler/startup.m
--- deep_profiler/startup.m	13 Nov 2002 16:17:33 -0000
+++ deep_profiler/startup.m	18 Nov 2002 02:57:03 -0000
@@ -29,7 +29,7 @@
 :- import_module profile, read_profile, callgraph, canonical.
 :- import_module measurements, array_util.
 :- import_module std_util, int, string, array, assoc_list, set, map, require.
-:- import_module unsafe.
+% :- import_module unsafe.
 
 read_and_startup(Machine, DataFileNames, Canonical, MaybeOutputStream, Res) -->
 	(
@@ -224,7 +224,6 @@
 initialize_module_data(_ModuleName, PSPtrs) =
 	module_data(zero_own_prof_info, zero_inherit_prof_info, PSPtrs).
 
-
 %-----------------------------------------------------------------------------%
 
 :- pred record_css_containers_module_procs(int::in, proc_static::in,
@@ -868,8 +867,14 @@
 :- pred maybe_report_stats(maybe(io__output_stream)::in,
 	io__state::di, io__state::uo) is det.
 
-maybe_report_stats(yes(_)) --> [].
-	% io__report_stats("standard"). XXX
+% XXX: io__report_stats writes to stderr, which mdprof_cgi has closed.
+% We want to write the report to _OutputStream, but the library doesn't
+% support that yet.
+%
+% The stats are needed only when writing the deep profiling paper anyway.
+
+maybe_report_stats(yes(_OutputStream)) --> [].
+	% io__report_stats("standard").
 maybe_report_stats(no) --> [].
 
 :- pred maybe_report_msg(maybe(io__output_stream)::in, string::in,
diff -u deep_profiler/timeout.m deep_profiler/timeout.m
--- deep_profiler/timeout.m	13 Nov 2002 12:15:12 -0000
+++ deep_profiler/timeout.m	18 Nov 2002 03:37:27 -0000
@@ -57,12 +57,14 @@
 :- pred setup_timeout(int::in, io__state::di, io__state::uo) is det.
 
 % Get the lock on the named mutex file if the bool is `no'.
+% (The mutex file exists iff some process holds the lock.)
 % If the bool is `yes', meaning debugging is enabled, do nothing.
 
 :- pred get_lock(bool::in, string::in,
 	io__state::di, io__state::uo) is det.
 
 % Release the lock on the named mutex file if the bool is `no'.
+% (The mutex file exists iff some process holds the lock.)
 % If the bool is `yes', meaning debugging is enabled, do nothing.
 
 :- pred release_lock(bool::in, string::in,
@@ -83,14 +85,16 @@
 
 :- pragma foreign_decl("C",
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
+
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
+#include <fcntl.h>	/* for O_CREAT, O_EXCL */
 #include <signal.h>	/* for signal numbers */
 #include <unistd.h>	/* for alarm() */
-#include <stdlib.h>	/* for atexit() */
+#include <stdio.h>
 #include <errno.h>	/* for EEXIST etc */
+#include	<dirent.h>
 #include ""mercury_signal.h""
 
 #define	MP_MAX_CLEANUP_FILES	20	/* this should be plenty */
@@ -135,16 +139,15 @@
 extern	MR_bool	MP_do_try_get_lock(const char *mutex_file);
 extern	void	MP_do_get_lock(const char *mutex_file);
 extern	void	MP_do_release_lock(const char *mutex_file);
+
+#endif
 ").
 
 :- pragma foreign_code("C",
 "
-#if defined(MR_HAVE_DIRENT_H)
-  #include	<sys/types.h>
-  #include	<dirent.h>
-#else
-  /* if we get here, the deep profiler isn't enabled */
-#endif
+#ifdef	MR_DEEP_PROFILER_ENABLED
+
+#include	<sys/types.h>
 
 const char	*MP_cleanup_files[MP_MAX_CLEANUP_FILES];
 int		MP_cleanup_file_next = 0;
@@ -258,7 +261,7 @@
 	FILE	*fp;
 	char	buf[1024];	/* that should be big enough */
 
-#ifdef	MP_DEBUG_SIGNAL
+#ifdef	MP_DEBUG_MDPROF_SIGNAL
 	fp = fopen(""/tmp/mdprof_signal"", ""w"");
 	if (fp != NULL) {
 		fprintf(fp, ""%s\n"", signal_name);
@@ -268,7 +271,7 @@
 
 	MP_delete_cleanup_files();
 
-#ifdef	MP_DEBUG_SIGNAL
+#ifdef	MP_DEBUG_MDPROF_SIGNAL
 	sprintf(buf, ""Mercury deep profiler: received unexpected signal %s"",
 		signal_name);
 	MR_fatal_error(buf);
@@ -334,9 +337,6 @@
 void
 MP_handle_timeout(void)
 {
-#if defined(MR_HAVE_DIRENT_H) && defined(MR_HAVE_OPENDIR) \
-		&& defined(MR_HAVE_READDIR) && defined(MR_HAVE_CLOSEDIR)
-
 	DIR		*dir;
 	struct	dirent	*dirent;
 	int		matchlen;
@@ -357,7 +357,7 @@
 
 		(void) alarm(MP_timeout_seconds);
 		return;
-		}
+	}
 
 	dir = opendir(MP_timeout_want_dir);
 	if (dir == NULL) {
@@ -373,7 +373,7 @@
 			(void) alarm(MP_timeout_seconds);
 			return;
 		}
-	}
+		}
 
 	(void) closedir(dir);
 
@@ -383,9 +383,6 @@
 	MP_delete_cleanup_files();
 	exit(EXIT_SUCCESS);
 
-#else
-	/* if we get here, the deep profiler isn't enabled */
-#endif
 }
 
 void
@@ -494,38 +491,56 @@
 	MP_unregister_cleanup_file(mutex_file);
 	(void) unlink(mutex_file);
 }
+
+#endif	/* MR_DEEP_PROFILER_ENABLED */
 ").
 
 :- pragma foreign_proc("C",
 	register_file_for_cleanup(File::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_register_cleanup_file(File);
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
 	unregister_file_for_cleanup(File::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_unregister_cleanup_file(File);
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
 	unregister_all_files_for_cleanup(S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_cleanup_file_next = 0;
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
 	delete_cleanup_files(S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_delete_cleanup_files();
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
@@ -533,6 +548,7 @@
 		S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	int	i;
 
 	MP_timeout_mutex_file = MutexFile;
@@ -556,15 +572,22 @@
 	MR_register_exception_cleanup(MP_handle_fatal_exception, NULL);
 
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
 	setup_timeout(Minutes::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_timeout_seconds = Minutes * 60;
 	(void) alarm(MP_timeout_seconds);
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 %-----------------------------------------------------------------------------%
@@ -591,8 +614,12 @@
 	do_get_lock(MutexFile::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure, tabled_for_io],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_do_get_lock(MutexFile);
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pred do_release_lock(string::in, io__state::di, io__state::uo)
@@ -602,14 +629,19 @@
 	do_release_lock(MutexFile::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure, tabled_for_io],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_do_release_lock(MutexFile);
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
 	make_want_file(WantFileName::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	int	fd;
 
 	fd = open(WantFileName, O_CREAT, 0);
@@ -621,11 +653,18 @@
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
 
 :- pragma foreign_proc("C",
 	remove_want_file(WantFileName::in, S0::di, S::uo),
 	[will_not_call_mercury, promise_pure],
 "
+#ifdef	MR_DEEP_PROFILER_ENABLED
 	MP_unregister_cleanup_file(WantFileName);
 	(void) unlink(WantFileName);
 	S = S0;
+#else
+	MR_fatal_error(""deep profiler not enabled"");
+#endif
 ").
diff -u runtime/mercury_conf.h.in runtime/mercury_conf.h.in
--- runtime/mercury_conf.h.in	11 Nov 2002 10:44:59 -0000
+++ runtime/mercury_conf.h.in	16 Nov 2002 13:18:18 -0000
@@ -361,6 +361,11 @@
 #undef	MR_LITTLE_ENDIAN
 
 /*
+** Do we have the O_CREAT and O_EXCL macros?
+*/
+#undef	MR_HAVE_OCREAT_OEXCL
+
+/*
 ** Which version of Mercury is this?  (Taken from the file ../VERSION.)
 */
 #define MR_VERSION "unknown"
@@ -403,6 +408,14 @@
 **	See trace/mercury_trace_external.c.
 */
 #undef  MR_USE_EXTERNAL_DEBUGGER
+
+/*
+** MR_DEEP_PROFILER_ENABLED
+**	Enable the deep profiler. This should be defined only if all the
+**	features (header files and system calls) needed by the deep profiler
+**	ara available on this platform.
+*/
+#undef  MR_DEEP_PROFILER_ENABLED
 
 /*
 ** MR_NO_USE_READLINE
diff -u runtime/mercury_misc.h runtime/mercury_misc.h
--- runtime/mercury_misc.h	13 Nov 2002 12:05:53 -0000
+++ runtime/mercury_misc.h	18 Nov 2002 02:51:39 -0000
@@ -27,8 +27,19 @@
 
 extern	void	MR_fatal_error(const char *msg, ...) MR_NO_RETURN;
 
+/*
+** Register a function to be called (as func(data)) when the program is
+** about to be terminated due to an uncaught exception. 
+*/
+
 extern	void	MR_register_exception_cleanup(void (*func)(void *),
 			void *data);
+
+/*
+** Call all the functions registered with MR_register_exception_cleanup.
+** Should be invoked only when the program is about to be terminated
+** due to an uncaught exception. 
+*/
 
 extern	void	MR_perform_registered_exception_cleanups(void);
 
only in patch2:
--- tests/general/Mmakefile	14 Nov 2002 09:46:29 -0000	1.45
+++ tests/general/Mmakefile	16 Nov 2002 03:20:33 -0000
@@ -96,6 +96,8 @@
 TESTS_DIR=..
 include $(TESTS_DIR)/Mmake.common
 
+MCFLAGS += --no-optimize-duplicate-calls
+
 # Module-specific options should go in Mercury.options so they
 # can be found by `mmc --make'.
 include Mercury.options
only in patch2:
--- scripts/Mmakefile	16 May 2002 06:48:43 -0000	1.27
+++ scripts/Mmakefile	14 Nov 2002 07:47:39 -0000
@@ -20,7 +20,6 @@
 	  mercury.bat
 DEBUGGER_SCRIPTS = mdbrc
 EMACS_SCRIPTS = gud.el
-CGI_SCRIPTS = mdprof
 
 #-----------------------------------------------------------------------------#
 
@@ -34,7 +33,7 @@
 #-----------------------------------------------------------------------------#
 
 .PHONY: all
-all: $(SCRIPTS) $(DEBUGGER_SCRIPTS) $(EMACS_SCRIPTS) $(CGI_SCRIPTS)
+all: $(SCRIPTS) $(DEBUGGER_SCRIPTS) $(EMACS_SCRIPTS)
 all: Mmake.vars
 
 #-----------------------------------------------------------------------------#
@@ -90,17 +89,6 @@
 install_emacs_scripts: $(EMACS_SCRIPTS) install_dirs
 	cp $(EMACS_SCRIPTS) $(INSTALL_ELISP_DIR)
 
-.PHONY: install_cgi_scripts
-install_cgi_scripts: $(CGI_SCRIPTS)
-	# $(INSTALL_CGI_DIR) is likely to be writeable only by root or
-	# the www system administrator, which is why we don't consider a
-	# failure of this action to be an error. If the command fails,
-	# the install action in ../Mmakefile will remind the user to do
-	# the copy later.
-	-if test $(ENABLE_DEEP_PROFILER) = yes ; then \
-		cp $(CGI_SCRIPTS) $(INSTALL_CGI_DIR) ; \
-	fi
-
 #-----------------------------------------------------------------------------#
 
 .PHONY: uninstall
@@ -113,15 +101,6 @@
 	# on $(INSTALL_LIBDIR), and the directory into which $(EMACS_SCRIPTS)
 	# is installed, $(INSTALL_ELISP_DIR), is configured to be a
 	# subdirectory of $(INSTALL_LIBDIR).
-	#
-	# We try to uninstall $(CGI_SCRIPTS), but failure to do so is not an
-	# error for two reasons: because we may simply lack permission to
-	# update the directory, and because the deep profiler installation
-	# may not have been enabled in the first place. (Looking at the current
-	# value of $(ENABLE_DEEP_PROFILER) to check for the latter wouldn't
-	# necessarily do any good, since its setting may have changed since
-	# the original install.)
-	-cd $(INSTALL_CGI_DIR) && rm $(CGI_SCRIPTS)
 
 #-----------------------------------------------------------------------------#
 
only in patch2:
--- runtime/mercury_conf_param.h	16 Oct 2002 05:45:24 -0000	1.66
+++ runtime/mercury_conf_param.h	16 Nov 2002 12:30:04 -0000
@@ -227,6 +227,10 @@
 ** MR_DEBUG_LVAL_REP
 ** 	Enables low-level debugging messages from routines concerned with
 ** 	the representation of lvals in the RTTI system.
+**
+** MR_DEBUG_MDPROF_SIGNAL
+**	Enables low-level debugging messages from the signal handling
+**	functions in the deep profiler.
 */
 
 #ifdef	MR_HIGHLEVEL_CODE
only in patch2:
--- doc/user_guide.texi	15 Nov 2002 04:50:33 -0000	1.343
+++ doc/user_guide.texi	16 Nov 2002 03:19:52 -0000
@@ -3932,16 +3932,16 @@
 To display the information contained in a deep profiling data file
 (which will be called @file{Deep.data} unless you renamed it),
 start up your browser and give it a URL of the form
- at file{http://server.domain.name/cgi-bin/mdprof?/full/path/name/Deep.data}.
+ at file{http://server.domain.name/cgi-bin/mdprof_cgi?/full/path/name/Deep.data}.
 The @file{server.domain.name} part should be the name of a machine
 with the following qualifications:
 it should have a web server running on it,
-and it should have the @samp{mdprof} program installed
+and it should have the @samp{mdprof_cgi} program installed
 in its @file{/usr/lib/cgi-bin} directory.
 The @file{/full/path/name/Deep.data} part
 should be the full path name of the deep profiling data file
 whose data you wish to explore.
-The name of this file must not have dollar signs in it.
+The name of this file must not have percent signs in it.
 
 @node Profiling and shared libraries
 @section Profiling and shared libraries
only in patch2:
--- bindist/bindist.Makefile.in	8 Aug 2001 13:55:52 -0000	1.28
+++ bindist/bindist.Makefile.in	18 Nov 2002 03:40:24 -0000
@@ -1,5 +1,5 @@
 #---------------------------------------------------------------------------#
-# Copyright (C) 1996-1999, 2001 The University of Melbourne.
+# Copyright (C) 1996-1999, 2001-2002 The University of Melbourne.
 # This file may only be copied under the terms of the GNU General
 # Public License - see the file COPYING in the Mercury distribution.
 #---------------------------------------------------------------------------#
@@ -23,7 +23,9 @@
 			scripts/ml scripts/mmake scripts/mprof \
 			scripts/mdb scripts/mkfifo_using_mknod
 
-INSTALL_CGI_SCRIPTS	= scripts/mdprof
+CGI_PROG_NAME		= mdprof_cgi
+
+INSTALL_CGI_PROG	= cgi/$(CGI_PROG_NAME)
 
 INSTALL_EMACS_SCRIPTS	= scripts/gud.el
 
@@ -57,18 +59,22 @@
 	@echo "-- The binary distribution does not need building."
 	@echo "-- Use \`make install' to install"
 
+# The code of the install rule is duplicated from the toplevel Mmakefile,
+# with minor changes.
+
 .PHONY: install
 install: install_lib install_info install_man \
-		install_scripts install_emacs_scripts install_cgi_scripts \
+		install_scripts install_emacs_scripts install_cgi_progs \
 		install_mmake install_mdb install_util install_gac
 	@echo
 	@echo "-- Don't forget to add $(INSTALL_BINDIR) to your PATH,"
 	@echo "-- $(INSTALL_MAN_DIR) to your MANPATH,"
 	@echo "-- and $(INSTALL_INFODIR) to your INFOPATH,"
 	@if test $(ENABLE_DEEP_PROFILER) != yes || \
-		cmp -s scripts/mdprof.in $(INSTALL_CGI_DIR)/mdprof; \
+		cmp -s $(INSTALL_CGI_PROG) \
+			$(INSTALL_CGI_DIR)/$(CGI_PROG_NAME); \
 	then true ; else \
-		echo "-- to copy scripts/mdprof to $(INSTALL_CGI_DIR),"; \
+		echo "-- to copy $(INSTALL_CGI_PROG) to $(INSTALL_CGI_DIR),"; \
 	fi
 	@echo "-- and to add the following lines to the \`.emacs' file"
 	@echo "-- in your home directory:"
@@ -118,15 +124,25 @@
 	test -d $(INSTALL_ELISP_DIR) || mkdir -p $(INSTALL_ELISP_DIR)
 	cp $(INSTALL_EMACS_SCRIPTS) $(INSTALL_ELISP_DIR)
 
-.PHONY: install_cgi_scripts
-install_cgi_scripts: $(INSTALL_CGI_SCRIPTS)
+# The code of the install_cgi_progs target is duplicated from the code
+# of the install_cgi_progs target in deep_profiler/Mmakefile. However,
+# they refer to the script by different paths.
+
+.PHONY: install_cgi_progs
+install_cgi_progs: $(INSTALL_CGI_PROG)
 	# $(INSTALL_CGI_DIR) is likely to be writeable only by root or
 	# the www system administrator, which is why we don't consider a
 	# failure of this action to be an error. If the command fails,
-	# the action for the `install' target will remind the user
-	# to do the copy later.
+	# the install action in ../Mmakefile will remind the user to do
+	# the copy later.
+	#
+	# The mv before the cp is there in case the executable is being
+	# executed when we do the install. The mv is of course expected to
+	# fail during a first-time installation.
 	-if test $(ENABLE_DEEP_PROFILER) = yes ; then \
-		cp $(INSTALL_CGI_SCRIPTS) $(INSTALL_CGI_DIR) ; \
+		mv $(INSTALL_CGI_DIR)/$(CGI_PROG_NAME) \
+			$(INSTALL_CGI_DIR)/$(CGI_PROG_NAME).was ; \
+		cp $(INSTALL_CGI_PROG) $(INSTALL_CGI_DIR) ; \
 	fi
 
 .PHONY: install_mmake
only in patch2:
--- bindist/Mmakefile	4 Nov 2002 06:30:39 -0000	1.34
+++ bindist/Mmakefile	14 Nov 2002 07:41:17 -0000
@@ -33,6 +33,8 @@
 		  ../scripts/canonical_grade \
 		  ../scripts/gud.el
 
+CGI_PROG	= ../deep_profiler/mdprof_cgi
+
 VIM_FILES	= ../vim/*
 
 CONFIG_FILES	= ../config.sub ../config.guess ../install-sh
@@ -73,6 +75,8 @@
 	cp $(SCRIPT_FILES) $(MERCURY_VERSION)/scripts
 	test -d $(MERCURY_VERSION)/util || mkdir $(MERCURY_VERSION)/util
 	cp $(UTILS) $(MERCURY_VERSION)/util
+	test -d $(MERCURY_VERSION)/cgi || mkdir $(MERCURY_VERSION)/cgi
+	cp $(CGI_PROG) $(MERCURY_VERSION)/cgi
 	test -d $(MERCURY_VERSION)/vim || mkdir $(MERCURY_VERSION)/vim
 	cp -R $(VIM_FILES) $(MERCURY_VERSION)/vim
 	cp $(CONFIG_FILES) $(MERCURY_VERSION)
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list