[m-rev.] for post-commit review: cords in the deep_profiler

Zoltan Somogyi zs at csse.unimelb.edu.au
Mon Aug 4 13:16:40 AEST 2008


Convert Paul's new code to use cords of strings to represent HTML.

deep_profiler/html_format.m:
	Convert to using cords. Restructure the code in a couple of places
	to always put start and end tags around HTML fragments together.

	Fix a missing "=" in a tag.

deep_profiler/interface.m:
deep_profiler/mdprof_cgi.m:
deep_profiler/read_profile.m:
	Provide better diagnostics.

deep_profiler/create_report.m:
deep_profiler/display.m:
deep_profiler/display_report.m:
deep_profiler/mdprof_feedback.m:
deep_profiler/measurement_units.m:
deep_profiler/query.m:
deep_profiler/report.m:
mdbcomp/feedback.m:
	Misc cleanups. They can be considered my post-commit review of Paul's
	diff.

	In mdprof_feedback.m, delete a strange test that prevented the program
	from being used from the command line.

deep_profiler/dump.m:
deep_profiler/mdprof_dump.m:
deep_profiler/timeout.m:
deep_profiler/util.m:
	Misc cleanups of old code.

Zoltan.

cvs diff: Diffing .
cvs diff: Diffing analysis
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/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
Index: deep_profiler/create_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/create_report.m,v
retrieving revision 1.1
diff -u -b -r1.1 create_report.m
--- deep_profiler/create_report.m	29 Jul 2008 01:42:59 -0000	1.1
+++ deep_profiler/create_report.m	3 Aug 2008 14:52:53 -0000
@@ -9,8 +9,7 @@
 % File: create_report.m.
 % Author: pbone.
 %
-% This module contains the create_report predicate that creates a report
-% from a deep data structure and a query.
+% This module creates a report from a deep data structure and a query.
 %
 %-----------------------------------------------------------------------------%
 
@@ -43,30 +42,31 @@
 
 %-----------------------------------------------------------------------------%
 
-create_report(deep_cmd_quit, Deep, Report) :-
-    Report = report_message(string.format(
-        "Shutting down deep profile server for %s.",
-        [s(Deep ^ data_file_name)])).
-
-create_report(deep_cmd_timeout(Timeout), _Deep, Report) :-
-    Report = report_message(string.format(
-        "Timeout set to %d minutes.", [i(Timeout)])).
-
-create_report(deep_cmd_restart, _, _) :-
-    error("create_report/3", "unexpected restart command").
-
-create_report(deep_cmd_menu, Deep, Report) :-
+create_report(Cmd, Deep, Report) :-
+    (
+        Cmd = deep_cmd_quit,
+        Msg = string.format("Shutting down deep profile server for %s.",
+            [s(Deep ^ data_file_name)]),
+        Report = report_message(Msg)
+    ;
+        Cmd = deep_cmd_timeout(Timeout),
+        Msg = string.format("Timeout set to %d minutes.", [i(Timeout)]),
+        Report = report_message(Msg)
+    ;
+        Cmd = deep_cmd_menu,
     Deep ^ profile_stats = profile_stats(NumCSD, NumCSS, NumPD, NumPS,
-        QuantaPerSec, InstrumentationQuanta, UserQuanta, NumCallsequs, _, _),
-    NumClique = array.max(Deep ^ clique_members),
+            QuantaPerSec, InstrumentationQuanta, UserQuanta, NumCallsequs,
+            _, _),
+        NumCliques = array.max(Deep ^ clique_members),
     Report = report_menu(QuantaPerSec, UserQuanta, InstrumentationQuanta,
-        NumCallsequs, NumCSD, NumCSS, NumPD, NumPS, NumClique).
-
-create_report(deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope), Deep,
-        Report) :-
-    create_top_procs_report(Deep, Limit, CostKind, InclDesc, Scope, Report).
-
-create_report(Cmd, _, _) :-
+            NumCallsequs, NumCSD, NumCSS, NumPD, NumPS, NumCliques)
+    ;
+        Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
+        create_top_procs_report(Deep, Limit, CostKind, InclDesc, Scope, Report)
+    ;
+        Cmd = deep_cmd_restart,
+        error("create_report/3", "unexpected restart command")
+    ;
     ( Cmd = deep_cmd_root(_)
     ; Cmd = deep_cmd_clique(_)
     ; Cmd = deep_cmd_proc(_)
@@ -77,8 +77,10 @@
     ; Cmd = deep_cmd_proc_dynamic(_)
     ; Cmd = deep_cmd_call_site_static(_)
     ; Cmd = deep_cmd_call_site_dynamic(_)
-    ; Cmd = deep_cmd_raw_clique(_)),
-    error("create_report/3", "Command not supported: " ++ string(Cmd)).
+        ; Cmd = deep_cmd_raw_clique(_)
+        ),
+        error("create_report/3", "Command not supported: " ++ string(Cmd))
+    ).
 
 %-----------------------------------------------------------------------------%
 %
@@ -115,18 +117,19 @@
     ;
         MaybeTopPSIs = ok(TopPSIs),
         Ordering = report_ordering(Limit, CostKind, InclDesc, Scope),
-        map(psi_to_row_data(Deep), TopPSIs, RowData),
+        list.map(psi_to_perf_row_data(Deep), TopPSIs, RowData),
         Report = report_top_procs(Ordering, RowData)
     ).
 
 %-----------------------------------------------------------------------------%
 
-    % For a Proc Static Index query the deep data and retrive the data to
-    % include in that row of the report.
+    % Lookup the proc_static structure with the given PSI index number
+    % and return performance information about it.
     %
-:- pred psi_to_row_data(deep::in, int::in, row_data(report_proc)::out) is det.
+:- pred psi_to_perf_row_data(deep::in, int::in,
+    perf_row_data(report_proc)::out) is det.
 
-psi_to_row_data(Deep, PSI, RowData) :-
+psi_to_perf_row_data(Deep, PSI, RowData) :-
     % Gather global deep profiling information.
     ProfileStats = Deep ^ profile_stats,
     TicksPerSec = ProfileStats ^ ticks_per_sec,
Index: deep_profiler/display.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/display.m,v
retrieving revision 1.1
diff -u -b -r1.1 display.m
--- deep_profiler/display.m	29 Jul 2008 01:42:59 -0000	1.1
+++ deep_profiler/display.m	2 Aug 2008 01:30:01 -0000
@@ -9,8 +9,8 @@
 % File: display.m.
 % Author: pbone.
 %
-% This module contains a data structure for displaying deep profiler
-% reports.  It may be versatile enough for other uses.
+% This module contains a data structure for displaying deep profiler reports.
+% It may be versatile enough for other uses.
 %
 %-----------------------------------------------------------------------------%
 
@@ -36,14 +36,14 @@
     --->    display_message(string)
     ;       display_table(table)
     ;       display_list(
-                list_class,
                     % Class of the list, may be used to display the list.
+                list_class,
 
-                maybe(string),
                     % An optional title.
+                maybe(string),
  
-                list(display_item)
                     % Items within the list.
+                list(display_item)
             )
     ;       display_command_link(deep_link).
 
@@ -54,22 +54,22 @@
 
 :- type table
     --->    table(
-                table_class     :: table_class,
                     % Enumeration of what the table stores, this can be used
                     % for layout hints.
+                table_class     :: table_class,
     
+                % The number of columns in the table.  If the number of cells
+                % in any data row is not equal to this number, the table is not
+                % well formed. The number of cells in the header may be smaller
+                % than this value when there are header cells that span
+                % multiple sub-header cells.
                 table_num_cols  :: int,
-                    % The number of columns in the table.  If the number of
-                    % cells in any data row is not equal to this number the
-                    % table is not well formed. The number of cells in the
-                    % header may be smaller than this value when there are
-                    % header cells that span multiple sub-header cells.
 
-                table_header    :: maybe(table_header),
                     % Header row of table.
+                table_header    :: maybe(table_header),
                 
+                % The data in table.
                 table_rows      :: list(table_row)
-                    % Data in table,
             ).
 
 :- type table_header
@@ -79,20 +79,20 @@
 
 :- type table_header_cell
     --->    table_header_cell(
-                thc_contents    :: table_data,
                     % The table contents.
+                thc_contents    :: table_data,
 
-                thc_class       :: table_col_class
                     % The class may be used by a layout to make decisions
                     % about how to paint this column.
+                thc_class       :: table_col_class
             )
     ;       table_header_group(
                 thg_title       :: string,
                 thg_subtitles   :: list(table_data),
                 
-                thg_class       :: table_col_class
                     % The class may be used by a layout to make decisions
                     % about how to paint this column.
+                thg_class       :: table_col_class
             ).
 
 :- type table_row
@@ -132,14 +132,14 @@
     ;       i(int)
     ;       l(deep_link)
     ;       m(
+                % The amount of memory.
                 memory,
-                    % The amount of memory
                     
+                % The units to display memory in.
                 memory_units,
-                    % The units to display memory in
 
+                % The number of decimal places to show.
                 int
-                    % The number of decimal places to show
             )
     ;       p(percent)
     ;       s(string)
@@ -162,17 +162,17 @@
 
 :- type deep_link
     --->    deep_link(
-                cmd,
                     % The link command.
+                cmd,
                
-                maybe(preferences),
                     % The preferences for the link command.
+                maybe(preferences),
 
-                string,
                     % A label for the link.
+                string,
                 
-                link_class
                     % Class of the link may control how it is displayed.
+                link_class
             ).
 
 :- type link_class
Index: deep_profiler/display_report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/display_report.m,v
retrieving revision 1.1
diff -u -b -r1.1 display_report.m
--- deep_profiler/display_report.m	29 Jul 2008 01:42:59 -0000	1.1
+++ deep_profiler/display_report.m	3 Aug 2008 14:13:06 -0000
@@ -21,16 +21,15 @@
 :- import_module profile.
 :- import_module report.
 
-% XXX: This include should be removed or replaced.  Some datastructes such as
-% preferences are currenty defined in query, the should be moved into a
-% different module so that this module doesn't need to include the whole of
-% query.
+% XXX: This include should be removed or replaced.  Some data structures
+% such as preferences are currently defined in query, they should be moved
+% into a different module so that this module doesn't need to include
+% the whole of query.
 :- import_module query.
 
 %-----------------------------------------------------------------------------%
 
-:- pred display_report(deep::in, preferences::in, deep_report::in,
-    display::out) is det.
+:- func report_to_display(deep, preferences, deep_report) = display.
     
 %-----------------------------------------------------------------------------%
 
@@ -48,28 +47,30 @@
 
 %-----------------------------------------------------------------------------%
 
-display_report(_, _, report_message(Msg), Display) :-
-    Display = display(no, [display_message(Msg)]).
-
-display_report(Deep, _, Report, Display) :-
-    Report = report_menu(QuantaPerSec, UserQuanta, InstQuanta, NumCallsequs,
-        NumCSD, NumCSS, NumPD, NumPS, NumClique),
+report_to_display(Deep, Prefs, Report) = Display :-
+    (
+        Report = report_message(Msg),
+        Display = display(no, [display_message(Msg)])
+    ;
+        Report = report_menu(QuantaPerSec, UserQuanta, InstQuanta,
+            NumCallseqs, NumCSD, NumCSS, NumPD, NumPS, NumClique),
     display_report_menu(Deep, QuantaPerSec, UserQuanta, InstQuanta,
-        NumCallsequs, NumCSD, NumCSS, NumPD, NumPS, NumClique, Display).
-
-display_report(_, Prefs, report_top_procs(Ordering, TopProcs), Display) :-
-    display_report_top_procs(Prefs, Ordering, TopProcs, Display).
+            NumCallseqs, NumCSD, NumCSS, NumPD, NumPS, NumClique, Display)
+    ;
+        Report = report_top_procs(Ordering, TopProcs),
+        display_report_top_procs(Prefs, Ordering, TopProcs, Display)
+    ).
 
 %-----------------------------------------------------------------------------%
 %
-% Code to display menu report..
+% Code to display menu report.
 %
 
 :- pred display_report_menu(deep::in, int::in, int::in, int::in, int::in,
     int::in, int::in, int::in, int::in, int::in, display::out)
     is det.
 
-display_report_menu(Deep, QuantaPerSec, UserQuanta, InstQuanta, NumCallsequs,
+display_report_menu(Deep, QuantaPerSec, UserQuanta, InstQuanta, NumCallseqs,
         NumCSD, NumCSS, NumPD, NumPS, NumClique, Display) :-
     ShouldDisplayTimes = should_display_times(Deep),
     
@@ -140,10 +141,10 @@
          (deep_cmd_top_procs(threshold_percent(0.1), cost_words, self, 
                 overall) -
             "Procedures above 0.1% threshold: words, self."),
-         % 2M words is chosen arbitrary because it is 8MB on ia32
          (deep_cmd_top_procs(threshold_percent(1.0), cost_words, 
                 self_and_desc, overall) -
             "Procedures above 1% threshold: words, self+descendants."),
+         % 2M words is chosen because it is 8MB on ia32.
          (deep_cmd_top_procs(threshold_value(float(1024 * 1024 * 2)), 
                 cost_words, self_and_desc, overall) -
             "Procedures above 2M words threshold: words, self+descendants.")],
@@ -151,22 +152,24 @@
     LinkCmds = LinksExploration ++ 
         LinksTopProcsByLimitTime ++ LinksTopProcsByLimit ++ 
         LinksTopProcsByPercentTime ++ LinksTopProcsByPercent,
-    map(make_command_link, LinkCmds, LinksList),
+    list.map(make_command_link, LinkCmds, LinksList),
     Links = display_list(list_class_vertical_bullets, 
         yes("You can start exploring the deep profile at the following" ++ 
             " points."), LinksList),
 
     % Display the table section of the report.
-    ProfilingStatistics = [("Quanta per second:"           - QuantaPerSec),
+    ProfilingStatistics =
+        [("Quanta per second:"          - QuantaPerSec),
                            ("Quanta in user code:"         - UserQuanta),
                            ("Quanta in instrumentation:"   - InstQuanta),
-                           ("Call sequence numbers:"       - NumCallsequs),
+        ("Call sequence numbers:"       - NumCallseqs),
                            ("CallSiteDyanic structures:"   - NumCSD),
                            ("ProcDynamic structures:"      - NumPD),
                            ("CallSiteStatic structures:"   - NumCSS),
                            ("ProcStatic structures:"       - NumPS),
                            ("Cliques:"                     - NumClique)],
-    map(make_menu_table_row, ProfilingStatistics, Rows),
+
+    list.map(make_menu_table_row, ProfilingStatistics, Rows),
     Table = table(table_class_menu, 2, no, Rows),
 
     % Display the Controls section of the report.
@@ -202,24 +205,20 @@
     % Create a display_report structure for a top_procedures report.
     %
 :- pred display_report_top_procs(preferences::in, report_ordering::in,
-    list(row_data(report_proc))::in, display::out) is det.
+    list(perf_row_data(report_proc))::in, display::out) is det.
 
 display_report_top_procs(Prefs, Ordering, TopProcs, Display) :-
     Ordering = report_ordering(DisplayLimit, CostKind, InclDesc, Scope), 
     Desc = cost_criteria_to_description(CostKind, InclDesc, Scope),
     Title = "Top procedures " ++ Desc, 
 
-    %
-    % Build table
-    %
+    % Build table.
     top_procs_table(Prefs, Ordering, TopProcs, Table),
     DisplayTable = display_table(Table), 
     TableAndLabel = display_list(list_class_vertical_no_bullets,
         yes(Title), [DisplayTable]),
 
-    %
-    % Build controls at bottom of page
-    %
+    % Build controls at bottom of page.
     Cmd = deep_cmd_top_procs(DisplayLimit, CostKind, InclDesc, Scope),
     sort_controls(Prefs, Ordering, SortControls),
     incldesc_and_scope_controls(Prefs, Ordering, InclDescScope),
@@ -288,7 +287,7 @@
             ).
 
 :- pred top_procs_table(preferences::in, report_ordering::in,
-    list(row_data(report_proc))::in, table::out) is det.
+    list(perf_row_data(report_proc))::in, table::out) is det.
 
 top_procs_table(Prefs, Ordering, TopProcs, Table) :-
     TableInfo = table_info(table_class_top_procs, ranked, Prefs, Ordering),
@@ -314,24 +313,37 @@
 
     % Produce a table for all these procedures.
     %
-:- pred proc_table(table_info::in, list(row_data(report_proc))::in, table::out)
-    is det. 
+:- pred proc_table(table_info::in, list(perf_row_data(report_proc))::in,
+    table::out) is det.
 
 proc_table(TableInfo, TopProcs, Table) :-
     % Later add support for non-ranked tables.
     proc_table_header(TableInfo, NumCols, Header),
-    map_foldl(proc_table_row(TableInfo), TopProcs, Rows, 1, _),
+    list.map_foldl(proc_table_row(TableInfo), TopProcs, Rows, 1, _),
     Table = table(TableInfo ^ table_class, NumCols, yes(Header), Rows).
 
-    % Common column header strings.
-    %
+%-----------------------------------------------------------------------------%
+%
+% Common column header strings.
+%
+
 :- func percall = table_data.
 percall = s("/call").
+
 :- func percent_label = table_data.
 percent_label = s("%").
+
 :- func self = table_data.
 self = s("Self").
 
+:- func time = table_data.
+time = s("Time").
+
+:- func total = table_data.
+total = s("Total").
+
+%-----------------------------------------------------------------------------%
+
 :- func make_link(report_ordering, preferences, string, cost_kind,
     include_descendants, measurement_scope) = deep_link.
 
@@ -362,6 +374,8 @@
     Ordering = TableInfo ^ table_ordering,
     Prefs = TableInfo ^ prefs.
 
+%-----------------------------------------------------------------------------%
+
 :- func self_link(table_info, cost_kind) = table_data.
 self_link(TableInfo, CostKind) = Link :-
     make_table_link(TableInfo, "Self", CostKind, self, overall) = Link.
@@ -386,17 +400,13 @@
 total_time_link(TableInfo) =
     make_table_link(TableInfo, "Time", cost_time, self_and_desc, overall).
 
-
-:- func time = table_data.
-time = s("Time").
-:- func total = table_data.
-total = s("Total").
+%-----------------------------------------------------------------------------%
 
     % Convert row data of procedures from the deep profiler into a table row
-    % accoding to the preferences.
+    % according to the preferences.
     %
-:- pred proc_table_row(table_info::in, 
-    row_data(report_proc)::in, table_row::out, int::in, int::out) is det.
+:- pred proc_table_row(table_info::in, perf_row_data(report_proc)::in,
+    table_row::out, int::in, int::out) is det.
 
 proc_table_row(TableInfo, RowData, table_row(Cells), Rank, Rank+1) :-
     Ranked = TableInfo ^ table_ranked,
@@ -424,7 +434,8 @@
         Fails = RowData ^ fails,
         Redos = RowData ^ redos,
         Excps = RowData ^ excps,
-        PortCells = [table_cell(i(Calls)), table_cell(i(Exits)),
+        PortCells =
+            [table_cell(i(Calls)), table_cell(i(Exits)),
             table_cell(i(Fails)), table_cell(i(Redos)),
             table_cell(i(Excps))]
     ;
@@ -465,9 +476,11 @@
                 TimeCell, TimePercentCell, TimePercallCell]
         ;
             TimeFields = ticks_and_time_and_percall,
-            TimeCells = [SelfTicksCell, SelfTimeCell, SelfTimePercentCell, 
-                    SelfTimePercallCell,
-                TicksCell, TimeCell, TimePercentCell, TimePercallCell]
+            TimeCells =
+                [SelfTicksCell, SelfTimeCell,
+                SelfTimePercentCell, SelfTimePercallCell,
+                TicksCell, TimeCell,
+                TimePercentCell, TimePercallCell]
         )
     ),
 
@@ -484,16 +497,19 @@
         CallseqsPercentCell = table_cell(p(RowData ^ callseqs_percent)),
         (
             CallSeqsFields = callseqs,
-            CallSeqsCells = [SelfCallseqsCell, SelfCallseqsPercentCell,
+            CallSeqsCells =
+                [SelfCallseqsCell, SelfCallseqsPercentCell,
                 CallseqsCell, CallseqsPercentCell]
         ;
             CallSeqsFields = callseqs_and_percall,
             SelfCallseqsPercallCell = 
                 table_cell(f(RowData ^ self_callseqs_percall)),
             CallseqsPercallCell = table_cell(f(RowData ^ callseqs_percall)),
-            CallSeqsCells = [SelfCallseqsCell, SelfCallseqsPercentCell, 
+            CallSeqsCells =
+                [SelfCallseqsCell, SelfCallseqsPercentCell,
                     SelfCallseqsPercallCell,
-                CallseqsCell, CallseqsPercentCell, CallseqsPercallCell]
+                CallseqsCell, CallseqsPercentCell,
+                CallseqsPercallCell]
         )
     ),
     
@@ -509,15 +525,16 @@
         AllocsPercentCell = table_cell(p(RowData ^ allocs_percent)),
         (
             AllocFields = alloc,
-            AllocCells = [SelfAllocsCell, SelfAllocsPercentCell,
+            AllocCells =
+                [SelfAllocsCell, SelfAllocsPercentCell,
                 AllocsCell, AllocsPercentCell]
         ;
             AllocFields = alloc_and_percall,
             SelfAllocsPercallCell = 
                 table_cell(f(RowData ^ self_allocs_percall)),
             AllocsPercallCell = table_cell(f(RowData ^ allocs_percall)),
-            AllocCells = [SelfAllocsCell, SelfAllocsPercentCell, 
-                    SelfAllocsPercallCell,
+            AllocCells =
+                [SelfAllocsCell, SelfAllocsPercentCell, SelfAllocsPercallCell,
                 AllocsCell, AllocsPercentCell, AllocsPercallCell]
         )
     ),
@@ -538,11 +555,13 @@
         MemPercentCell = table_cell(p(RowData ^ mem_percent)),
         (
             MemoryFields = memory(_),
-            MemoryCells = [SelfMemCell, SelfMemPercentCell, 
+            MemoryCells =
+                [SelfMemCell, SelfMemPercentCell,
                 MemCell, MemPercentCell]
         ;
             MemoryFields = memory_and_percall(_),
-            MemoryCells = [SelfMemCell, SelfMemPercentCell, SelfMemPercallCell,
+            MemoryCells =
+                [SelfMemCell, SelfMemPercentCell, SelfMemPercallCell,
                 MemCell, MemPercentCell, MemPercallCell]
         )
     ),
@@ -550,7 +569,6 @@
     Cells = RankCells ++ cons(ProcCell, PortCells ++ TimeCells ++ 
         CallSeqsCells ++ AllocCells ++ MemoryCells). 
 
-
 :- pred proc_to_cell(table_info::in, report_proc::in, table_cell::out) is det.
 
 proc_to_cell(TableInfo, ReportProc, table_cell(Data)) :-
@@ -560,7 +578,6 @@
     Cmd = deep_cmd_proc(PSIndex),
     Data = l(deep_link(Cmd, yes(Prefs), Name, link_class_link)). 
 
-
     % Create the table header cell for the timing fields.
     %
 :- pred proc_table_time_header(table_info::in, fields::in,
@@ -595,12 +612,14 @@
         ;
             TimeFields = time_and_percall,
             Title = "Time",
-            SubTitles = [Self, percent_label, SelfPercall, 
+            SubTitles =
+                [Self, percent_label, SelfPercall,
                 Total, percent_label, TotalPercall]
         ; 
             TimeFields = ticks_and_time_and_percall, 
             Title = "Clock ticks and times",
-            SubTitles = [Self, Time, percent_label, SelfPercall, 
+            SubTitles =
+                [Self, Time, percent_label, SelfPercall,
                 Total, TotalTime, percent_label, TotalPercall]
         ),
         MaybeHeaderCell = yes(table_header_group(Title, SubTitles,
@@ -645,7 +664,8 @@
             Callseqs = callseqs_and_percall,
             SelfPercall = self_percall_link(TableInfo, cost_callseqs),
             TotalPercall = total_percall_link(TableInfo, cost_callseqs),
-            SubTitles = [Self, percent_label, SelfPercall, 
+            SubTitles =
+                [Self, percent_label, SelfPercall,
                 Total, percent_label, TotalPercall]
         ),
         MaybeCallseqsHeader = yes(table_header_group("Call sequence numbers",
@@ -672,7 +692,8 @@
             AllocFields = alloc_and_percall,
             SelfPercall = self_percall_link(TableInfo, cost_allocs),
             TotalPercall = total_percall_link(TableInfo, cost_allocs),
-            SubTitles = [Self, percent_label, SelfPercall, 
+            SubTitles =
+                [Self, percent_label, SelfPercall,
                 Total, percent_label, TotalPercall]
         ),
         MaybeHeader = yes(table_header_group("Memory allocations", SubTitles,
@@ -700,7 +721,8 @@
             Memory = memory_and_percall(Units),
             SelfPercall = self_percall_link(TableInfo, cost_words),
             TotalPercall = total_percall_link(TableInfo, cost_words),
-            SubTitles = [Self, Percent, SelfPercall, 
+            SubTitles =
+                [Self, Percent, SelfPercall,
                 Total, Percent, TotalPercall]
         ),
         (
@@ -735,8 +757,9 @@
         ;
             Ranked = non_ranked
         ),
-        table_add_header_col(table_header_cell(s("Procedure"),
-            table_col_class_proc), !Cols, !NumCols),
+        ProcHeaderCell =
+            table_header_cell(s("Procedure"), table_col_class_proc),
+        table_add_header_col(ProcHeaderCell, !Cols, !NumCols),
         
         proc_table_ports_header(TableInfo, Fields, MaybePortsHeader),
         table_maybe_add_header_col(MaybePortsHeader, !Cols, !NumCols),
@@ -836,7 +859,7 @@
             deep_cmd_top_procs(DisplayLimit, CostKind, CurrentInclDesc, Scope),
             yes(Prefs), ScopeLabel, link_class_control),
 
-    map(link_to_display, [InclDescControl, ScopeControl], Controls), 
+    list.map(link_to_display, [InclDescControl, ScopeControl], Controls),
     ControlsList = display_list(list_class_horizontal, no, Controls).
 
     % Provide a predicate to be used as a higher order value that wraps the
@@ -1054,8 +1077,8 @@
 :- mode make_fields_control(pred(in, in, out) is det, pred(in, out) is det,
     in, in, in, out) is det.
 
-make_fields_control(UpdateFields, MakeLabel, Cmd, Prefs0, NewFields, Control)
-        :-
+make_fields_control(UpdateFields, MakeLabel, Cmd, Prefs0, NewFields,
+        Control) :-
     Fields0 = Prefs0 ^ pref_fields,
     UpdateFields(NewFields, Fields0, Fields),
     Prefs = Prefs0 ^ pref_fields := Fields,
@@ -1094,8 +1117,8 @@
     
 %-----------------------------------------------------------------------------%
     
-    % Make a mercury list of display items into a display item representing a
-    % horizontal list of these items.
+    % Make a mercury list of display items into a display item representing
+    % a horizontal list of these items.
     %
 :- pred make_horizontal_list(list(display_item)::in, display_item::out) is det.
 
Index: deep_profiler/dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/dump.m,v
retrieving revision 1.14
diff -u -b -r1.14 dump.m
--- deep_profiler/dump.m	29 Jul 2008 23:57:59 -0000	1.14
+++ deep_profiler/dump.m	3 Aug 2008 14:14:56 -0000
@@ -38,7 +38,6 @@
                 do_dump_prop_measurements   :: dump_prop_measurements
             ).
 
-
     % This type is used to describe if a restricted set of "css" and "ps"
     % structures should be shown, (those for code that was executed), or if all
     % "css" and "ps" structures should be shown.
@@ -47,7 +46,6 @@
     --->        show_restricted_dump
     ;           show_complete_dump.
 
-
     % This type indicates the arrays in the deep profile data that may be
     % printed.
     %
@@ -57,14 +55,12 @@
     ;           pd
     ;           ps.
 
-    
     % show_stats describes whether to show some statistics and the root node
     % in the dump.
     %
 :- type show_stats
     --->        show_stats
-    ;           dont_show_stats.
-
+    ;           do_not_show_stats.
 
     % Types to specifiy if cliques, rev (proc static to caller) links and
     % propagated measurements should be dumpped by dump_deep/3.
@@ -81,14 +77,12 @@
     --->        dump_prop_measurements
     ;           do_not_dump_prop_measurements.
 
-
 %-----------------------------------------------------------------------------%
     
     % returns the default dump options.
     %
 :- func default_dump_options = dump_options.
 
-
     % dump_array_options will take a list of strings for the accumulating
     % dump options and produce a set if possible.
     %
@@ -100,7 +94,6 @@
 :- pred det_dump_array_options(list(string)::in, set(dumpable_array)::out)
     is det.
 
-    
     % dump_array_options_to_dump_options takes a list of strings of the
     % accumulating array dump options and create a dump_options structure
     % based on the default plus these spacific array options.
@@ -108,7 +101,6 @@
 :- pred dump_array_options_to_dump_options(list(string)::in,
     dump_options::out) is det.
 
-
     % dump_initial_deep(InitialDeep, DumpOptions, !IO):
     %
     % Print selected parts of InitialDeep to standard output.  Which parts
@@ -153,7 +145,6 @@
     DumpOptions = dump_options(show_complete_dump, all_array_options,
         show_stats, dump_cliques, dump_rev_links, dump_prop_measurements).
 
-
 det_dump_array_options(Strings, DumpArrayOptions) :-
     (
         dump_array_options_special(Strings, DumpArrayOptionsSpecial)
@@ -174,7 +165,6 @@
             DumpArrayOptions)
     ).
 
-
     % Handle special cases in the list of array options.
     %
 :- pred dump_array_options_special(list(string)::in, set(dumpable_array)::out)
@@ -183,22 +173,18 @@
 dump_array_options_special([], all_array_options).
 dump_array_options_special(["all"], all_array_options).
 
-
 dump_array_options_to_dump_options(Strings, DumpOptions) :-
     det_dump_array_options(Strings, DumpArrayOptions),
     DumpOptions = default_dump_options ^ do_arrays := DumpArrayOptions.
       
-
-
 :- pred string_list_to_sym_set(pred(string, X), list(string), set(X)).
 :- mode string_list_to_sym_set(pred(in, out) is det, in, out) is det.
 :- mode string_list_to_sym_set(pred(in, out) is semidet, in, out) is semidet.
 
-string_list_to_sym_set(StrToSym, List0, Set) :-
-    map(StrToSym, List0, List),
+string_list_to_sym_set(StrToSym, StrList, Set) :-
+    list.map(StrToSym, StrList, List),
     list_to_set(List, Set).
 
-
 :- pred det_string_to_dumpable_array(string::in, dumpable_array::out) is det.
 
 det_string_to_dumpable_array(String, Array) :-
@@ -208,7 +194,6 @@
         error("Invalid array name in dump options: " ++ String)
     ).
 
-
 :- pred string_to_dumpable_array(string::in, dumpable_array::out) is semidet.
 
 string_to_dumpable_array("csd", csd).
@@ -216,13 +201,11 @@
 string_to_dumpable_array("pd", pd).
 string_to_dumpable_array("ps", ps).
 
-
 :- func all_array_options = set(dumpable_array).
 
 all_array_options = Set :-
     Set = set.list_to_set([csd, css, pd, ps]).
 
-
 %----------------------------------------------------------------------------%
 %
 % Dump initial deep profiling structure.
@@ -245,7 +228,7 @@
         dump_init_profile_stats(Stats, !IO),
         dump_init_root(InitRoot, !IO)
     ;
-        ShowStats = dont_show_stats
+        ShowStats = do_not_show_stats
     ),
     ( should_dump(DumpOptions, csd) ->
         dump_init_call_site_dynamics(CSDs, !IO)
@@ -586,7 +569,6 @@
     CSSPtr = call_site_static_ptr(CSSI),
     io.format("\tps_site[%d]: css%d\n", [i(Slot), i(CSSI)], !IO).
 
-
 :- pred dump_coverage_point(int::in, coverage_point::in, io::di, io::uo) 
     is det.
 
@@ -596,7 +578,6 @@
     io.format("\tcoverage_point[%d]: %s, %s: %d\n", 
         [i(Num), s(string(Type)), s(PathString), i(Count)], !IO).
 
-
 %----------------------------------------------------------------------------%
 
 :- func dump_proc_id(string_proc_label) = string.
@@ -660,7 +641,6 @@
         DumpPropMeasurements = do_not_dump_prop_measurements
     ).
 
-
 %----------------------------------------------------------------------------%
 
 :- pred dump_deep_cliques(deep::in, io::di, io::uo) is det.
Index: deep_profiler/html_format.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/html_format.m,v
retrieving revision 1.22
diff -u -b -r1.22 html_format.m
--- deep_profiler/html_format.m	29 Jul 2008 01:42:59 -0000	1.22
+++ deep_profiler/html_format.m	3 Aug 2008 14:41:36 -0000
@@ -11,15 +11,12 @@
 %
 % This module contains code that sets the format of the HTML tables
 % we generate for individual queries.
-%
-% This module makes many calls to string.append.  In the C backends
-% string.append is linear time over the length of both input strings when
-% called in in, in, out mode.  If we build a long string from many short
-% strings the cost will be quadratic.  It may be better to build a data
-% structure with cords to describe how strings should be appended and then
-% use calls to string.append_list at a final stage to construct a single
-% string from the cord of strings.  There are alternative approaches that
-% should reduce the final cost to linear.
+
+% This module appends many strings. Since string.append takes time that is
+% linear over the length of both input strings, building a long string
+% from many short strings would take quadratic time. This is why we represent
+% HTML as a cord of strings instead. This cord is then converted to a list of
+% strings and then a single list just before being given to the browser.
 %
 %-----------------------------------------------------------------------------%
 
@@ -33,18 +30,25 @@
 :- import_module display.
 
 :- import_module bool.
+:- import_module cord.
 :- import_module list.
 :- import_module unit.
 
 %-----------------------------------------------------------------------------%
 
+:- type html == cord(string).
+
+:- func html_to_string(html) = string.
+
+%-----------------------------------------------------------------------------%
+
     % Construct a complete HTML page from the given display structure.
     %
-    % The first parameter is used to geather extra information from the deep
+    % The first parameter is used to gather extra information from the deep
     % profile, for example the name of the Deep.data file to build the URLs
     % from.
     %
-:- pred htmlize_display(deep::in, display::in, string::out) is det.
+:- func htmlize_display(deep, display) = html.
 
 %-----------------------------------------------------------------------------%
 
@@ -183,19 +187,42 @@
 
 %-----------------------------------------------------------------------------%
 
-htmlize_display(Deep, display(MaybeTitle, Content), HTML) :-
-    maybe_title_to_title(Deep, MaybeTitle, Title),
+html_to_string(HTML) = Str :-
+    string.append_list(cord.list(HTML), Str).
+
+%-----------------------------------------------------------------------------%
+
+htmlize_display(Deep, display(MaybeSubTitle, Items)) = HTML :-
+    MainTitle = str_to_html("Mercury Deep Profile for ") ++
+        str_to_html(Deep ^ data_file_name),
+    (
+        MaybeSubTitle = no,
+        Title = MainTitle
+    ;
+        MaybeSubTitle = yes(Subtitle),
+        Title = MainTitle ++ str_to_html(" - ") ++ str_to_html(Subtitle)
+    ),
+    TitleHTML = wrap_tags("<title>", "</title>", Title),
     deep_to_http_context(Deep, HTTPContext),
-    map_join_html("</div><div>", item_to_html(HTTPContext), Content, Body),
-    string.format(html_template, [s(Title), s(Body)], HTML).
+    map_join_html(item_to_html("<div>\n", "</div>\n", HTTPContext),
+        Items, ItemsHTML),
+    HTML = doc_type_html ++
+        wrap_tags("<html>", "</html>",
+            wrap_tags("<head>", "</head>", TitleHTML ++ css_style_html) ++
+            wrap_tags("<body>", "</body>", ItemsHTML)
+        ).
+
+:- func doc_type_html = html.
+
+doc_type_html =
+    str_to_html(
+        "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"
+        \"http://www.w3.org/TR/html4/strict.dtd\">").
 
-:- func html_template = string.
-html_template = 
-"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01//EN""
-""http://www.w3.org/TR/html4/strict.dtd"">
-<html>
-    <head>
-        <title>%s</title>
+:- func css_style_html = html.
+
+css_style_html =
+    str_to_html("
         <style type=\"text/css\">
             td.allocations
             {
@@ -257,74 +284,79 @@
                 border-style: inset inset inset inset;
             }
         </style>
-    </head>
-    <body>
-    <div>
-    %s
-    </div>
-    </body>
-</html>".
+").
 
 %-----------------------------------------------------------------------------%
     
     % Convert a display item into a HTML snippet.
     %
-:- pred item_to_html(http_context::in, display_item::in, string::out) is det.
-
-item_to_html(_, display_message(Message), HTML) :-
-    HTML = "<h3>" ++ Message ++ "</h3>\n".
-
-item_to_html(HTTPContext, display_table(Table), HTML) :-
-    table_to_html(HTTPContext, Table, HTML).
+:- func item_to_html(string, string, http_context, display_item) = html.
 
-item_to_html(HTTPContext, display_list(Class, MaybeTitle, Items), HTML) :-
-    some [!HTML]
+item_to_html(StartTag, EndTag, HTTPContext, Item) = HTML :-
     (
+        Item = display_message(Message),
+        HTML = wrap_tags(StartTag, EndTag,
+            wrap_tags("<h3>", "</h3>\n", str_to_html(Message)))
+    ;
+        Item = display_command_link(DeepLink),
+        HTML = wrap_tags(StartTag, EndTag,
+            link_to_html(HTTPContext, DeepLink))
+    ;
+        Item = display_table(Table),
+        HTML = wrap_tags(StartTag, EndTag,
+            table_to_html(HTTPContext, Table))
+    ;
+        Item = display_list(Class, MaybeTitle, Items),
         (
             MaybeTitle = yes(Title),
-            !:HTML = "<span id=""list_title"">" ++ Title ++ "</span>",
+            TitleStartTag = "<span id=\"list_title\">",
+            TitleEndTag = "</span>",
+            TitleHTML = wrap_tags(TitleStartTag, TitleEndTag,
+                str_to_html(Title)),
             (
-                Class = list_class_vertical_bullets
+                Class = list_class_vertical_bullets,
+                PostTitleHTML = empty_html
             ;
                 ( Class = list_class_horizontal
-                ; Class = list_class_vertical_no_bullets ),
-                !:HTML = !.HTML ++ "<br>"
+                ; Class = list_class_vertical_no_bullets
+                ),
+                PostTitleHTML = str_to_html("<br>")
             )
         ;
             MaybeTitle = no,
-            !:HTML = ""
-        ),
-        (
-            Class = list_class_vertical_bullets,
-            Delim = "</li>\n<li>",
-            !:HTML = !.HTML ++ "<ul><li>"
-        ;
-            Class = list_class_vertical_no_bullets,
-            Delim = "<br>"
-        ;
-            Class = list_class_horizontal,
-            Delim = " "
+            TitleHTML = empty_html,
+            PostTitleHTML = empty_html
         ),
-        map_join_html(Delim, item_to_html(HTTPContext), Items, HTML_Items),
-        !:HTML = !.HTML ++ HTML_Items,
         (
             Class = list_class_vertical_bullets,
-            HTML_End = "</li></ul>\n"
+            OutsideStartTag = "<ul>",
+            OutsideEndTag = "<ul>\n",
+            InnerStartTag = "<li>",         % XXX add \n?
+            InnerEndTag = "</li>\n",
+            Separator = empty_html
         ;
             Class = list_class_vertical_no_bullets,
-            HTML_End = "<br>\n"
+            OutsideStartTag = "",
+            OutsideEndTag = "\n",
+            InnerStartTag = "",
+            InnerEndTag = "",               % XXX add \n?
+            Separator = str_to_html("<br>\n")
         ;
             Class = list_class_horizontal,
-            HTML_End = "\n"
-        ),
-        !:HTML = !.HTML ++ HTML_End, 
-        HTML = !.HTML
+            OutsideStartTag = "",
+            OutsideEndTag = "\n",
+            InnerStartTag = "",
+            InnerEndTag = "",
+            Separator = str_to_html(" ")
+        ),
+        sep_map_join_html(Separator,
+            item_to_html(InnerStartTag, InnerEndTag, HTTPContext), Items,
+            InnerItemsHTML),
+        ItemsHTML = wrap_tags(OutsideStartTag, OutsideEndTag, InnerItemsHTML),
+        HTML = wrap_tags(StartTag, EndTag,
+            TitleHTML ++ PostTitleHTML ++ ItemsHTML)
     ).
 
-item_to_html(HTTPContext, display_command_link(DeepLink), HTML) :-
-    link_to_html(HTTPContext, DeepLink, HTML).
-
-
 %-----------------------------------------------------------------------------%
 %
 % Table htmlization.
@@ -333,8 +365,8 @@
     % The number of rows to be used for a table header.
     %
 :- type table_header_rows
-    --->    one
-    ;       two.
+    --->    one_header_row
+    ;       two_header_rows.
 
     % A mapping of column numbers to classes.
     %
@@ -344,99 +376,111 @@
 
     % Create a HTML table entity from the given table description.
     %
-:- pred table_to_html(http_context::in, table::in, string::out) is det.
+:- func table_to_html(http_context, table) = html.
 
-table_to_html(HTTPContext, table(Class, NumCols, MaybeHeader, Rows), HTML) :-
-    table_class_to_string(Class, ClassStr),
-    Open = "<table class=\"" ++ ClassStr ++ "\">\n",
-    Close = "</table>\n",
+table_to_html(HTTPContext, Table) = HTML :-
+    Table = table(Class, NumCols, MaybeHeader, BodyRows),
+
+    ClassStr = table_class_to_string(Class),
+    TableStartTag = "<table class=\"" ++ ClassStr ++ "\">\n",
+    TableEndTag = "</table>\n",
     
     % Build a header row.
     (
         MaybeHeader = yes(table_header(THCells)),
-        foldl3(table_header_num_rows_and_classmap, THCells, one, THNumRows,
-            0, _, map.init, ClassMap),
+        list.foldl3(table_header_num_rows_and_classmap, THCells,
+            one_header_row, THNumRows, 0, _, map.init, ClassMap),
         MaybeClassMap = yes(ClassMap),
         map_join_html(table_header_cell_to_html_row_1(HTTPContext, THNumRows), 
-            THCells, HeaderHTML0),
-        HeaderHTML1 = "<tr>" ++ HeaderHTML0 ++ "</tr>\n",
+            THCells, InnerHeaderRowOneHTML),
+        HeaderRowOneHTML =
+            wrap_tags("<tr>", "</tr>\n", InnerHeaderRowOneHTML),
         (
-            THNumRows = one,
-            HeaderHTML2 = HeaderHTML1
+            THNumRows = one_header_row,
+            HeaderRowTwoHTML = empty_html
         ;
-            THNumRows = two,
+            THNumRows = two_header_rows,
             map_join_html(table_header_cell_to_html_row_2(HTTPContext),
-                THCells, HeaderHTML11),
-            HeaderHTML2 = HeaderHTML1 ++ "<tr>" ++ HeaderHTML11 ++ "</tr>\n"
-        ),
-        HeaderHTML = HeaderHTML2 ++ 
-            format("<tr><td colspan=\"%d\"/></tr>\n", [i(NumCols)])
+                THCells, InnerHeaderRowTwoHTML),
+            HeaderRowTwoHTML =
+                wrap_tags("<tr>", "</tr>\n", InnerHeaderRowTwoHTML)
+        ),
+        InnerHeaderRowThree =
+            string.format("<td colspan=\"%d\"/>", [i(NumCols)]),
+        HeaderRowThreeHTML =
+            wrap_tags("<tr>", "</tr>\n",  str_to_html(InnerHeaderRowThree)),
+        HeaderHTML = HeaderRowOneHTML ++ HeaderRowTwoHTML ++ HeaderRowThreeHTML
     ;
         MaybeHeader = no,
         MaybeClassMap = no,
-        HeaderHTML = ""
+        HeaderHTML = empty_html
     ),
 
     % Build the table rows.
-    map_join_html(table_row_to_html(HTTPContext, MaybeClassMap, NumCols), Rows,
-        RowsHTML),
+    map_join_html(table_row_to_html(HTTPContext, MaybeClassMap, NumCols),
+        BodyRows, BodyRowsHTML),
 
     % Construct the table.
-    HTML = Open ++ HeaderHTML ++ RowsHTML ++ Close.
+    HTML = wrap_tags(TableStartTag, TableEndTag, HeaderHTML ++ BodyRowsHTML).
 
 %-----------------------------------------------------------------------------%
 
     % Return the HTML entity for a table header cell.
     %
-:- pred table_header_cell_to_html_row_1(http_context::in,
-    table_header_rows::in, table_header_cell::in, string::out) is det.
+:- func table_header_cell_to_html_row_1(http_context,
+    table_header_rows, table_header_cell) = html.
 
-table_header_cell_to_html_row_1(HTTPContext, HeaderNumRows, Cell, HTML) :-
+table_header_cell_to_html_row_1(HTTPContext, HeaderNumRows, Cell) = HTML :-
     (
         Cell = table_header_cell(Contents, Class),
         (
-            HeaderNumRows = one,
+            HeaderNumRows = one_header_row,
             RowSpan = "1"
         ;
-            HeaderNumRows = two,
+            HeaderNumRows = two_header_rows,
             RowSpan = "2"
         ),
         ColSpan = "1",
-        table_data_to_string(HTTPContext, Contents, ContentsString)
+        ContentsHTML = table_data_to_html(HTTPContext, Contents)
     ;
         Cell = table_header_group(Title, SubHeaderCells, Class),
         RowSpan = "1",
-        length(SubHeaderCells, NumSubHeaderCells),
-        ColSpan = string(NumSubHeaderCells),
-        ContentsString = Title    
+        list.length(SubHeaderCells, NumSubHeaderCells),
+        ColSpan = string.int_to_string(NumSubHeaderCells),
+        ContentsHTML = str_to_html(Title)
     ),
 
     table_col_class_to_string(Class, ClassStr),
-    string.format("<th rowspan=\"%s\" colspan=\"%s\" class=\"%s\">", 
-        [s(RowSpan), s(ColSpan), s(ClassStr)], Open),
-    HTML = Open ++ ContentsString ++ "</th>".
+    StartTag = string.format("<th rowspan=\"%s\" colspan=\"%s\" class=\"%s\">",
+        [s(RowSpan), s(ColSpan), s(ClassStr)]),
+    EndTag = "</th>",
+    HTML = wrap_tags(StartTag, EndTag, ContentsHTML).
 
 %-----------------------------------------------------------------------------%
 
-:- pred table_header_cell_to_html_row_2(http_context::in,
-    table_header_cell::in, string::out) is det.
+:- func table_header_cell_to_html_row_2(http_context, table_header_cell)
+    = html.
 
-table_header_cell_to_html_row_2(_, table_header_cell(_, _), "").
-
-table_header_cell_to_html_row_2(HTTPContext,
-    table_header_group(_, Cells, Class), HTML) :-
-    map_join_html((pred(Cell0::in, Cell::out) is det :-
-            table_data_to_string(HTTPContext, Cell0, Cell1),
-            wrap_in_th_tags(Class, Cell1, Cell)),
-        Cells, HTML).
+table_header_cell_to_html_row_2(HTTPContext, HeaderCell) = HTML :-
+    (
+        HeaderCell = table_header_cell(_, _),
+        HTML = empty_html
+    ;
+        HeaderCell = table_header_group(_, Cells, Class),
+        map_join_html(table_data_to_th_html(HTTPContext, Class), Cells, HTML)
+    ).
 
 %-----------------------------------------------------------------------------%
 
-:- pred wrap_in_th_tags(table_col_class::in, string::in, string::out) is det.
+:- func table_data_to_th_html(http_context, table_col_class, table_data)
+    = html.
 
-wrap_in_th_tags(Class, In, Out) :-
+table_data_to_th_html(HTTPContext, Class, TableData) = HTML :-
     table_col_class_to_string(Class, ClassStr),
-    string.format("<th class\"%s\">%s</th>", [s(ClassStr), s(In)], Out).
+    TableDataHTML = table_data_to_html(HTTPContext, TableData),
+    StartTag = string.format("<th class=\"%s\">", [s(ClassStr)]),
+    EndTag = "</th>",
+    HTML = wrap_tags(StartTag, EndTag, TableDataHTML).
 
 %-----------------------------------------------------------------------------%
 
@@ -457,9 +501,9 @@
     ;
         Cell = table_header_group(_, Subtitles, Class),
         length(Subtitles, NumSubCols),
-        !:NumRows = two,
+        !:NumRows = two_header_rows,
         table_col_class_to_string(Class, ClassStr),
-        % fold_up is inclusive of the higher number,
+        % fold_up is inclusive of the higher number.
         fold_up(insert_col_classmap(ClassStr), 
             !.ColNum, !.ColNum + NumSubCols - 1, 
             !ClassMap)
@@ -478,64 +522,77 @@
 
     % Build a row of a HTML table from the table_row type.
     %
-:- pred table_row_to_html(http_context::in, maybe(col_class_map)::in, int::in,
-    table_row::in, string::out) is det.
-
-table_row_to_html(HTTPContext, _, NumCols,
-        table_section_header(Content), HTML) :-
-    table_data_to_string(HTTPContext, Content, Text),
-    string.format("<tr><td colspan=\"%d\">%s</td></tr>",
-        [i(NumCols), s(Text)], HTML).
+:- func table_row_to_html(http_context, maybe(col_class_map), int, table_row)
+    = html.
 
-table_row_to_html(HTTPContext, ColClassMap, _, table_row(Cells), HTML) :-
-    map_join_html_count(table_cell_to_html(HTTPContext, ColClassMap), 0, Cells,
-        "", HTML0),
-    HTML = "<tr>" ++ HTML0 ++ "</tr>".
+table_row_to_html(HTTPContext, MaybeColClassMap, NumCols, TableRow) = HTML :-
+    (
+        TableRow = table_section_header(Contents),
+        ContentsHTML = table_data_to_html(HTTPContext, Contents),
+        StartTag = string.format("<tr><td colspan=\"%d\">", [i(NumCols)]),
+        EndTag = "</td></tr>",
+        HTML = wrap_tags(StartTag, EndTag, ContentsHTML)
+    ;
+        TableRow = table_row(Cells),
+        map_join_html_count(table_cell_to_html(HTTPContext, MaybeColClassMap),
+            0, Cells, InnerHTML),
+        HTML = wrap_tags("<tr>", "</tr>", InnerHTML)
+    ).
 
 %-----------------------------------------------------------------------------%
 
-:- pred table_cell_to_html(http_context::in, maybe(col_class_map)::in, int::in,
-    table_cell::in, string::out) is det.
+:- func table_cell_to_html(http_context, maybe(col_class_map), int, table_cell)
+    = html.
 
-table_cell_to_html(_, _, _, table_empty_cell, "<td/>").
-
-table_cell_to_html(HTTPContext, MaybeClassMap, ColNum, table_cell(Data), HTML)
-        :-
+table_cell_to_html(HTTPContext, MaybeClassMap, ColNum, Cell) = HTML :-
+    (
+        Cell = table_empty_cell,
+        HTML = str_to_html("<td/>")
+    ;
+        Cell = table_cell(CellData),
     (
         MaybeClassMap = yes(ClassMap),
-        ( map.search(ClassMap, ColNum, ClassPrime) ->
-            ClassStr = ClassPrime
+            ( map.search(ClassMap, ColNum, ClassStrPrime) ->
+                ClassStr = ClassStrPrime
         ;
-            throw(software_error(string.format(
+                Msg = string.format(
                 "Class map had no class for col %d, check table structure",
-                [i(ColNum)])))
+                    [i(ColNum)]),
+                error(Msg)
         )
     ;
         MaybeClassMap = no,
-        ( table_data_class(Data, ClassP) ->
-            Class = ClassP
+            ( table_data_class(CellData, ClassPrime) ->
+                Class = ClassPrime
         ;
             Class = default_table_col_class
         ),
         table_col_class_to_string(Class, ClassStr)
     ),
-    table_data_to_string(HTTPContext, Data, Text),
-    string.format("<td class=\"%s\">%s</td>", [s(ClassStr), s(Text)], HTML). 
+        CellHTML = table_data_to_html(HTTPContext, CellData),
+        StartTag = string.format("<td class=\"%s\">", [s(ClassStr)]),
+        EndTag = "</td>",
+        HTML = wrap_tags(StartTag, EndTag, CellHTML)
+    ).
 
 %-----------------------------------------------------------------------------%
 
-:- pred table_data_to_string(http_context::in, table_data::in, string::out) 
-    is det.
-
-table_data_to_string(_, f(Float), two_decimal_fraction(Float)).
-table_data_to_string(_, i(Int), commas(Int)).
-table_data_to_string(HTTPCtxt, l(Link), HTML) :- 
-    link_to_html(HTTPCtxt, Link, HTML).
-table_data_to_string(_, m(Mem, Units, Decimals),
-    format_memory(Mem, Units, Decimals)).
-table_data_to_string(_, p(Percent), format_percent(Percent)).
-table_data_to_string(_, s(String), escape_break_html_string(String)).
-table_data_to_string(_, t(Time), format_time(Time)).
+:- func table_data_to_html(http_context, table_data) = html.
+
+table_data_to_html(_, f(Float)) =
+    str_to_html(two_decimal_fraction(Float)).
+table_data_to_html(_, i(Int)) =
+    str_to_html(commas(Int)).
+table_data_to_html(HTTPCtxt, l(Link)) =
+    link_to_html(HTTPCtxt, Link).
+table_data_to_html(_, m(Mem, Units, Decimals)) =
+    str_to_html(format_memory(Mem, Units, Decimals)).
+table_data_to_html(_, p(Percent)) =
+    str_to_html(format_percent(Percent)).
+table_data_to_html(_, s(String)) =
+    str_to_html(escape_break_html_string(String)).
+table_data_to_html(_, t(Time)) =
+    str_to_html(format_time(Time)).
 
     % This predicate is used when a table class map couldn't be built from the
     % header of the table (perhaps there was no header).  It it provides a
@@ -566,24 +623,14 @@
 table_col_class_to_string(table_col_class_proc, "proc").
 table_col_class_to_string(table_col_class_ticks_and_times, "ticks_and_times").
 
-:- pred table_class_to_string(table_class::in, string::out) is det.
-
-table_class_to_string(table_class_menu, "menu").
-table_class_to_string(table_class_top_procs, "top_procs").
+:- func table_class_to_string(table_class) = string.
 
-%-----------------------------------------------------------------------------%
-%
-% Link Related Predicates.
-%
-
-:- pred link_class_to_string(link_class::in, string::out) is det.
-
-link_class_to_string(link_class_link, "default").
-link_class_to_string(link_class_control, "control").
+table_class_to_string(table_class_menu) = "menu".
+table_class_to_string(table_class_top_procs) = "top_procs".
 
 %-----------------------------------------------------------------------------%
 
-    % Information about the HTTP session.  This is used to create HTTP links as
+    % Information about the HTTP session. This is used to create HTTP links
     % below.
     %
 :- type http_context
@@ -597,20 +644,21 @@
 
     % Transform a deep link into HTML.
     %
-:- pred link_to_html(http_context::in, deep_link::in, string::out) is det.
+:- func link_to_html(http_context, deep_link) = html.
 
-link_to_html(HTTPContext, deep_link(Cmd, MaybePrefs, Label, Class), HTML) :-
-    link_class_to_string(Class, ClassStr),
+link_to_html(HTTPContext, Link) = HTML :-
+    Link = deep_link(Cmd, MaybePrefs, Label, Class),
     deep_cmd_to_url(HTTPContext, Cmd, MaybePrefs, URL),
     (
         Class = link_class_control,
-        FormatString = "<a class=""%s"" href=""%s"">[%s]</a>"
+        FormatString = "<a class=\"control\" href=\"%s\">[%s]</a>"
     ;
         Class = link_class_link,
-        FormatString = "<a class=""%s"" href=""%s"">%s</a>"
+        FormatString = "<a class=\"link\" href=\"%s\">%s</a>"
     ),
     string.format(FormatString, 
-        [ s(ClassStr), s(URL), s(escape_break_html_string(Label)) ], HTML).
+        [s(URL), s(escape_break_html_string(Label))], HTMLStr),
+    HTML = str_to_html(HTMLStr).
 
 %-----------------------------------------------------------------------------%
 
@@ -636,7 +684,7 @@
     (
         MaybePrefs = no,
         string.format("http://%s%s?%s&%s", 
-            [ s(HostAndPort), s(Script), s(CmdStr), s(DataFile) ], URL)
+            [s(HostAndPort), s(Script), s(CmdStr), s(DataFile)], URL)
     ;
         MaybePrefs = yes(Prefs),
         PrefStr = preferences_to_string(Prefs),
@@ -647,78 +695,85 @@
 
 %-----------------------------------------------------------------------------%
 %
-% Generic html helper predicates.
+% Generic HTML helper predicates.
 %
 
-    % Join two HTML snippits with the given delimiter.
-    %
-:- pred html_join(string::in, string::in, string::in, string::out) is det.
+:- func wrap_tags(string, string, html) = html.
+
+wrap_tags(StartTag, EndTag, InnerHTML) =
+    str_to_html(StartTag) ++ InnerHTML ++ str_to_html(EndTag).
+
+:- func empty_html = html.
+
+empty_html = cord.empty.
+
+:- func nl_html = html.
 
-html_join(Delim, H1, H2, H) :-
-    H = string.append_list([H1, Delim, "\n", H2]).
+nl_html = str_to_html("\n").
+
+:- func str_to_html(string) = html.
+
+str_to_html(Str) = cord.singleton(Str).
 
 %-----------------------------------------------------------------------------%
 
-    % This predicate builds the concatentation of Acc and ASs where each AS
-    % is MapPred(A, AS), the Delim is placed between concatentated strings.
+    % For each A, compute S = MapFunc(A), and concatenate all Ss.
     %
-:- pred map_join_html_acc(string, pred(A, string), list(A), string, string).
-:- mode map_join_html_acc(in, pred(in, out) is det, in, in, out) is det.
+:- pred map_join_html((func(A) = html)::in, list(A)::in, html::out) is det.
 
-map_join_html_acc(_, _, [], Result, Result).
-map_join_html_acc(Delim, MapPred, [ X | XS ], Acc0, Out) :-
-    MapPred(X, Y),
-    html_join(Delim, Acc0, Y, Acc),
-    map_join_html_acc(Delim, MapPred, XS, Acc, Out).
+map_join_html(MapFunc, List, HTML) :-
+    sep_map_join_html(empty_html, MapFunc, List, HTML).
 
-    % For each A do MapPred(A, S) and return the concatenation of Ss
-    % seperated by Delim. 
+    % For each A, compute S = MapFunc(A), and concatenate all Ss
+    % after putting Separator between them.
     %
-:- pred map_join_html(string, pred(A, string), list(A), string).
-:- mode map_join_html(in, pred(in, out) is det, in, out) is det.
+:- pred sep_map_join_html(html::in, (func(A) = html)::in,
+    list(A)::in, html::out) is det.
 
-map_join_html(_, _, [], "").
-map_join_html(Delim, MapPred, [ X | XS ], Result) :-
-    MapPred(X, Str),
-    map_join_html_acc(Delim, MapPred, XS, Str, Result).
+sep_map_join_html(_, _, [], empty_html).
+sep_map_join_html(Separator, MapFunc, [Head | Tail], HTML) :-
+    HeadHTML = MapFunc(Head),
+    sep_map_join_html_acc(Separator, MapFunc, Tail, HeadHTML, HTML).
 
-    % For each A do MapPred(A, S) and concatenate all Ss.
-    %
-:- pred map_join_html(pred(A, string), list(A), string).
-:- mode map_join_html(pred(in, out) is det, in, out) is det.
+:- pred sep_map_join_html_acc(html::in, (func(A) = html)::in, list(A)::in,
+    html::in, html::out) is det.
 
-map_join_html(MapPred, List, Result) :-
-    map_join_html("", MapPred, List, Result).
+sep_map_join_html_acc(_, _, [], !HTML).
+sep_map_join_html_acc(Separator, MapFunc, [Head | Tail], !HTML) :-
+    HeadHTML = MapFunc(Head),
+    !:HTML = !.HTML ++ Separator ++ HeadHTML,
+    sep_map_join_html_acc(Separator, MapFunc, Tail, !HTML).
     
-    % This predicate is the same as above except that it passes an integer
-    % to the higher order call, the integer is incremented on each
-    % recursion.
+    % For each A, compute S = MapFunc(N, A), and concatenate all Ss.
+    % N is the ordinal number of the element in the list.
     %
-:- pred map_join_html_count(pred(int, A, string), int, list(A), string,
-    string).
-:- mode map_join_html_count(pred(in, in, out) is det, in, in, in, out) 
-    is det.
-
-map_join_html_count(_, _, [], Result, Result).
-map_join_html_count(MapPred, N, [ X | XS ], Acc0, Out) :-
-    MapPred(N, X, Y),
-    html_join("", Acc0, Y, Acc),
-    map_join_html_count(MapPred, N+1, XS, Acc, Out).
+:- pred map_join_html_count((func(int, A) = html)::in, int::in, list(A)::in,
+    html::out) is det.
 
-%-----------------------------------------------------------------------------%
+map_join_html_count(MapFunc, N, List, HTML) :-
+    sep_map_join_html_count(empty_html, MapFunc, N, List, HTML).
 
-    % Format a title for the given website.  It will be the common title,
-    % followed by an optional subtitle seperated by - 
+    % For each A, compute S = MapFunc(N, A), and concatenate all Ss
+    % after putting Separator between them.
+    % N is the ordinal number of the element in the list.
     %
-:- pred maybe_title_to_title(deep::in, maybe(string)::in, string::out) 
-    is det.  
+:- pred sep_map_join_html_count(html::in, (func(int, A) = html)::in,
+    int::in, list(A)::in, html::out) is det.
+
+sep_map_join_html_count(_, _, _, [], empty_html).
+sep_map_join_html_count(Separator, MapFunc, N, [Head | Tail], HTML) :-
+    HeadHTML = MapFunc(N, Head),
+    sep_map_join_html_count_acc(Separator, MapFunc, N + 1, Tail,
+        HeadHTML, HTML).
 
-maybe_title_to_title(Deep, yes(Subtitle), Title) :-
-    maybe_title_to_title(Deep, no, MainTitle),
-    Title = MainTitle ++ " - " ++ Subtitle.
+:- pred sep_map_join_html_count_acc(html::in, (func(int, A) = html)::in,
+    int::in, list(A)::in, html::in, html::out) is det.
 
-maybe_title_to_title(Deep, no, Title) :-
-    Title = "Mercury Deep Profile for " ++ Deep ^ data_file_name.
+sep_map_join_html_count_acc(_, _, _, [], !HTML).
+sep_map_join_html_count_acc(Separator, MapFunc, N, [Head | Tail], !HTML) :-
+    HeadHTML = MapFunc(N, Head),
+    !:HTML = !.HTML ++ Separator ++ HeadHTML,
+    sep_map_join_html_count_acc(Separator, MapFunc, N + 1, Tail, !HTML).
 
 %-----------------------------------------------------------------------------%
 %
@@ -1065,7 +1120,8 @@
         CallSeqs1Fields = Fields ^ callseqs_fields := no_callseqs,
         CallSeqs1Pref = Pref ^ pref_fields := CallSeqs1Fields,
         CallSeqs1Msg = "[No call sequence number info]",
-        CallSeqs1Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+        CallSeqs1Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(CallSeqs1Pref, Deep, Cmd)),
                 s(CallSeqs1Msg)])
     ),
@@ -1075,7 +1131,8 @@
         CallSeqs2Fields = Fields ^ callseqs_fields := callseqs,
         CallSeqs2Pref = Pref ^ pref_fields := CallSeqs2Fields,
         CallSeqs2Msg = "[Call sequence numbers]",
-        CallSeqs2Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+        CallSeqs2Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(CallSeqs2Pref, Deep, Cmd)),
                 s(CallSeqs2Msg)])
     ),
@@ -1085,7 +1142,8 @@
         CallSeqs3Fields = Fields ^ callseqs_fields := callseqs_and_percall,
         CallSeqs3Pref = Pref ^ pref_fields := CallSeqs3Fields,
         CallSeqs3Msg = "[Call sequence numbers including per-call]",
-        CallSeqs3Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+        CallSeqs3Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(CallSeqs3Pref, Deep, Cmd)),
                 s(CallSeqs3Msg)])
     ),
@@ -1122,8 +1180,10 @@
         Memory1Fields = Fields ^ memory_fields := no_memory,
         Memory1Pref = Pref ^ pref_fields := Memory1Fields,
         Memory1Msg = "[No memory info]",
-        Memory1Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(Memory1Pref, Deep, Cmd)), s(Memory1Msg)])
+        Memory1Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(deep_cmd_pref_to_url(Memory1Pref, Deep, Cmd)),
+                s(Memory1Msg)])
     ),
     ( Fields ^ memory_fields = memory(units_words) ->
         Memory2Toggle = ""
@@ -1131,8 +1191,10 @@
         Memory2Fields = Fields ^ memory_fields := memory(units_words),
         Memory2Pref = Pref ^ pref_fields := Memory2Fields,
         Memory2Msg = "[Words]",
-        Memory2Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(Memory2Pref, Deep, Cmd)), s(Memory2Msg)])
+        Memory2Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(deep_cmd_pref_to_url(Memory2Pref, Deep, Cmd)),
+                s(Memory2Msg)])
     ),
     ( Fields ^ memory_fields = memory(units_bytes) ->
         Memory3Toggle = ""
@@ -1140,8 +1202,10 @@
         Memory3Fields = Fields ^ memory_fields := memory(units_bytes),
         Memory3Pref = Pref ^ pref_fields := Memory3Fields,
         Memory3Msg = "[Bytes]",
-        Memory3Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(Memory3Pref, Deep, Cmd)), s(Memory3Msg)])
+        Memory3Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(deep_cmd_pref_to_url(Memory3Pref, Deep, Cmd)),
+                s(Memory3Msg)])
     ),
     ( Fields ^ memory_fields = memory_and_percall(units_words) ->
         Memory4Toggle = ""
@@ -1150,8 +1214,10 @@
             memory_and_percall(units_words),
         Memory4Pref = Pref ^ pref_fields := Memory4Fields,
         Memory4Msg = "[Words and per-call words]",
-        Memory4Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(Memory4Pref, Deep, Cmd)), s(Memory4Msg)])
+        Memory4Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(deep_cmd_pref_to_url(Memory4Pref, Deep, Cmd)),
+                s(Memory4Msg)])
     ),
     ( Fields ^ memory_fields = memory_and_percall(units_bytes) ->
         Memory5Toggle = ""
@@ -1160,16 +1226,20 @@
             memory_and_percall(units_bytes),
         Memory5Pref = Pref ^ pref_fields := Memory5Fields,
         Memory5Msg = "[Bytes and per-call bytes]",
-        Memory5Toggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(Memory5Pref, Deep, Cmd)), s(Memory5Msg)])
+        Memory5Toggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(deep_cmd_pref_to_url(Memory5Pref, Deep, Cmd)),
+                s(Memory5Msg)])
     ),
     ( Fields = default_fields(Deep) ->
         DefaultToggle = ""
     ;
         DefaultMsg  = "[Restore defaults]",
         DefaultPref = Pref ^ pref_fields := default_fields(Deep),
-        DefaultToggle = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(DefaultPref, Deep, Cmd)), s(DefaultMsg)])
+        DefaultToggle =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(deep_cmd_pref_to_url(DefaultPref, Deep, Cmd)),
+                s(DefaultMsg)])
     ),
     HTML =
         "<strong>Toggle fields:</strong>\n" ++
@@ -1481,7 +1551,8 @@
         ; CostKind = cost_words
         ),
         MsgCallSeqs = "[Sort by call sequence numbers]",
-        ToggleCallSeqs = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+        ToggleCallSeqs =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
             [s(UpdateCriteria(cost_callseqs, InclDesc, Scope)),
                 s(MsgCallSeqs)])
     ;
@@ -1496,8 +1567,10 @@
         ; CostKind = cost_words
         ),
         MsgAllocs = "[Sort by allocations]",
-        ToggleAllocs = string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
-            [s(UpdateCriteria(cost_allocs, InclDesc, Scope)), s(MsgAllocs)])
+        ToggleAllocs =
+            string.format("<A CLASS=""button"" HREF=""%s"">%s</A>\n",
+                [s(UpdateCriteria(cost_allocs, InclDesc, Scope)),
+                s(MsgAllocs)])
     ;
         CostKind = cost_allocs,
         ToggleAllocs = ""
Index: deep_profiler/interface.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/interface.m,v
retrieving revision 1.20
diff -u -b -r1.20 interface.m
--- deep_profiler/interface.m	18 Apr 2008 05:57:48 -0000	1.20
+++ deep_profiler/interface.m	3 Aug 2008 13:02:52 -0000
@@ -172,124 +172,155 @@
     ).
 
 send_term(ToPipeName, Debug, Data, !IO) :-
-    io.open_output(ToPipeName, Res, !IO),
+    io.open_output(ToPipeName, ToPipeRes, !IO),
     (
-        Res = ok(ToStream),
+        ToPipeRes = ok(ToStream),
         io.write(ToStream, Data, !IO),
         io.write_string(ToStream, ".\n", !IO),
         io.close_output(ToStream, !IO)
     ;
-        Res = error(_),
-        error("send_term: couldn't open pipe")
+        ToPipeRes = error(ToPipeError),
+        io.error_message(ToPipeError, ToPipeErrorMsg),
+        string.format("send_term: couldn't open pipe %s: %s",
+            [s(ToPipeName), s(ToPipeErrorMsg)], ToPipeMsg),
+        error(ToPipeMsg)
     ),
     (
         Debug = yes,
-        io.open_output("/tmp/.send_term", Res2, !IO),
+        DebugFileName = "/tmp/.send_term",
+        io.open_output(DebugFileName, DebugRes, !IO),
         (
-            Res2 = ok(DebugStream),
+            DebugRes = ok(DebugStream),
             io.write(DebugStream, Data, !IO),
             io.write_string(DebugStream, ".\n", !IO),
             io.close_output(DebugStream, !IO)
         ;
-            Res2 = error(_),
-            error("send_term: couldn't debug")
+            DebugRes = error(DebugError),
+            io.error_message(DebugError, DebugErrorMsg),
+            string.format("send_term: couldn't open debug file %s: %s",
+                [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+            error(DebugMsg)
         )
     ;
         Debug = no
     ).
 
 send_string(ToPipeName, Debug, Data, !IO) :-
-    io.open_output(ToPipeName, Res, !IO),
+    io.open_output(ToPipeName, ToPipeRes, !IO),
     (
-        Res = ok(ToStream),
+        ToPipeRes = ok(ToStream),
         io.write_string(ToStream, Data, !IO),
         io.close_output(ToStream, !IO)
     ;
-        Res = error(_),
-        error("send_string: couldn't open pipe")
+        ToPipeRes = error(ToPipeError),
+        io.error_message(ToPipeError, ToPipeErrorMsg),
+        string.format("send_term: couldn't open pipe %s: %s",
+            [s(ToPipeName), s(ToPipeErrorMsg)], ToPipeMsg),
+        error(ToPipeMsg)
     ),
     (
         Debug = yes,
-        io.open_output("/tmp/.send_string", Res2, !IO),
+        DebugFileName = "/tmp/.send_string",
+        io.open_output(DebugFileName, DebugRes, !IO),
         (
-            Res2 = ok(DebugStream),
+            DebugRes = ok(DebugStream),
             io.write_string(DebugStream, Data, !IO),
             io.close_output(DebugStream, !IO)
         ;
-            Res2 = error(_),
-            error("send_string: couldn't debug")
+            DebugRes = error(DebugError),
+            io.error_message(DebugError, DebugErrorMsg),
+            string.format("send_term: couldn't open debug file %s: %s",
+                [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+            error(DebugMsg)
         )
     ;
         Debug = no
     ).
 
 recv_term(FromPipeName, Debug, Resp, !IO) :-
-    io.open_input(FromPipeName, Res0, !IO),
+    io.open_input(FromPipeName, FromPipeRes, !IO),
     (
-        Res0 = ok(FromStream),
-        io.read(FromStream, Res1, !IO),
+        FromPipeRes = ok(FromStream),
+        io.read(FromStream, ReadRes, !IO),
         (
-            Res1 = ok(Resp0),
-            Resp = Resp0
+            ReadRes = ok(Resp)
         ;
-            Res1 = eof,
-            error("recv_term: read failed")
+            ReadRes = eof,
+            error("recv_term: read failed: premature eof")
         ;
-            Res1 = error(_, _),
-            error("recv_term: read failed")
+            ReadRes = error(ReadErrorMsg, ReadErrorLineNumber),
+            string.format("recv_term: read failed at line %d: %s",
+                [i(ReadErrorLineNumber), s(ReadErrorMsg)], ReadMsg),
+            error(ReadMsg)
         ),
         io.close_input(FromStream, !IO),
         (
             Debug = yes,
-            io.open_output("/tmp/.recv_term", Res2, !IO),
+            DebugFileName = "/tmp/.recv_term",
+            io.open_output(DebugFileName, DebugRes, !IO),
             (
-                Res2 = ok(DebugStream),
-                io.write(DebugStream, Res1, !IO),
+                DebugRes = ok(DebugStream),
+                io.write(DebugStream, ReadRes, !IO),
                 io.write_string(DebugStream, ".\n", !IO),
                 io.close_output(DebugStream, !IO)
             ;
-                Res2 = error(_),
-                error("recv_term: couldn't debug")
+                DebugRes = error(DebugError),
+                io.error_message(DebugError, DebugErrorMsg),
+                string.format("recv_term: couldn't open debug file %s: %s",
+                    [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+                error(DebugMsg)
             )
         ;
             Debug = no
         )
     ;
-        Res0 = error(_),
-        error("recv_term: couldn't open pipe")
+        FromPipeRes = error(FromPipeError),
+        io.error_message(FromPipeError, FromPipeErrorMsg),
+        string.format("recv_term: couldn't open pipe %s: %s",
+            [s(FromPipeName), s(FromPipeErrorMsg)], FromPipeMsg),
+        error(FromPipeMsg)
     ).
 
 recv_string(FromPipeName, Debug, Resp, !IO) :-
-    io.open_input(FromPipeName, Res0, !IO),
+    io.open_input(FromPipeName, FromPipeRes, !IO),
     (
-        Res0 = ok(FromStream),
-        io.read_file_as_string(FromStream, Res1, !IO),
+        FromPipeRes = ok(FromStream),
+        io.read_file_as_string(FromStream, ReadRes, !IO),
         (
-            Res1 = ok(Resp0),
-            Resp = Resp0
+            ReadRes = ok(Resp)
         ;
-            Res1 = error(_, _),
-            error("recv_string: read failed")
+            ReadRes = error(_, ReadError),
+            io.error_message(ReadError, ReadErrorMsg),
+            string.format("recv_string: read failed: %s",
+                [s(ReadErrorMsg)], ReadMsg),
+            error(ReadMsg)
         ),
         io.close_input(FromStream, !IO),
         (
             Debug = yes,
-            io.open_output("/tmp/.recv_string", Res2, !IO),
+            DebugFileName = "/tmp/.recv_string",
+            io.open_output(DebugFileName, DebugRes, !IO),
             (
-                Res2 = ok(DebugStream),
-                io.write(DebugStream, Res1, !IO),
+                DebugRes = ok(DebugStream),
+                io.write(DebugStream, ReadRes, !IO),
                 io.write_string(DebugStream, ".\n", !IO),
                 io.close_output(DebugStream, !IO)
             ;
-                Res2 = error(_),
-                error("recv_string: couldn't debug")
+                DebugRes = error(DebugError),
+                io.error_message(DebugError, DebugErrorMsg),
+                string.format("recv_string: couldn't open debug file %s: %s",
+                    [s(DebugFileName), s(DebugErrorMsg)], DebugMsg),
+                error(DebugMsg)
             )
         ;
             Debug = no
         )
     ;
-        Res0 = error(_),
-        error("recv_term: couldn't open pipe")
+        FromPipeRes = error(FromPipeError),
+        io.error_message(FromPipeError, FromPipeErrorMsg),
+        string.format("recv_string: couldn't open pipe %s: %s",
+            [s(FromPipeName), s(FromPipeErrorMsg)], FromPipeMsg),
+        error(FromPipeMsg)
     ).
 
 %-----------------------------------------------------------------------------%
Index: deep_profiler/mdprof_cgi.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_cgi.m,v
retrieving revision 1.22
diff -u -b -r1.22 mdprof_cgi.m
--- deep_profiler/mdprof_cgi.m	18 Apr 2008 05:57:48 -0000	1.22
+++ deep_profiler/mdprof_cgi.m	3 Aug 2008 14:09:49 -0000
@@ -378,7 +378,7 @@
         release_lock(Debug, MutexFile, !IO),
         remove_want_file(WantFile, !IO),
         io.set_exit_status(1, !IO),
-        io.format("error reading data file: %s\n", [s(Error)], !IO)
+        io.format("error reading %s: %s\n", [s(FileName), s(Error)], !IO)
     ).
 
     % Become the new server. Delete the mutex and want files when we get out
Index: deep_profiler/mdprof_dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_dump.m,v
retrieving revision 1.9
diff -u -b -r1.9 mdprof_dump.m
--- deep_profiler/mdprof_dump.m	5 Mar 2008 05:05:49 -0000	1.9
+++ deep_profiler/mdprof_dump.m	3 Aug 2008 14:16:29 -0000
@@ -102,7 +102,6 @@
 % Option processing
 %
 
-
     % Process options and the list of arrays to be dumped.
     %
 :- pred make_dump_options(option_table(option)::in, maybe(dump_options)::out)
@@ -119,15 +118,12 @@
         Restrict = show_complete_dump
     ),
     DumpOptions0 = default_dump_options ^ do_restricted := Restrict, 
-    (
-        dump_array_options(ArrayOptionStrs, ArrayOptions) 
-    ->
+    ( dump_array_options(ArrayOptionStrs, ArrayOptions) ->
         MaybeDumpOptions = yes(DumpOptions0 ^ do_arrays := ArrayOptions)
     ;
         MaybeDumpOptions = no
     ).
 
-
 :- type option
     --->    help
     ;       dump_options
@@ -190,7 +186,6 @@
     "\t-D prop\n" ++
     "\t\tDump propagated measurement information.\n".
 
-
 %----------------------------------------------------------------------------%
 :- end_module mdprof_dump.
 %----------------------------------------------------------------------------%
Index: deep_profiler/mdprof_feedback.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_feedback.m,v
retrieving revision 1.6
diff -u -b -r1.6 mdprof_feedback.m
--- deep_profiler/mdprof_feedback.m	30 Jul 2008 04:32:08 -0000	1.6
+++ deep_profiler/mdprof_feedback.m	3 Aug 2008 14:16:34 -0000
@@ -40,6 +40,7 @@
 
 :- import_module array.
 :- import_module bool.
+:- import_module cord.
 :- import_module char.
 :- import_module getopt.
 :- import_module int.
@@ -76,34 +77,37 @@
         ->
             write_help_message(ProgName, !IO)
         ; 
-            ProfileProgName \= "",
-            Args = [Input, Output],
+            % XXX What was the point of this test?
+            % ProfileProgName \= "",
+            Args = [InputFileName, OutputFileName],
             check_options(Options, RequestedFeedbackInfo)
         ->
             lookup_bool_option(Options, verbose, Verbose),
-            read_deep_file(Input, Verbose, MaybeDeep, !IO),
+            read_deep_file(InputFileName, Verbose, MaybeDeep, !IO),
             (
                 MaybeDeep = ok(Deep),
-                feedback.read_or_create(Output, Feedback0, !IO),
+                feedback.read_or_create(OutputFileName, Feedback0, !IO),
                 process_deep_to_feedback(RequestedFeedbackInfo, 
                     Deep, Feedback0, Feedback),
-                write_feedback_file(Output, ProfileProgName, Feedback,
+                write_feedback_file(OutputFileName, ProfileProgName, Feedback,
                     WriteResult, !IO),
                 (
                     WriteResult = ok
                 ;
                     ( WriteResult = open_error(Error)
-                    ; WriteResult = write_error(Error) ),
+                    ; WriteResult = write_error(Error)
+                    ),
                     io.error_message(Error, ErrorMessage),
-                    io.format("%s: %s\n", [s(Output), s(ErrorMessage)], !IO),
+                    io.format("%s: %s\n",
+                        [s(OutputFileName), s(ErrorMessage)], !IO),
                     io.set_exit_status(1, !IO)
                 )
             ;
                 MaybeDeep = error(Error),
                 io.stderr_stream(Stderr, !IO),
                 io.set_exit_status(1, !IO),
-                io.format(Stderr, "%s: error reading deep file: %s\n",
-                    [s(ProgName), s(Error)], !IO)
+                io.format(Stderr, "%s: error reading %s: %s\n",
+                    [s(ProgName), s(InputFileName), s(Error)], !IO)
             )   
         ;
             io.set_exit_status(1, !IO),
@@ -118,37 +122,48 @@
         write_help_message(ProgName, !IO)
     ).
 
+:- func help_message = string.
+
+help_message =
+"Usage: %s [<options>] <input> <output>
+    <input> must name a deep profiling data file.
+    <output> is the name of the file to be generated by this program.
+
+    You may specify the following general options:
+
+    --help      Generate this help message.
+    --version   Report the program's version number.
+    --verbose   Generate progress messages.
+    --program-name <name>
+                The name of the program that generated the profiling data.
+                This is stored in the feedback file.
+
+    The following options select sets of feedback information useful
+    for particular compiler optimizations.
+
+    --implicit-parallelism
+                Generate information that the compiler can use for automatic
+                parallelization.
+
+    The following options select specific types of feedback information
+    and parameterise them
+
+    --calls-above-threshold-sorted
+                A list of calls whose typical cost (in call sequence counts)
+                is above a given threshold. The next two options allow you
+                to specify the threshold and what 'typical' means.
+    --calls-above-threshold-sorted-threshold <value>
+                Set the threshold to <value>.
+    --calls-above-threshold-sorted-measure mean|median
+                mean: Use mean(call site dynamic cost) as the typical cost.
+                median: Use median(call site dynamic cost) as the typical cost.
+                The default is 'mean'.
+".
+
 :- pred write_help_message(string::in, io::di, io::uo) is det.
 
 write_help_message(ProgName, !IO) :- 
-    Message0 = [
-        "Usage: %s --program-name <ProgName> [<options>] <input> <output>",
-        "   <input> must name a deep profiling data file.",
-        "   <output> is the file generated by this program.",
-        "   You may specify the following options:",
-        "   --help      Generate this help message.",
-        "   --version   Report the program's version number.",
-        "   --verbose   Generate progress messages.",
-        "   --program-name <name>",
-        "               The name of the program that generated the",
-        "               profiling data.  This is stored in the",
-        "               feedback file",
-        "\nThe following options select sets of feedback information useful",
-        "for particular compiler optimizations",
-        "   --implicit-parallelism",
-        "\nThe following options select specific types of feedback",
-        "information and parameterise them",
-        "   --calls-above-threshold-sorted",
-        "               A list of calls whose typical cost (in call sequence",
-        "               counts is above a given threshold, the definition of",
-        "               'typical' may be specified.",
-        "   --calls-above-threshold-sorted-threshold <value>",
-        "               Set the threshold to <value>.",
-        "   --calls-above-threshold-sorted-measure mean|median",
-        "               mean : Use mean(call site dynamic cost), this is the",
-        "                      default.",
-        "               median : Use median(call site dynamic cost)."],
-    string.join_list("\n", Message0) ++ "\n" = Message,
+    Message = help_message,
     io.format(Message, [s(ProgName)], !IO).
 
 :- pred write_version_message(string::in, io::di, io::uo) is det.
@@ -163,8 +178,8 @@
 
     % Read a deep profiling data file.
     % 
-:- pred read_deep_file(string::in, bool::in,
-    maybe_error(deep)::out, io::di, io::uo) is det.
+:- pred read_deep_file(string::in, bool::in, maybe_error(deep)::out,
+    io::di, io::uo) is det.
 
 read_deep_file(Input, Verbose, MaybeProfile, !IO) :-
     server_name_port(Machine, !IO),
@@ -245,7 +260,7 @@
 construct_measure("median",     stat_median).
 
     % This type defines the set of feedback_types that are to be calculated and
-    % put into the feedback info file,  They should correspond with the values
+    % put into the feedback info file. They should correspond with the values
     % of feedback_type.
     %
 :- type requested_feedback_info 
@@ -260,7 +275,6 @@
                 threshold       :: int
             ).
 
-
     % Check all the command line options and return a well-typed representation
     % of the user's request.  Some command line options imply other options,
     % those implications are also handled here.
@@ -302,9 +316,7 @@
     option_table(option)::in, option_table(option)::out) is det.
 
 option_implies(Option, ImpliedOption, ImpliedValue, !Options) :-
-    (
-        lookup_bool_option(!.Options, Option, yes)
-    ->
+    ( lookup_bool_option(!.Options, Option, yes) ->
         svmap.set(ImpliedOption, bool(ImpliedValue), !Options)
     ;
         true
@@ -343,8 +355,9 @@
 css_list_above_threshold(Options, Deep, !Feedback) :-
     Options = calls_above_threshold_sorted_opts(MeasureType, Threshold),
     compute_css_list_above_threshold(0, Deep, Threshold, 
-        MeasureType, [], CSSList),
-    map(css_to_call(Deep), CSSList, Calls), 
+        MeasureType, cord.empty, AboveThresholdCSSCord),
+    AboveThresholdCSSs = cord.list(AboveThresholdCSSCord),
+    list.map(css_to_call(Deep), AboveThresholdCSSs, Calls),
     FeedbackData = feedback_data_calls_above_threshold_sorted(Threshold,
         MeasureType, Calls),
     FeedbackType = feedback_type_calls_above_threshold_sorted, 
@@ -354,11 +367,10 @@
     % exceed the given threshold.
     % 
 :- pred compute_css_list_above_threshold(int::in, deep::in, int::in, 
-    stat_measure::in, list(call_site_static)::in, 
-    list(call_site_static)::out) is det.
+    stat_measure::in,
+    cord(call_site_static)::in, cord(call_site_static)::out) is det.
 
-compute_css_list_above_threshold(Index, Deep, Threshold, Measure,
-        !CSSAcc) :-
+compute_css_list_above_threshold(Index, Deep, Threshold, Measure, !CSSCord) :-
     array.size(Deep ^ call_site_statics, Size),
     ( Index = Size ->
         true
@@ -387,12 +399,12 @@
         ),
         ( Callseqs >= Threshold ->
             CSS = array.lookup(Deep ^ call_site_statics, Index),
-            list.append(!.CSSAcc, [CSS], !:CSSAcc),
+            !:CSSCord = snoc(!.CSSCord, CSS),
             compute_css_list_above_threshold(Index + 1, Deep, Threshold, 
-                Measure, !CSSAcc)
+                Measure, !CSSCord)
         ;
             compute_css_list_above_threshold(Index + 1, Deep, Threshold, 
-                Measure, !CSSAcc)
+                Measure, !CSSCord)
         ) 
     ).
 
Index: deep_profiler/mdprof_test.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_test.m,v
retrieving revision 1.16
diff -u -b -r1.16 mdprof_test.m
--- deep_profiler/mdprof_test.m	17 Feb 2008 06:48:38 -0000	1.16
+++ deep_profiler/mdprof_test.m	3 Aug 2008 14:26:24 -0000
@@ -130,8 +130,8 @@
         ;
             Res = error(Error),
             io.set_exit_status(1, !IO),
-            io.format("%s: error reading data file: %s\n",
-                [s(ProgName), s(Error)], !IO)
+            io.format("%s: error reading %s: %s\n",
+                [s(ProgName), s(FileName), s(Error)], !IO)
         )
     ;
         io.set_exit_status(1, !IO),
@@ -176,8 +176,8 @@
     ;
         Res = error(Error),
         io.set_exit_status(1, !IO),
-        io.format("%s: error reading data file: %s\n",
-            [s(ProgName), s(Error)], !IO)
+        io.format("%s: error reading %s: %s\n",
+            [s(ProgName), s(FileName), s(Error)], !IO)
     ).
 
 %-----------------------------------------------------------------------------%
Index: deep_profiler/measurement_units.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/measurement_units.m,v
retrieving revision 1.1
diff -u -b -r1.1 measurement_units.m
--- deep_profiler/measurement_units.m	29 Jul 2008 01:43:00 -0000	1.1
+++ deep_profiler/measurement_units.m	2 Aug 2008 01:55:34 -0000
@@ -9,8 +9,8 @@
 % File: measurement_units.m.
 % Author: pbone.
 %
-% This module contains a memory, time and percentage abstract data types and
-% predicates and functions for using them.
+% This module contains abstract data types for representing memory, time
+% and percentages, and predicates and functions for operating on them.
 %
 %-----------------------------------------------------------------------------%
 
@@ -26,7 +26,7 @@
 % Memory
 %
 
-    % Units avalible for measuring memory in.
+    % Units for measuring memory.
     %
 :- type memory_units
     --->    units_words
@@ -51,8 +51,9 @@
 
 %-----------------------------------------------------------------------------%
 
-    % Division for memory units.  Use of this function may return continous
+    % Division for memory units. Use of this function may return fractions of
     % units.
+    %
 :- func (memory) / (int) = (memory) is det.
 
 %-----------------------------------------------------------------------------%
@@ -187,18 +188,20 @@
 
 %-----------------------------------------------------------------------------%
 
-percent(P) = percent_float(P) :-
-    ( (P >= 0.0, P =< 1.0) ->
-        true
+percent(P) = PF :-
+    (
+        0.0 =< P,
+        P =< 1.0
+    ->
+        PF = percent_float(P)
     ; 
-        throw(software_error(
-            "Percentage value out of range 0.0 to 1.0 (inclusive)"))
+        error("Percentage value out of range 0.0 to 1.0 (inclusive)")
     ).
 
 %-----------------------------------------------------------------------------%
 
 format_percent(percent_float(P)) = String :-
-    string.format("%.2f", [f(P*100.0)], String).
+    string.format("%.2f", [f(P * 100.0)], String).
 
 %-----------------------------------------------------------------------------%
 % 
@@ -234,7 +237,6 @@
 :- func pico = float.
 pico = 0.000000000001.
 
-%
 % TODO: When there is no resolution beyond 10ms since there is a clock tick
 % every 10ms, the decimal points on some of these numbers should not be shown.
 % However it's probably useful to show at least 2 decimal points when the value
@@ -242,7 +244,7 @@
 %
 % TODO: If the display system supports printing the greek letter mu, then it
 % should be used rather than the latin letter u.
-%
+
 format_time(time_sec(F)) = String :-
     ( F < nano ->
         % Print in ps.
@@ -267,7 +269,7 @@
 %
 
 commas(Num) = Str :-
-    string.format("%d", [i(Num)], Str0),
+    string.int_to_string(Num, Str0),
     add_commas_intstr(Str0, Str).
 
 %-----------------------------------------------------------------------------%
@@ -281,8 +283,8 @@
         add_commas_intstr(WholeString0, WholeString),
         Representation = WholeString ++ "." ++ FractionString
     ;
-        % If there are no decimal symbols in the number, try to work with it as
-        % an integer.
+        % If there are no decimal symbols in the number, try to work with it
+        % as an integer.
         SubStrings = [WholeString]
     ->
         add_commas_intstr(WholeString, Representation)
@@ -296,7 +298,7 @@
 
 add_commas_intstr(Str0, Str) :-
     string.to_char_list(Str0, Chars0),
-    reverse(Chars0, RevChars0),
+    list.reverse(Chars0, RevChars0),
     string.from_char_list(reverse(add_commas(RevChars0)), Str).
 
 :- func add_commas(list(char)) = list(char).
Index: deep_profiler/query.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/query.m,v
retrieving revision 1.21
diff -u -b -r1.21 query.m
--- deep_profiler/query.m	29 Jul 2008 01:43:00 -0000	1.21
+++ deep_profiler/query.m	3 Aug 2008 13:57:22 -0000
@@ -61,9 +61,9 @@
     ;       deep_cmd_module(string)
     ;       deep_cmd_top_procs(display_limit, cost_kind, include_descendants,
                 measurement_scope)
-    %
+
     % The following commands are for debugging.
-    %
+
     ;       deep_cmd_proc_static(int)
     ;       deep_cmd_proc_dynamic(int)
     ;       deep_cmd_call_site_static(int)
@@ -149,7 +149,6 @@
     ;       time_and_percall
     ;       ticks_and_time_and_percall.
 
-
 :- type callseqs_fields
     --->    no_callseqs
     ;       callseqs
@@ -301,7 +300,7 @@
 :- pred exec(cmd::in, preferences::in, deep::in, string::out,
     io::di, io::uo) is det.
 
-exec(Cmd, Prefs, Deep, HTML, !IO) :-
+exec(Cmd, Prefs, Deep, HTMLStr, !IO) :-
     ( Cmd = deep_cmd_quit
     ; Cmd = deep_cmd_timeout(_)
     ; Cmd = deep_cmd_restart
@@ -309,12 +308,12 @@
     ; Cmd = deep_cmd_top_procs(_, _, _, _)
     ),
     create_report(Cmd, Deep, Report),
-    display_report(Deep, Prefs, Report, Display),
-    htmlize_display(Deep, Display, HTML).
+    Display = report_to_display(Deep, Prefs, Report),
+    HTML = htmlize_display(Deep, Display),
+    HTMLStr = html_to_string(HTML).
 
 % Old deep profiler cgi code.  This should remain supported until all the deep
-% profiler reports have been updated to use the new datastructures.
-%
+% profiler reports have been updated to use the data structures in report.m.
 
 %exec(Cmd, Pref, Deep, HTML, !IO) :-
 %    Cmd = deep_cmd_menu,
@@ -667,7 +666,7 @@
             "Procedures above 1% threshold: words, self+descendants.")
             ++
         "<li>\n" ++
-        % 2M words is chosen arbitrary because it is 8MB on ia32
+        % 2M words is chosen because it is 8MB on ia32
         menu_item(Deep, Pref,
             deep_cmd_top_procs(threshold_value(float(1024 * 1024 * 2)), 
                 cost_words, self_and_desc, overall),
@@ -763,8 +762,7 @@
         table_end(Pref) ++
         page_footer(Cmd, Pref, Deep).
 
-:- func generate_proc_page(cmd, proc_static_ptr, preferences, deep)
-    = string.
+:- func generate_proc_page(cmd, proc_static_ptr, preferences, deep) = string.
 
 generate_proc_page(Cmd, PSPtr, Pref, Deep) =
     page_banner(Cmd, Pref) ++
Index: deep_profiler/read_profile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/read_profile.m,v
retrieving revision 1.23
diff -u -b -r1.23 read_profile.m
--- deep_profiler/read_profile.m	29 Jul 2008 23:58:00 -0000	1.23
+++ deep_profiler/read_profile.m	3 Aug 2008 14:26:43 -0000
@@ -118,26 +118,35 @@
     io::di, io::uo) is det.
 
 read_deep_id_string(Res, !IO) :-
-    read_n_byte_string(string.length(deep_id_string), Res0, !IO),
+    read_line(string.length(deep_id_string), LineRes, !IO),
     (
-        Res0 = ok(String),
-        ( String = deep_id_string ->
+        LineRes = ok(Line),
+        ( Line = deep_id_string ->
             Res = ok(deep_id_string)
+        ; string.prefix(Line, deep_id_prefix) ->
+            Res = error("version number mismatch")
         ;
             Res = error("not a deep profiling data file")
         )
     ;
-        Res0 = error(Err),
+        LineRes = error(Err),
         Res = error(Err)
     ).
 
+    % Return the string identifying a file as a deep profiling data file.
+    % This must the same string as the one written by the function
+    % MR_write_out_deep_id_string in runtime/mercury_deep_profiling.c.
+    %
 :- func deep_id_string = string.
 
-% This must the same string as the one written by MR_write_out_deep_id_string
-% in runtime/mercury_deep_profiling.c.
-
 deep_id_string = "Mercury deep profiler data version 5\n".
 
+    % Return the part of deep_id_string that is version independent.
+    %
+:- func deep_id_prefix = string.
+
+deep_id_prefix = "Mercury deep profiler data version".
+
 :- func init_deep(int, int, int, int, int, int, int, int, int, int, int)
     = initial_deep.
 
@@ -426,7 +435,6 @@
         ),
         Res, !IO).
 
-
 :- func raw_proc_id_to_string(string_proc_label) = string.
 
 raw_proc_id_to_string(str_special_proc_label(TypeName, TypeModule, _DefModule,
@@ -945,6 +953,46 @@
 
 %-----------------------------------------------------------------------------%
 
+:- pred read_line(int::in, maybe_error(string)::out, io::di, io::uo) is det.
+
+read_line(Limit, Res, !IO) :-
+    read_line_acc(Limit, [], Res, !IO).
+
+:- pred read_line_acc(int::in, list(char)::in, maybe_error(string)::out,
+    io::di, io::uo) is det.
+
+read_line_acc(Limit, !.RevChars, Res, !IO) :-
+    ( Limit > 0 ->
+        read_byte(ByteRes, !IO),
+        (
+            ByteRes = ok(Byte),
+            ( char.to_int(Char, Byte) ->
+                % Include the newline in the string.
+                !:RevChars = [Char | !.RevChars],
+                ( Char = '\n' ->
+                    list.reverse(!.RevChars, Chars),
+                    string.from_char_list(Chars, Str),
+                    Res = ok(Str)
+                ;
+                    read_line_acc(Limit - 1, !.RevChars, Res, !IO)
+                )
+            ;
+                Res = error("unexpected end of file")
+            )
+        ;
+            ByteRes = eof,
+            Res = error("unexpected end of file")
+        ;
+            ByteRes = error(Err),
+            io.error_message(Err, Msg),
+            Res = error(Msg)
+        )
+    ;
+        list.reverse(!.RevChars, Chars),
+        string.from_char_list(Chars, Str),
+        Res = ok(Str)
+    ).
+
 :- pred read_string(maybe_error(string)::out,
     io::di, io::uo) is det.
 
@@ -966,11 +1014,11 @@
     io::di, io::uo) is det.
 
 read_n_byte_string(Length, Res, !IO) :-
-    read_n_bytes(Length, Res1, !IO),
+    read_n_bytes(Length, NByteRes, !IO),
     (
-        Res1 = ok(Bytes),
+        NByteRes = ok(Bytes),
         (
-            map((pred(I::in, C::out) is semidet :- char.to_int(C, I)),
+            list.map((pred(I::in, C::out) is semidet :- char.to_int(C, I)),
                 Bytes, Chars)
         ->
             string.from_char_list(Chars, Str),
@@ -979,7 +1027,7 @@
             Res = error("string contained bad char")
         )
     ;
-        Res1 = error(Err),
+        NByteRes = error(Err),
         Res = error(Err)
     ),
     trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
@@ -991,14 +1039,13 @@
 :- pred read_ptr(ptr_kind::in, maybe_error(int)::out, io::di, io::uo) is det.
 
 read_ptr(_Kind, Res, !IO) :-
-    read_num1(0, Res, !IO),
+    read_num(Res, !IO),
     trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("ptr ", !IO),
         io.write(Res, !IO),
         io.write_string("\n", !IO)
     ).
 
-
 :- pred read_cp_type(maybe_error(cp_type)::out, io::di, io::uo) is det.
 
 read_cp_type(MaybeRes, !IO) :-
@@ -1012,37 +1059,35 @@
         MaybeRes = error(Msg)
     ).
 
-
 :- pred num_to_cp_type(int::in, cp_type::out) is det.
 
-:- pragma foreign_proc("C", num_to_cp_type(Int::in, CPType::out),
-    [will_not_call_mercury, thread_safe, promise_pure], "
-
+:- pragma foreign_proc("C",
+    num_to_cp_type(Int::in, CPType::out),
+    [will_not_call_mercury, thread_safe, promise_pure],
+"
         CPType = Int;
-
-    ").
-
+").
 
 :- pred read_num(maybe_error(int)::out, io::di, io::uo) is det.
 
 read_num(Res, !IO) :-
-    read_num1(0, Res, !IO),
+    read_num_acc(0, Res, !IO),
     trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("num ", !IO),
         io.write(Res, !IO),
         io.write_string("\n", !IO)
     ).
 
-:- pred read_num1(int::in, maybe_error(int)::out,
+:- pred read_num_acc(int::in, maybe_error(int)::out,
     io::di, io::uo) is det.
 
-read_num1(Num0, Res, !IO) :-
+read_num_acc(Num0, Res, !IO) :-
     read_byte(Res0, !IO),
     (
         Res0 = ok(Byte),
         Num1 = (Num0 << 7) \/ (Byte /\ 0x7F),
         ( Byte /\ 0x80 \= 0 ->
-            read_num1(Num1, Res, !IO)
+            read_num_acc(Num1, Res, !IO)
         ;
             Res = ok(Num1)
         )
@@ -1066,12 +1111,12 @@
     io::di, io::uo) is det.
 
 read_fixed_size_int(Res, !IO) :-
-    read_fixed_size_int1(fixed_size_int_bytes, 0, 0, Res, !IO).
+    read_fixed_size_int_acc(fixed_size_int_bytes, 0, 0, Res, !IO).
 
-:- pred read_fixed_size_int1(int::in, int::in, int::in, maybe_error(int)::out,
-    io::di, io::uo) is det.
+:- pred read_fixed_size_int_acc(int::in, int::in, int::in,
+    maybe_error(int)::out, io::di, io::uo) is det.
 
-read_fixed_size_int1(BytesLeft, Num0, ShiftBy, Res, !IO) :-
+read_fixed_size_int_acc(BytesLeft, Num0, ShiftBy, Res, !IO) :-
     ( BytesLeft =< 0 ->
         Res = ok(Num0)
     ;
@@ -1079,7 +1124,7 @@
         (
             Res0 = ok(Byte),
             Num1 = Num0 \/ ( Byte << ShiftBy),
-            read_fixed_size_int1(BytesLeft - 1, Num1, ShiftBy + 8, Res, !IO)
+            read_fixed_size_int_acc(BytesLeft - 1, Num1, ShiftBy + 8, Res, !IO)
         ;
             Res0 = error(Err),
             Res = error(Err)
@@ -1090,27 +1135,27 @@
     io::di, io::uo) is det.
 
 read_n_bytes(N, Res, !IO) :-
-    read_n_bytes(N, [], Res0, !IO),
+    read_n_bytes_acc(N, [], Res0, !IO),
     (
         Res0 = ok(Bytes0),
-        reverse(Bytes0, Bytes),
+        list.reverse(Bytes0, Bytes),
         Res = ok(Bytes)
     ;
         Res0 = error(Err),
         Res = error(Err)
     ).
 
-:- pred read_n_bytes(int::in, list(int)::in, maybe_error(list(int))::out,
+:- pred read_n_bytes_acc(int::in, list(int)::in, maybe_error(list(int))::out,
     io::di, io::uo) is det.
 
-read_n_bytes(N, Bytes0, Res, !IO) :-
+read_n_bytes_acc(N, RevBytes0, Res, !IO) :-
     ( N =< 0 ->
-        Res = ok(Bytes0)
+        Res = ok(RevBytes0)
     ;
         read_deep_byte(Res0, !IO),
         (
             Res0 = ok(Byte),
-            read_n_bytes(N - 1, [Byte | Bytes0], Res, !IO)
+            read_n_bytes_acc(N - 1, [Byte | RevBytes0], Res, !IO)
         ;
             Res0 = error(Err),
             Res = error(Err)
Index: deep_profiler/report.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/report.m,v
retrieving revision 1.1
diff -u -b -r1.1 report.m
--- deep_profiler/report.m	29 Jul 2008 01:43:00 -0000	1.1
+++ deep_profiler/report.m	3 Aug 2008 13:57:13 -0000
@@ -9,11 +9,11 @@
 % File: report.m.
 % Author: pbone.
 %
-% This module defined deep profiling reports.  Deep profiling reports are the
-% result of querying a Deep profile, a different query results in a different
-% type of report.  They are processed further by display_report.m and
-% html_format.m in order to create HTML output.  Other tools may make use of
-% the information in deep profiling reports.
+% This module defines deep profiling reports. Each report is the result of
+% querying a Deep.data file. Different queries result in different types
+% of reports. Reports can be converted into HTML by display_report.m and
+% html_format.m, but some tools may use the data structures constructed here
+% directly.
 %
 %-----------------------------------------------------------------------------%
 
@@ -26,7 +26,7 @@
 :- import_module measurement_units.
 :- import_module profile.
 % TODO: The data structures in query should be moved into a different module,
-% then this module may depend on those datastructures but not the rest of
+% then this module may depend on those data structures but not the rest of
 % query.
 :- import_module query.
 
@@ -39,7 +39,7 @@
     
     ;       report_menu(
                 % Statistics about the deep profiling data.  Gives simple
-                % information about the size of the program and it's runtime.
+                % information about the size of the program and its runtime.
                 % These statistics are displayed on the menu of the mdprof_cgi
                 % program.
 
@@ -54,31 +54,30 @@
                 num_clique      :: int
             )
     ;       report_top_procs(
-                % Information about the most expensive procedures.  ordering
-                % defines what measurements are used to select and order the
-                % procedures in this report.
+                % Information about the most expensive procedures. The ordering
+                % field defines what measurements are used to select and order
+                % the procedures in this report.
 
                 ordering        :: report_ordering,
-                top_procs       :: list(row_data(report_proc))
+                top_procs                   :: list(perf_row_data(report_proc))
             ).
 
-
-:- type row_data(T)
-    --->    row_data(
+:- type perf_row_data(T)
+    --->    perf_row_data(
                 % The item represented by this data row.
                 subject             :: T,
 
-                % Port counts
+                % Port counts.
                 calls               :: int,
                 exits               :: int,
                 fails               :: int,
                 redos               :: int,
                 excps               :: int,
 
-                % Clock ticks and times, Ticks are 'countable' so int is
-                % used.  Time is discrete and has units so a time type is
-                % used.  When percent is NaN because the total time for the
-                % program is close to zero the percent type will represent
+                % Clock ticks and times. We always use simple integers to
+                % represent clock ticks, whereas for time, we use more
+                % user-friendly units. When the total time for the program
+                % is close to zero, the percentage may be NaN representing
                 % 'not_applicable' or 'do not know'.
                 self_ticks          :: int,
                 self_time           :: time,
@@ -90,7 +89,7 @@
                 time_percent        :: percent,
                 time_percall        :: time,
                 
-                % Call sequence counts,
+                % Call sequence counts.
                 self_callseqs           :: int,
                 self_callseqs_percent   :: percent,
                 self_callseqs_percall   :: float,
@@ -99,7 +98,7 @@
                 callseqs_percent        :: percent,
                 callseqs_percall        :: float,
 
-                % Memory allocations,
+                % Memory allocations.
                 self_allocs         :: int,
                 self_allocs_percent :: percent,
                 self_allocs_percall :: float,
@@ -108,9 +107,10 @@
                 allocs_percent      :: percent,
                 allocs_percall      :: float,
 
-                % Memory used.  Since memory has a scale it's stored in a
-                % memory type.  Memory per call might not be an integer,
-                % perhaps a new type should be used here.
+                % Memory used. We try to use the most appropriate units
+                % for representing each given amount of memory.
+                % XXX Memory per call might not be an integer, so we should
+                % make sure that the memory type can represent fractions.
                 bytes_per_word      :: int,
                 self_mem            :: memory,
                 self_mem_percent    :: percent,
@@ -134,9 +134,8 @@
                 scope           :: measurement_scope
             ).
 
-
     % The representation of a procedure in the report structure, including
-    % information about its location in mercury source code.
+    % information about its location in Mercury source code.
     %
 :- type report_proc
     --->    report_proc(
Index: deep_profiler/startup.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/startup.m,v
retrieving revision 1.18
diff -u -b -r1.18 startup.m
Index: deep_profiler/timeout.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/timeout.m,v
retrieving revision 1.18
diff -u -b -r1.18 timeout.m
--- deep_profiler/timeout.m	1 Dec 2006 15:03:47 -0000	1.18
+++ deep_profiler/timeout.m	3 Aug 2008 14:34:24 -0000
@@ -23,6 +23,7 @@
 % created, but we don't want the parent process after the fork to delete them
 % while they are still in use by the child process. This is prevented by the
 % boolean flag process_is_detached_server.
+%
 %-----------------------------------------------------------------------------%
 
 :- module timeout.
Index: deep_profiler/top_procs.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/top_procs.m,v
retrieving revision 1.13
diff -u -b -r1.13 top_procs.m
--- deep_profiler/top_procs.m	18 Apr 2008 05:57:48 -0000	1.13
+++ deep_profiler/top_procs.m	3 Aug 2008 14:34:50 -0000
@@ -13,6 +13,7 @@
 %
 % For comparisons on costs, we sort highest first. For comparisons on names and
 % contexts, we sort lowest first. This is consistently what users want.
+%
 %-----------------------------------------------------------------------------%
 
 :- module top_procs.
Index: deep_profiler/util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/util.m,v
retrieving revision 1.7
diff -u -b -r1.7 util.m
--- deep_profiler/util.m	1 Dec 2006 15:03:47 -0000	1.7
+++ deep_profiler/util.m	3 Aug 2008 14:35:26 -0000
@@ -10,6 +10,7 @@
 % Authors: conway, zs.
 %
 % This module defines utility predicates for the CGI program.
+%
 %-----------------------------------------------------------------------------%
 
 :- module util.
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/base64
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/fixed
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_allegro
cvs diff: Diffing extras/graphics/mercury_allegro/examples
cvs diff: Diffing extras/graphics/mercury_allegro/samples
cvs diff: Diffing extras/graphics/mercury_allegro/samples/demo
cvs diff: Diffing extras/graphics/mercury_allegro/samples/mandel
cvs diff: Diffing extras/graphics/mercury_allegro/samples/pendulum2
cvs diff: Diffing extras/graphics/mercury_allegro/samples/speed
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/log4m
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/mopenssl
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/net
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/posix/samples
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
Index: mdbcomp/feedback.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/feedback.m,v
retrieving revision 1.1
diff -u -b -r1.1 feedback.m
--- mdbcomp/feedback.m	23 Jul 2008 23:20:34 -0000	1.1
+++ mdbcomp/feedback.m	3 Aug 2008 14:56:49 -0000
@@ -37,28 +37,32 @@
 %-----------------------------------------------------------------------------%
 
     % This type is used as a key for the data that may be fed back into the
-    % compiler.  When making changes to this structure be sure to increment the
-    % file format version number towards the bottom of this file.
+    % compiler.
+    %
+    % NOTE: When making changes to this structure, be sure to increment
+    % the file format version number towards the bottom of this file.
     %
 :- type feedback_type
     --->    feedback_type_calls_above_threshold_sorted.
-                % Feedback data of this type represents a list of
-                % calli sites sorted in decending order of mean/median
-                % call cost where that cost is greater than a given
-                % threshold.  Mean or median costs are used.
-               
+            % Feedback data of this type represents a list of call sites
+            % sorted in descending order of mean or median call cost where
+            % that cost is greater than a given threshold.
 
 %-----------------------------------------------------------------------------%
 
-    % This type stores the data that may be fed back into the compiler.  Each
-    % constructor here corresponds to a value of the above type.  When making
-    % changes to this structure or structures in mdbcomp.program_representation
-    % be sure to increment the file format version number towards the bottom of
-    % this file.
+    % This type stores the data that may be fed back into the compiler.
+    % Each constructor here corresponds to a constructor of the feedback_type
+    % type.
+    %
+    % TODO: We need a mechanism to ensure that the answer for a given query
+    % (a value of type feedback_type) is always the corresponding value
+    % in this type. The right solution would be to represent a query as
+    % a partially instantiated data structure that we later fill in,
+    % but Mercury doesn't yet let us do that.
     %
-    % TODO: Somehow need to constrain the instantiations of this type so that
-    % they are always paired with instantitations of the above type, and
-    % hopefuly the compiler can assert this.
+    % NOTE: When making changes to this structure or structures in
+    % mdbcomp.program_representation, be sure to increment the file format
+    % version number towards the bottom of this file.
     %
 :- type feedback_data
     --->    feedback_data_calls_above_threshold_sorted(
@@ -98,8 +102,8 @@
 
     % read_feedback_file(Path, FeedbackState, !IO)
     %
-    % This predicate reads in feedback data from a specified file.  It should
-    % be called once per compiler invocation.
+    % This predicate reads in feedback data from a specified file.
+    % It should be called once per compiler invocation.
     %
 :- pred read_feedback_file(string::in, 
     feedback_read_result(feedback_info)::out, io::di, io::uo) is det.
@@ -113,7 +117,8 @@
     ;       read_error(io.error)
     ;       parse_error(
                 message     :: string,
-                line_no     :: int)
+                line_no     :: int
+            )
     ;       unexpected_eof
     ;       incorrect_version
     ;       incorrect_first_line
@@ -178,9 +183,7 @@
 
 get_feedback_data(Type, MaybeData, Info) :-
     Info = feedback_info(Map),
-    (
-        map.search(Map, Type, Data)
-    ->
+    ( map.search(Map, Type, Data) ->
         MaybeData = yes(Data)
     ;
         MaybeData = no
@@ -205,10 +208,9 @@
         %
         IOResStream = ok(Stream),
         some [!Result] (
-            %
             % Read each part of the file and continue reading of this is
             % succesful.  read_cont takes care of this logic.
-            %
+
             read_check_line(feedback_first_line, incorrect_first_line, Stream, 
                 unit, !:Result, !IO),
             maybe_read(
@@ -226,9 +228,9 @@
         ReadResultFeedbackInfo = error(open_error(ErrorCode))
     ).
 
-    % If the result so far is successful, call the colsure and return it's
+    % If the result so far is successful, call the closure and return its
     % result.  Otherwise return the accumulated result without calling the
-    % colsure.
+    % closure.
     %
 :- pred maybe_read(pred(A, feedback_read_result(B), io, io), 
     feedback_read_result(A), feedback_read_result(B), io, io).
@@ -256,7 +258,8 @@
         IOResultLine = ok(Line),
         (
             ( Line = TestLine
-            ; Line = TestLine ++ "\n")
+            ; Line = TestLine ++ "\n"
+            )
         ->
             Result = ok(unit)
         ;
@@ -324,7 +327,8 @@
 read_error_message_string(File, Error, Message) :-
     (
         ( Error = open_error(Code)
-        ; Error = read_error(Code) ),
+        ; Error = read_error(Code)
+        ),
         error_message(Code, MessagePart)
     ;
         Error = parse_error(ParseMessage, Line),
@@ -340,7 +344,8 @@
         MessagePart = "Incorrect file format"
     ;
         Error = incorrect_program_name,
-        MessagePart = "Program name didn't match, is this the right feedback file?"
+        MessagePart =
+            "Program name didn't match, is this the right feedback file?"
     ),
     string.format("%s: %s\n", [s(File), s(MessagePart)], Message).
 
@@ -363,20 +368,18 @@
     io.open_output(Path, OpenRes, !IO),
     (
         OpenRes = ok(Stream),
-        promise_equivalent_solutions [!:IO, ExcpRes] 
-            try_io(write2(Stream, ProgName, Feedback), ExcpRes, !IO),
+        promise_equivalent_solutions [!:IO, ExcpRes] (
+            try_io(write_feedback_file_2(Stream, ProgName, Feedback),
+                ExcpRes, !IO)
+        ),
         (
             ExcpRes = succeeded(_),
             Res = ok
         ;
             ExcpRes = exception(ExcpUniv),
             
-            %
-            % If the exception is not a type we exected then re-throw it.
-            %
-            (
-                univ_to_type(ExcpUniv, Excp)
-            ->
+            % If the exception is not of a type we expected, then re-throw it.
+            ( univ_to_type(ExcpUniv, Excp) ->
                 Res = write_error(Excp)
             ;
                 rethrow(ExcpRes)
@@ -387,13 +390,14 @@
         Res = open_error(ErrorCode)
     ). 
 
-    % Write out the data.  This is called by try IO to catch any exceptions
-    % that close_output and other predicates may throw.
+    % Write out the data. This is called by try_io to catch any exceptions
+    % that close_output and the other predicates we call here (e.g. io.write)
+    % may throw.
     %
-:- pred write2(output_stream::in, string::in, feedback_info::in, unit::out, 
-    io::di, io::uo) is det.
+:- pred write_feedback_file_2(output_stream::in, string::in, feedback_info::in,
+    unit::out, io::di, io::uo) is det.
 
-write2(Stream, ProgName, Feedback, unit, !IO) :-
+write_feedback_file_2(Stream, ProgName, Feedback, unit, !IO) :-
     io.write_string(Stream, feedback_first_line, !IO),
     io.nl(Stream, !IO),
     io.write_string(Stream, feedback_version, !IO),
Index: mdbcomp/prim_data.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/prim_data.m,v
retrieving revision 1.29
diff -u -b -r1.29 prim_data.m
Index: mdbcomp/trace_counts.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/mdbcomp/trace_counts.m,v
retrieving revision 1.22
diff -u -b -r1.22 trace_counts.m
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
cvs diff: Diffing runtime/GETOPT
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/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/standalone_c
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/solver_types
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing slice
cvs diff: Diffing ssdb
cvs diff: Diffing tests
cvs diff: Diffing tests/analysis
cvs diff: Diffing tests/analysis/ctgc
cvs diff: Diffing tests/analysis/excp
cvs diff: Diffing tests/analysis/ext
cvs diff: Diffing tests/analysis/sharing
cvs diff: Diffing tests/analysis/table
cvs diff: Diffing tests/analysis/trail
cvs diff: Diffing tests/analysis/unused_args
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list