[m-rev.] For review: Re-organize deep profilier tools modules.

Paul Bone pbone at csse.unimelb.edu.au
Fri Apr 18 12:49:57 AEST 2008


For review by anyone.

Estimated Hours Taken: 1
Branches: main

Tidying up some of the deep profiler tools code.  Moved data structures,
predicates and functions that are not specific to the mdprof_cgi program
from interface.m to other modules.

deep_profilier/query.m:
    Moved data structures from interface.m to query.m including the cmd and
    preferences data structures.
    Renamed functions to replace url_compoent with string.

deep_profilier/interface.m:
    Moved code from this module that doesn't relate to the mdprof_cgi
    program's client-server nature to query.m and html_format.m
    Conformed to predicate-renaming changes in query.m

deep_profilier/html_format.m:
    Moved machine_datafile_cmd_pref_to_url function to this module.
    Conform to changes in interface.m and query.m.

deep_profiler/top_procs.m:
    Conform to changes in interface.m and query.m.


Index: deep_profiler/html_format.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/html_format.m,v
retrieving revision 1.20
diff -u -u -r1.20 html_format.m
--- deep_profiler/html_format.m	2 Jul 2007 10:04:07 -0000	1.20
+++ deep_profiler/html_format.m	18 Apr 2008 02:41:35 -0000
@@ -17,9 +17,9 @@
 :- module html_format.
 :- interface.
 
-:- import_module interface.
 :- import_module measurements.
 :- import_module profile.
+:- import_module query.
 :- import_module top_procs.
 
 :- import_module bool.
@@ -2352,5 +2352,21 @@
 zero_width_space = "<wbr />".
 
 %-----------------------------------------------------------------------------%
+
+:- func machine_datafile_cmd_pref_to_url(string, string, string, cmd,
+    preferences) = string.
+
+machine_datafile_cmd_pref_to_url(Machine, ScriptName, DataFileName, Cmd,
+        Preferences) =
+    "http://" ++
+    Machine ++
+    ScriptName ++ "?" ++
+    cmd_to_string(Cmd) ++
+    string.char_to_string(query_separator_char) ++
+    preferences_to_string(Preferences) ++
+    string.char_to_string(query_separator_char) ++
+    DataFileName.
+
+%-----------------------------------------------------------------------------%
 :- end_module html_format.
 %-----------------------------------------------------------------------------%
Index: deep_profiler/interface.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/interface.m,v
retrieving revision 1.19
diff -u -u -r1.19 interface.m
--- deep_profiler/interface.m	23 Nov 2007 07:35:51 -0000	1.19
+++ deep_profiler/interface.m	18 Apr 2008 02:41:35 -0000
@@ -33,27 +33,13 @@
 % the user wants data displayed; they persist across queries unless the user
 % changes them.
 %
-% This module defines the types of commands and preferences. It provides
-% mechanisms for converting queries to URLs and URLs to queries, but it
-% does not expose the encoding. The encoding is compositional; each component
-% of the query (say x) has a x_to_string function to convert it to the URL form
-% and a string_to_x predicate to try to convert an URL fragment back to it.
-% The function/predicate pairs are adjacent to make it easy to update both at
-% the same time. This is essential, because we have no other mechanism to
-% ensure that the URLs we embed in the HTML pages we generate will be
-% recognized and correctly parsed by the CGI program.
-%
 %-----------------------------------------------------------------------------%
 
 :- module interface.
 :- interface.
 
-:- import_module profile.
-
 :- import_module bool.
-:- import_module char.
 :- import_module io.
-:- import_module maybe.
 
 %-----------------------------------------------------------------------------%
 
@@ -82,7 +68,6 @@
 :- func want_prefix = string.
 :- func want_file_name = string.
 :- func response_file_name(string, int) = string.
-:- func contour_file_name(string) = string.
 
     % send_term(ToFileName, Debug, Term):
     %
@@ -116,224 +101,13 @@
 
 %-----------------------------------------------------------------------------%
 
-:- type resp
-    --->    html(string).
-
-:- type cmd_pref
-    --->    cmd_pref(cmd, preferences_indication).
-
-:- type cmd
-    --->    deep_cmd_quit
-    ;       deep_cmd_restart
-    ;       deep_cmd_timeout(int)
-    ;       deep_cmd_menu
-    ;       deep_cmd_root(maybe(int))
-    ;       deep_cmd_clique(int)
-    ;       deep_cmd_proc(int)
-    ;       deep_cmd_proc_callers(int, caller_groups, int)
-    ;       deep_cmd_modules
-    ;       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)
-    ;       deep_cmd_call_site_dynamic(int)
-    ;       deep_cmd_raw_clique(int).
-
-:- type caller_groups
-    --->    group_by_call_site
-    ;       group_by_proc
-    ;       group_by_module
-    ;       group_by_clique.
-
-:- type cost_kind
-    --->    cost_calls
-    ;       cost_redos
-    ;       cost_time
-    ;       cost_callseqs
-    ;       cost_allocs
-    ;       cost_words.
-
-:- type include_descendants
-    --->    self
-    ;       self_and_desc.
-
-:- type display_limit
-    --->    rank_range(int, int)
-            % rank_range(M, N): display procedures with rank M to N,
-            % both inclusive.
-
-    ;       threshold_percent(float)
-            % threshold(Percent): display procedures whose cost is at least
-            % Percent% of the whole program's cost.
-    
-    ;       threshold_value(float).
-            % threshold_value(Value): display procedures whose cost is at least
-            % this value.
-
-:- type preferences_indication
-    --->    given_pref(preferences)
-    ;       default_pref
-    ;       all_pref.
-
-:- type preferences
-    --->    preferences(
-                % The set of fields to display.
-                pref_fields         :: fields,
-
-                % Whether displays should be boxed.
-                pref_box            :: box,
-
-                % What principle governs colours.
-                pref_colour         :: colour_scheme,
-
-                % The max number of ancestors to display.
-                pref_anc            :: maybe(int),
-
-                % Whether pages should summarize at higher order call sites.
-                pref_summarize      :: summarize,
-
-                % The criteria for ordering lines in pages, if the command
-                % doesn't specify otherwise.
-                pref_criteria       :: order_criteria,
-
-                % Whether contour exclusion should be applied.
-                pref_contour        :: contour,
-
-                pref_time           :: time_format,
-
-                % Whether we should show modules/procs that haven't been called.
-                pref_inactive       :: inactive_items
-            ).
-
-:- type port_fields
-    --->    no_port
-    ;       port.
-
-:- type time_fields
-    --->    no_time
-    ;       ticks
-    ;       time
-    ;       ticks_and_time
-    ;       time_and_percall
-    ;       ticks_and_time_and_percall.
-
-
-:- type callseqs_fields
-    --->    no_callseqs
-    ;       callseqs
-    ;       callseqs_and_percall.
-
-:- type alloc_fields
-    --->    no_alloc
-    ;       alloc
-    ;       alloc_and_percall.
-
-:- type memory_fields
-    --->    no_memory
-    ;       memory(memory_units)
-    ;       memory_and_percall(memory_units).
-
-:- type memory_units
-    --->    units_words
-    ;       units_bytes.
-
-:- type fields
-    --->    fields(
-                port_fields     :: port_fields,
-                time_fields     :: time_fields,
-                callseqs_fields :: callseqs_fields,
-                alloc_fields    :: alloc_fields,
-                memory_fields   :: memory_fields
-            ).
-
-:- type box
-    --->    box
-    ;       nobox.
-
-:- type colour_scheme
-    --->    colour_column_groups
-    ;       colour_none.
-
-:- type summarize
-    --->    summarize
-    ;       dont_summarize.
-
-:- type order_criteria
-    --->    by_context
-    ;       by_name
-    ;       by_cost(
-                cost_kind,
-                include_descendants,
-                measurement_scope
-            ).
-
-:- type measurement_scope
-    --->    per_call
-    ;       overall.
-
-:- type contour
-    --->    apply_contour
-    ;       no_contour.
-
-:- type time_format
-    --->    no_scale
-    ;       scale_by_millions
-    ;       scale_by_thousands.
-
-:- type inactive_status
-    --->    inactive_hide
-    ;       inactive_show.
-
-:- type inactive_items
-    --->    inactive_items(
-                inactive_procs   :: inactive_status,
-                inactive_modules :: inactive_status
-            ).
-
-%-----------------------------------------------------------------------------%
-
-    % Return "yes" if it is worth displaying times for this profile.
-    %
-:- func should_display_times(deep) = bool.
-
-:- func solidify_preference(deep, preferences_indication) = preferences.
-
-:- func default_preferences(deep) = preferences.
-
-:- func default_fields(deep) = fields.
-:- func all_fields = fields.
-:- func default_box = box.
-:- func default_colour_scheme = colour_scheme.
-:- func default_ancestor_limit = maybe(int).
-:- func default_summarize = summarize.
-:- func default_order_criteria = order_criteria.
-:- func default_cost_kind = cost_kind.
-:- func default_incl_desc = include_descendants.
-:- func default_scope = measurement_scope.
-:- func default_contour = contour.
-:- func default_time_format = time_format.
-:- func default_inactive_items = inactive_items.
-
-:- func query_separator_char = char.
-:- func machine_datafile_cmd_pref_to_url(string, string, string, cmd,
-    preferences) = string.
-:- func url_component_to_cmd(string, cmd) = cmd.
-:- func url_component_to_maybe_cmd(string) = maybe(cmd).
-:- func url_component_to_maybe_pref(string) = maybe(preferences).
-
-%-----------------------------------------------------------------------------%
-%-----------------------------------------------------------------------------%
-
 :- implementation.
 
 :- import_module conf.
 :- import_module util.
+:- import_module query.
 
+:- import_module char.
 :- import_module int.
 :- import_module list.
 :- import_module require.
@@ -341,70 +115,6 @@
 
 %-----------------------------------------------------------------------------%
 
-    % Display times only if the profile was derived from a run that ran for
-    % at least this many quanta.
-    %
-:- func minimum_meaningful_quanta = int.
-
-minimum_meaningful_quanta = 10.
-
-should_display_times(Deep) =
-    ( Deep ^ profile_stats ^ user_quanta > minimum_meaningful_quanta ->
-        yes
-    ;
-        no
-    ).
-
-solidify_preference(Deep, PrefInd) = Pref :-
-    (
-        PrefInd = given_pref(Pref)
-    ;
-        PrefInd = default_pref,
-        Pref = default_preferences(Deep)
-    ;
-        PrefInd = all_pref,
-        Pref = default_preferences(Deep) ^ pref_fields := all_fields
-    ).
-
-default_preferences(Deep) =
-    preferences(
-        default_fields(Deep),
-        default_box,
-        default_colour_scheme,
-        default_ancestor_limit,
-        default_summarize,
-        default_order_criteria,
-        default_contour,
-        default_time_format,
-        default_inactive_items
-    ).
-
-default_fields(Deep) = Fields :-
-    ShouldDisplayTimes = should_display_times(Deep),
-    (
-        ShouldDisplayTimes = yes,
-        Time = ticks
-    ;
-        ShouldDisplayTimes = no,
-        Time = no_time
-    ),
-    Fields = fields(port, Time, callseqs, no_alloc, memory(units_words)).
-all_fields = fields(port, ticks_and_time_and_percall, callseqs_and_percall,
-    alloc, memory(units_words)).
-default_box = box.
-default_colour_scheme = colour_column_groups.
-default_ancestor_limit = yes(5).
-default_summarize = dont_summarize.
-default_order_criteria = by_context.
-default_cost_kind = cost_callseqs.
-default_incl_desc = self_and_desc.
-default_scope = overall.
-default_contour = no_contour.
-default_time_format = scale_by_thousands.
-default_inactive_items = inactive_items(inactive_hide, inactive_hide).
-
-%-----------------------------------------------------------------------------%
-
 to_server_pipe_name(DataFileName) =
     server_dir ++ "/" ++
     "mdprof_server_to" ++ filename_mangle(DataFileName).
@@ -433,9 +143,6 @@
     "mdprof_response" ++ filename_mangle(DataFileName) ++
     string.int_to_string(QueryNum).
 
-contour_file_name(DataFileName) =
-    DataFileName ++ ".contour".
-
 :- func server_dir = string.
 
 server_dir = "/var/tmp".
@@ -586,567 +293,5 @@
     ).
 
 %-----------------------------------------------------------------------------%
-
-:- func cmd_separator_char = char.
-:- func pref_separator_char = char.
-:- func criteria_separator_char = char.
-:- func field_separator_char = char.
-:- func limit_separator_char = char.
-
-query_separator_char = ('&').
-cmd_separator_char = ('/').
-pref_separator_char = ('/').
-criteria_separator_char = ('-').
-field_separator_char = ('-').
-limit_separator_char = ('-').
-
-machine_datafile_cmd_pref_to_url(Machine, ScriptName, DataFileName, Cmd,
-        Preferences) =
-    "http://" ++
-    Machine ++
-    ScriptName ++ "?" ++
-    cmd_to_string(Cmd) ++
-    string.char_to_string(query_separator_char) ++
-    preferences_to_string(Preferences) ++
-    string.char_to_string(query_separator_char) ++
-    DataFileName.
-
-:- func cmd_to_string(cmd) = string.
-
-cmd_to_string(Cmd) = CmdStr :-
-    (
-        Cmd = deep_cmd_quit,
-        CmdStr = "quit"
-    ;
-        Cmd = deep_cmd_restart,
-        CmdStr = "restart"
-    ;
-        Cmd = deep_cmd_timeout(Minutes),
-        CmdStr = string.format("timeout%c%d",
-            [c(cmd_separator_char), i(Minutes)])
-    ;
-        Cmd = deep_cmd_menu,
-        CmdStr = "menu"
-    ;
-        Cmd = deep_cmd_root(MaybePercent),
-        (
-            MaybePercent = yes(Percent),
-            CmdStr = string.format("root%c%d",
-                [c(cmd_separator_char), i(Percent)])
-        ;
-            MaybePercent = no,
-            CmdStr = string.format("root%c%s",
-                [c(cmd_separator_char), s("no")])
-        )
-    ;
-        Cmd = deep_cmd_clique(CliqueNum),
-        CmdStr = string.format("clique%c%d",
-            [c(cmd_separator_char), i(CliqueNum)])
-    ;
-        Cmd = deep_cmd_proc(ProcNum),
-        CmdStr = string.format("proc%c%d",
-            [c(cmd_separator_char), i(ProcNum)])
-    ;
-        Cmd = deep_cmd_proc_callers(ProcNum, GroupCallers, BunchNum),
-        GroupCallersStr = caller_groups_to_string(GroupCallers),
-        CmdStr = string.format("proc_callers%c%d%c%s%c%d",
-            [c(cmd_separator_char), i(ProcNum),
-            c(cmd_separator_char), s(GroupCallersStr),
-            c(cmd_separator_char), i(BunchNum)])
-    ;
-        Cmd = deep_cmd_modules,
-        CmdStr = "modules"
-    ;
-        Cmd = deep_cmd_module(ModuleName),
-        CmdStr = string.format("module%c%s",
-            [c(cmd_separator_char), s(ModuleName)])
-    ;
-        Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
-        LimitStr = limit_to_string(Limit),
-        CostKindStr = cost_kind_to_string(CostKind),
-        InclDescStr = incl_desc_to_string(InclDesc),
-        ScopeStr = scope_to_string(Scope),
-        CmdStr = string.format("top_procs%c%s%c%s%c%s%c%s",
-            [c(cmd_separator_char), s(LimitStr),
-            c(cmd_separator_char), s(CostKindStr),
-            c(cmd_separator_char), s(InclDescStr),
-            c(cmd_separator_char), s(ScopeStr)])
-    ;
-        Cmd = deep_cmd_proc_static(PSI),
-        CmdStr = string.format("proc_static%c%d",
-            [c(cmd_separator_char), i(PSI)])
-    ;
-        Cmd = deep_cmd_proc_dynamic(PDI),
-        CmdStr = string.format("proc_dynamic%c%d",
-            [c(cmd_separator_char), i(PDI)])
-    ;
-        Cmd = deep_cmd_call_site_static(CSSI),
-        CmdStr = string.format("call_site_static%c%d",
-            [c(cmd_separator_char), i(CSSI)])
-    ;
-        Cmd = deep_cmd_call_site_dynamic(CSDI),
-        CmdStr = string.format("call_site_dynamic%c%d",
-            [c(cmd_separator_char), i(CSDI)])
-    ;
-        Cmd = deep_cmd_raw_clique(CI),
-        CmdStr = string.format("raw_clique%c%d",
-            [c(cmd_separator_char), i(CI)])
-    ).
-
-:- func preferences_to_string(preferences) = string.
-
-preferences_to_string(Pref) = PrefStr :-
-    Pref = preferences(Fields, Box, Colour, MaybeAncestorLimit,
-        Summarize, Order, Contour, Time, InactiveItems),
-    (
-        MaybeAncestorLimit = yes(AncestorLimit),
-        MaybeAncestorLimitStr =
-            string.format("%d", [i(AncestorLimit)])
-    ;
-        MaybeAncestorLimit = no,
-        MaybeAncestorLimitStr = "no"
-    ),
-    PrefStr = string.format("%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s",
-        [s(fields_to_string(Fields)),
-        c(pref_separator_char), s(box_to_string(Box)),
-        c(pref_separator_char), s(colour_scheme_to_string(Colour)),
-        c(pref_separator_char), s(MaybeAncestorLimitStr),
-        c(pref_separator_char), s(summarize_to_string(Summarize)),
-        c(pref_separator_char), s(order_criteria_to_string(Order)),
-        c(pref_separator_char), s(contour_to_string(Contour)),
-        c(pref_separator_char), s(time_format_to_string(Time)),
-        c(pref_separator_char),
-        s(inactive_items_to_string(InactiveItems))
-    ]).
-
-url_component_to_cmd(QueryString, DefaultCmd) = Cmd :-
-    MaybeCmd = url_component_to_maybe_cmd(QueryString),
-    (
-        MaybeCmd = yes(Cmd)
-    ;
-        MaybeCmd = no,
-        Cmd = DefaultCmd
-    ).
-
-url_component_to_maybe_cmd(QueryString) = MaybeCmd :-
-    split(QueryString, pref_separator_char, Pieces),
-    (
-        Pieces = ["root", MaybePercentStr],
-        ( MaybePercentStr = "no" ->
-            MaybePercent = no
-        ; string.to_int(MaybePercentStr, Percent) ->
-            MaybePercent = yes(Percent)
-        ;
-            fail
-        )
-    ->
-        MaybeCmd = yes(deep_cmd_root(MaybePercent))
-    ;
-        Pieces = ["clique", CliqueNumStr],
-        string.to_int(CliqueNumStr, CliqueNum)
-    ->
-        MaybeCmd = yes(deep_cmd_clique(CliqueNum))
-    ;
-        Pieces = ["proc", PSIStr],
-        string.to_int(PSIStr, PSI)
-    ->
-        MaybeCmd = yes(deep_cmd_proc(PSI))
-    ;
-        Pieces = ["proc_callers", PSIStr, GroupCallersStr, BunchNumStr],
-        string.to_int(PSIStr, PSI),
-        string.to_int(BunchNumStr, BunchNum),
-        string_to_caller_groups(GroupCallersStr, GroupCallers)
-    ->
-        MaybeCmd = yes(deep_cmd_proc_callers(PSI, GroupCallers, BunchNum))
-    ;
-        Pieces = ["modules"]
-    ->
-        MaybeCmd = yes(deep_cmd_modules)
-    ;
-        Pieces = ["module", ModuleName]
-    ->
-        MaybeCmd = yes(deep_cmd_module(ModuleName))
-    ;
-        Pieces = ["top_procs", LimitStr, CostKindStr, InclDescStr, ScopeStr],
-        string_to_limit(LimitStr, Limit),
-        string_to_cost_kind(CostKindStr, CostKind),
-        string_to_incl_desc(InclDescStr, InclDesc),
-        string_to_scope(ScopeStr, Scope)
-    ->
-        MaybeCmd = yes(deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope))
-    ;
-        Pieces = ["menu"]
-    ->
-        MaybeCmd = yes(deep_cmd_menu)
-    ;
-        Pieces = ["proc_static", PSIStr],
-        string.to_int(PSIStr, PSI)
-    ->
-        MaybeCmd = yes(deep_cmd_proc_static(PSI))
-    ;
-        Pieces = ["proc_dynamic", PDIStr],
-        string.to_int(PDIStr, PDI)
-    ->
-        MaybeCmd = yes(deep_cmd_proc_dynamic(PDI))
-    ;
-        Pieces = ["call_site_static", CSSIStr],
-        string.to_int(CSSIStr, CSSI)
-    ->
-        MaybeCmd = yes(deep_cmd_call_site_static(CSSI))
-    ;
-        Pieces = ["call_site_dynamic", CSDIStr],
-        string.to_int(CSDIStr, CSDI)
-    ->
-        MaybeCmd = yes(deep_cmd_call_site_dynamic(CSDI))
-    ;
-        Pieces = ["raw_clique", CliqueNumStr],
-        string.to_int(CliqueNumStr, CliqueNum)
-    ->
-        MaybeCmd = yes(deep_cmd_raw_clique(CliqueNum))
-    ;
-        Pieces = ["timeout", TimeOutStr],
-        string.to_int(TimeOutStr, TimeOut)
-    ->
-        MaybeCmd = yes(deep_cmd_timeout(TimeOut))
-    ;
-        Pieces = ["restart"]
-    ->
-        MaybeCmd = yes(deep_cmd_restart)
-    ;
-        Pieces = ["quit"]
-    ->
-        MaybeCmd = yes(deep_cmd_quit)
-    ;
-        MaybeCmd = no
-    ).
-
-url_component_to_maybe_pref(QueryString) = MaybePreferences :-
-    split(QueryString, pref_separator_char, Pieces),
-    (
-        Pieces = [FieldsStr, BoxStr, ColourStr, MaybeAncestorLimitStr,
-            SummarizeStr, OrderStr, ContourStr, TimeStr,
-            InactiveItemsStr],
-        string_to_fields(FieldsStr, Fields),
-        string_to_box(BoxStr, Box),
-        string_to_colour_scheme(ColourStr, Colour),
-        ( string.to_int(MaybeAncestorLimitStr, AncestorLimit) ->
-            MaybeAncestorLimit = yes(AncestorLimit)
-        ; MaybeAncestorLimitStr = "no" ->
-            MaybeAncestorLimit = no
-        ;
-            fail
-        ),
-        string_to_summarize(SummarizeStr, Summarize),
-        string_to_order_criteria(OrderStr, Order),
-        string_to_contour(ContourStr, Contour),
-        string_to_time_format(TimeStr, Time),
-        string_to_inactive_items(InactiveItemsStr, InactiveItems)
-    ->
-        Preferences = preferences(Fields, Box, Colour, MaybeAncestorLimit,
-            Summarize, Order, Contour, Time, InactiveItems),
-        MaybePreferences = yes(Preferences)
-    ;
-        MaybePreferences = no
-    ).
-
-%-----------------------------------------------------------------------------%
-
-:- func port_fields_to_string(port_fields) = string.
-
-port_fields_to_string(PortFields) = String :-
-    string_to_port_fields(String, PortFields).
-
-:- pred string_to_port_fields(string, port_fields).
-:- mode string_to_port_fields(in, out) is semidet.
-:- mode string_to_port_fields(out, in) is det.
-
-string_to_port_fields("_", no_port).
-string_to_port_fields("p", port).
-
-:- func time_fields_to_string(time_fields) = string.
-
-time_fields_to_string(TimeFields) = String :-
-    string_to_time_fields(String, TimeFields).
-
-:- pred string_to_time_fields(string, time_fields).
-:- mode string_to_time_fields(in, out) is semidet.
-:- mode string_to_time_fields(out, in) is det.
-
-string_to_time_fields("_",   no_time).
-string_to_time_fields("q",   ticks).
-string_to_time_fields("t",   time).
-string_to_time_fields("qt",  ticks_and_time).
-string_to_time_fields("tp",  time_and_percall).
-string_to_time_fields("qtp", ticks_and_time_and_percall).
-
-:- func callseqs_fields_to_string(callseqs_fields) = string.
-
-callseqs_fields_to_string(AllocFields) = String :-
-    string_to_callseqs_fields(String, AllocFields).
-
-:- pred string_to_callseqs_fields(string, callseqs_fields).
-:- mode string_to_callseqs_fields(in, out) is semidet.
-:- mode string_to_callseqs_fields(out, in) is det.
-
-string_to_callseqs_fields("_", no_callseqs).
-string_to_callseqs_fields("s", callseqs).
-string_to_callseqs_fields("S", callseqs_and_percall).
-
-:- func alloc_fields_to_string(alloc_fields) = string.
-
-alloc_fields_to_string(AllocFields) = String :-
-    string_to_alloc_fields(String, AllocFields).
-
-:- pred string_to_alloc_fields(string, alloc_fields).
-:- mode string_to_alloc_fields(in, out) is semidet.
-:- mode string_to_alloc_fields(out, in) is det.
-
-string_to_alloc_fields("_", no_alloc).
-string_to_alloc_fields("a", alloc).
-string_to_alloc_fields("A", alloc_and_percall).
-
-:- func memory_fields_to_string(memory_fields) = string.
-
-memory_fields_to_string(MemoryFields) = String :-
-    string_to_memory_fields(String, MemoryFields).
-
-:- pred string_to_memory_fields(string, memory_fields).
-:- mode string_to_memory_fields(in, out) is semidet.
-:- mode string_to_memory_fields(out, in) is det.
-
-string_to_memory_fields("_", no_memory).
-string_to_memory_fields("b", memory(units_bytes)).
-string_to_memory_fields("w", memory(units_words)).
-string_to_memory_fields("B", memory_and_percall(units_bytes)).
-string_to_memory_fields("W", memory_and_percall(units_words)).
-
-:- func fields_to_string(fields) = string.
-
-fields_to_string(fields(Port, Time, CallSeqs, Allocs, Memory)) =
-    port_fields_to_string(Port) ++
-    string.char_to_string(field_separator_char) ++
-    time_fields_to_string(Time) ++
-    string.char_to_string(field_separator_char) ++
-    callseqs_fields_to_string(CallSeqs) ++
-    string.char_to_string(field_separator_char) ++
-    alloc_fields_to_string(Allocs) ++
-    string.char_to_string(field_separator_char) ++
-    memory_fields_to_string(Memory).
-
-:- pred string_to_fields(string::in, fields::out) is semidet.
-
-string_to_fields(FieldsStr, Fields) :-
-    (
-        split(FieldsStr, field_separator_char, Pieces),
-        Pieces = [PortStr, TimeStr, CallSeqsStr, AllocStr, MemoryStr],
-        string_to_port_fields(PortStr, Port),
-        string_to_time_fields(TimeStr, Time),
-        string_to_callseqs_fields(CallSeqsStr, CallSeqs),
-        string_to_alloc_fields(AllocStr, Alloc),
-        string_to_memory_fields(MemoryStr, Memory)
-    ->
-        Fields = fields(Port, Time, CallSeqs, Alloc, Memory)
-    ;
-        fail
-    ).
-
-:- func caller_groups_to_string(caller_groups) = string.
-
-caller_groups_to_string(CallerGroups) = String :-
-    string_to_caller_groups(String, CallerGroups).
-
-:- pred string_to_caller_groups(string, caller_groups).
-:- mode string_to_caller_groups(in, out) is semidet.
-:- mode string_to_caller_groups(out, in) is det.
-
-string_to_caller_groups("cs", group_by_call_site).
-string_to_caller_groups("pr", group_by_proc).
-string_to_caller_groups("mo", group_by_module).
-string_to_caller_groups("cl", group_by_clique).
-
-:- func cost_kind_to_string(cost_kind) = string.
-
-cost_kind_to_string(CostKind) = String :-
-    string_to_cost_kind(String, CostKind).
-
-:- pred string_to_cost_kind(string, cost_kind).
-:- mode string_to_cost_kind(in, out) is semidet.
-:- mode string_to_cost_kind(out, in) is det.
-
-string_to_cost_kind("calls",    cost_calls).
-string_to_cost_kind("redos",    cost_redos).
-string_to_cost_kind("time",     cost_time).
-string_to_cost_kind("callseqs", cost_callseqs).
-string_to_cost_kind("allocs",   cost_allocs).
-string_to_cost_kind("words",    cost_words).
-
-:- func incl_desc_to_string(include_descendants) = string.
-
-incl_desc_to_string(InclDesc) = String :-
-    string_to_incl_desc(String, InclDesc).
-
-:- pred string_to_incl_desc(string, include_descendants).
-:- mode string_to_incl_desc(in, out) is semidet.
-:- mode string_to_incl_desc(out, in) is det.
-
-string_to_incl_desc("self", self).
-string_to_incl_desc("both", self_and_desc).
-
-:- func limit_to_string(display_limit) = string.
-
-limit_to_string(rank_range(Lo, Hi)) =
-    string.format("%d%c%d", [i(Lo), c(limit_separator_char), i(Hi)]).
-limit_to_string(threshold_percent(Threshold)) =
-    string.format("p%g", [f(Threshold)]).
-limit_to_string(threshold_value(Value)) =
-    string.format("v%g", [f(Value)]).
-
-:- pred string_to_limit(string::in, display_limit::out) is semidet.
-
-string_to_limit(LimitStr, Limit) :-
-    (
-        split(LimitStr, limit_separator_char, Pieces),
-        Pieces = [FirstStr, LastStr],
-        string.to_int(FirstStr, First),
-        string.to_int(LastStr, Last)
-    ->
-        Limit = rank_range(First, Last)
-    ;
-        string.append("p", PercentStr, LimitStr),
-        string.to_float(PercentStr, Threshold)
-    ->
-        Limit = threshold_percent(Threshold)
-    ;
-        string.append("v", ValueStr, LimitStr),
-        string.to_float(ValueStr, Value)
-    ->
-        Limit = threshold_value(Value)
-    ;
-        fail
-    ).
-
-:- func summarize_to_string(summarize) = string.
-
-summarize_to_string(summarize)      = "sum".
-summarize_to_string(dont_summarize) = "nosum".
-
-:- pred string_to_summarize(string::in, summarize::out) is semidet.
-
-string_to_summarize("sum",   summarize).
-string_to_summarize("nosum", dont_summarize).
-
-:- func order_criteria_to_string(order_criteria) = string.
-
-order_criteria_to_string(by_context) = "context".
-order_criteria_to_string(by_name) = "name".
-order_criteria_to_string(by_cost(CostKind, InclDesc, Scope)) =
-    "cost" ++
-    string.char_to_string(criteria_separator_char) ++
-    cost_kind_to_string(CostKind) ++
-    string.char_to_string(criteria_separator_char) ++
-    incl_desc_to_string(InclDesc) ++
-    string.char_to_string(criteria_separator_char) ++
-    scope_to_string(Scope).
-
-:- pred string_to_order_criteria(string::in, order_criteria::out) is semidet.
-
-string_to_order_criteria(CriteriaStr, Criteria) :-
-    (
-        CriteriaStr = "context"
-    ->
-        Criteria = by_context
-    ;
-        CriteriaStr = "name"
-    ->
-        Criteria = by_name
-    ;
-        split(CriteriaStr, criteria_separator_char, Pieces),
-        Pieces = ["cost", CostKindStr, InclDescStr, ScopeStr],
-        string_to_cost_kind(CostKindStr, CostKind),
-        string_to_incl_desc(InclDescStr, InclDesc),
-        string_to_scope(ScopeStr, Scope)
-    ->
-        Criteria = by_cost(CostKind, InclDesc, Scope)
-    ;
-        fail
-    ).
-
-:- func scope_to_string(measurement_scope) = string.
-
-scope_to_string(Scope) = String :-
-    string_to_scope(String, Scope).
-
-:- pred string_to_scope(string, measurement_scope).
-:- mode string_to_scope(in, out) is semidet.
-:- mode string_to_scope(out, in) is det.
-
-string_to_scope("pc", per_call).
-string_to_scope("oa",  overall).
-
-:- func contour_to_string(contour) = string.
-
-contour_to_string(Contour) = String :-
-    string_to_contour(String, Contour).
-
-:- pred string_to_contour(string, contour).
-:- mode string_to_contour(in, out) is semidet.
-:- mode string_to_contour(out, in) is det.
-
-string_to_contour("ac", apply_contour).
-string_to_contour("nc", no_contour).
-
-:- func time_format_to_string(time_format) = string.
-
-time_format_to_string(no_scale)           = "no".
-time_format_to_string(scale_by_millions)  = "mi".
-time_format_to_string(scale_by_thousands) = "th".
-
-:- pred string_to_time_format(string, time_format).
-:- mode string_to_time_format(in, out) is semidet.
-:- mode string_to_time_format(out, in) is det.
-
-string_to_time_format("no", no_scale).
-string_to_time_format("mi", scale_by_millions).
-string_to_time_format("th", scale_by_thousands).
-
-:- func inactive_items_to_string(inactive_items) = string.
-
-inactive_items_to_string(Items) = String :-
-    string_to_inactive_items(String, Items).
-
-:- pred string_to_inactive_items(string, inactive_items).
-:- mode string_to_inactive_items(in, out) is semidet.
-:- mode string_to_inactive_items(out, in) is det.
-
-string_to_inactive_items("hh", inactive_items(inactive_hide, inactive_hide)).
-string_to_inactive_items("sh", inactive_items(inactive_show, inactive_hide)).
-string_to_inactive_items("hs", inactive_items(inactive_hide, inactive_show)).
-string_to_inactive_items("ss", inactive_items(inactive_show, inactive_show)).
-
-:- func colour_scheme_to_string(colour_scheme) = string.
-
-colour_scheme_to_string(Scheme) = String :-
-    string_to_colour_scheme(String, Scheme).
-
-:- pred string_to_colour_scheme(string, colour_scheme).
-:- mode string_to_colour_scheme(in, out) is semidet.
-:- mode string_to_colour_scheme(out, in) is det.
-
-string_to_colour_scheme("cols", colour_column_groups).
-string_to_colour_scheme("none", colour_none).
-
-:- func box_to_string(box) = string.
-
-box_to_string(Box) = String :-
-    string_to_box(String, Box).
-
-:- pred string_to_box(string, box).
-:- mode string_to_box(in, out) is semidet.
-:- mode string_to_box(out, in) is det.
-
-string_to_box("box",   box).
-string_to_box("nobox", nobox).
-
-%-----------------------------------------------------------------------------%
 :- end_module interface.
 %-----------------------------------------------------------------------------%
Index: deep_profiler/mdprof_cgi.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_cgi.m,v
retrieving revision 1.21
diff -u -u -r1.21 mdprof_cgi.m
--- deep_profiler/mdprof_cgi.m	17 Feb 2008 06:48:38 -0000	1.21
+++ deep_profiler/mdprof_cgi.m	18 Apr 2008 02:41:35 -0000
@@ -71,10 +71,10 @@
         ),
         split(QueryString0, query_separator_char, Pieces),
         ( Pieces = [CmdStr, PrefStr, FileName] ->
-            Cmd = url_component_to_cmd(CmdStr, deep_cmd_menu),
+            Cmd = string_to_cmd(CmdStr, deep_cmd_menu),
             process_query(Cmd, yes(PrefStr), FileName, Options, !IO)
         ; Pieces = [CmdStr, FileName] ->
-            Cmd = url_component_to_cmd(CmdStr, deep_cmd_menu),
+            Cmd = string_to_cmd(CmdStr, deep_cmd_menu),
             process_query(Cmd, no, FileName, Options, !IO)
         ; Pieces = [FileName] ->
             process_query(deep_cmd_menu, no, FileName, Options, !IO)
@@ -197,7 +197,7 @@
 process_query(Cmd, MaybePrefStr, DataFileName0, Options0, !IO) :-
     (
         MaybePrefStr = yes(PrefStr),
-        MaybePref = url_component_to_maybe_pref(PrefStr)
+        MaybePref = string_to_maybe_pref(PrefStr)
     ;
         MaybePrefStr = no,
         MaybePref = no
Index: deep_profiler/query.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/query.m,v
retrieving revision 1.18
diff -u -u -r1.18 query.m
--- deep_profiler/query.m	23 Nov 2007 07:35:52 -0000	1.18
+++ deep_profiler/query.m	18 Apr 2008 02:41:35 -0000
@@ -11,15 +11,28 @@
 %
 % This module contains the top level predicates for servicing individual
 % queries.
+%
+% This module defines the types of commands and preferences.  It provides
+% mechanisms for converting queries to strings and strings to queries, but
+% it does not expose the encoding. The encoding is compositional; each
+% component of the query (say x) has a x_to_string function to convert it to
+% a string and a string_to_x predicate to try to convert a string fragment
+% back to it.  The function/predicate pairs are adjacent to make it easy to
+% update both at the same time. This is essential, because we have no other
+% mechanism to ensure that the URLs embeded in the HTML pages generated by
+% the mdprof_cgi tool will be recognized and correctly parsed by mdprof_cgi.
+%
 %-----------------------------------------------------------------------------%
 
 :- module query.
 :- interface.
 
 :- import_module profile.
-:- import_module interface.
 
+:- import_module bool.
+:- import_module char.
 :- import_module io.
+:- import_module maybe.
 
 %-----------------------------------------------------------------------------%
 
@@ -27,6 +40,219 @@
     io::di, io::uo) is cc_multi.
 
 %-----------------------------------------------------------------------------%
+
+:- type resp
+    --->    html(string).
+
+:- type cmd_pref
+    --->    cmd_pref(cmd, preferences_indication).
+
+:- type cmd
+    --->    deep_cmd_quit
+    ;       deep_cmd_restart
+    ;       deep_cmd_timeout(int)
+    ;       deep_cmd_menu
+    ;       deep_cmd_root(maybe(int))
+    ;       deep_cmd_clique(int)
+    ;       deep_cmd_proc(int)
+    ;       deep_cmd_proc_callers(int, caller_groups, int)
+    ;       deep_cmd_modules
+    ;       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)
+    ;       deep_cmd_call_site_dynamic(int)
+    ;       deep_cmd_raw_clique(int).
+
+:- type caller_groups
+    --->    group_by_call_site
+    ;       group_by_proc
+    ;       group_by_module
+    ;       group_by_clique.
+
+:- type cost_kind
+    --->    cost_calls
+    ;       cost_redos
+    ;       cost_time
+    ;       cost_callseqs
+    ;       cost_allocs
+    ;       cost_words.
+
+:- type include_descendants
+    --->    self
+    ;       self_and_desc.
+
+:- type display_limit
+    --->    rank_range(int, int)
+            % rank_range(M, N): display procedures with rank M to N,
+            % both inclusive.
+
+    ;       threshold_percent(float)
+            % threshold(Percent): display procedures whose cost is at least
+            % Percent% of the whole program's cost.
+    
+    ;       threshold_value(float).
+            % threshold_value(Value): display procedures whose cost is at least
+            % this value.
+
+:- type preferences_indication
+    --->    given_pref(preferences)
+    ;       default_pref
+    ;       all_pref.
+
+:- type preferences
+    --->    preferences(
+                % The set of fields to display.
+                pref_fields         :: fields,
+
+                % Whether displays should be boxed.
+                pref_box            :: box,
+
+                % What principle governs colours.
+                pref_colour         :: colour_scheme,
+
+                % The max number of ancestors to display.
+                pref_anc            :: maybe(int),
+
+                % Whether pages should summarize at higher order call sites.
+                pref_summarize      :: summarize,
+
+                % The criteria for ordering lines in pages, if the command
+                % doesn't specify otherwise.
+                pref_criteria       :: order_criteria,
+
+                % Whether contour exclusion should be applied.
+                pref_contour        :: contour,
+
+                pref_time           :: time_format,
+
+                % Whether we should show modules/procs that haven't been called.
+                pref_inactive       :: inactive_items
+            ).
+
+:- type port_fields
+    --->    no_port
+    ;       port.
+
+:- type time_fields
+    --->    no_time
+    ;       ticks
+    ;       time
+    ;       ticks_and_time
+    ;       time_and_percall
+    ;       ticks_and_time_and_percall.
+
+
+:- type callseqs_fields
+    --->    no_callseqs
+    ;       callseqs
+    ;       callseqs_and_percall.
+
+:- type alloc_fields
+    --->    no_alloc
+    ;       alloc
+    ;       alloc_and_percall.
+
+:- type memory_fields
+    --->    no_memory
+    ;       memory(memory_units)
+    ;       memory_and_percall(memory_units).
+
+:- type memory_units
+    --->    units_words
+    ;       units_bytes.
+
+:- type fields
+    --->    fields(
+                port_fields     :: port_fields,
+                time_fields     :: time_fields,
+                callseqs_fields :: callseqs_fields,
+                alloc_fields    :: alloc_fields,
+                memory_fields   :: memory_fields
+            ).
+
+:- type box
+    --->    box
+    ;       nobox.
+
+:- type colour_scheme
+    --->    colour_column_groups
+    ;       colour_none.
+
+:- type summarize
+    --->    summarize
+    ;       dont_summarize.
+
+:- type order_criteria
+    --->    by_context
+    ;       by_name
+    ;       by_cost(
+                cost_kind,
+                include_descendants,
+                measurement_scope
+            ).
+
+:- type measurement_scope
+    --->    per_call
+    ;       overall.
+
+:- type contour
+    --->    apply_contour
+    ;       no_contour.
+
+:- type time_format
+    --->    no_scale
+    ;       scale_by_millions
+    ;       scale_by_thousands.
+
+:- type inactive_status
+    --->    inactive_hide
+    ;       inactive_show.
+
+:- type inactive_items
+    --->    inactive_items(
+                inactive_procs   :: inactive_status,
+                inactive_modules :: inactive_status
+            ).
+
+%-----------------------------------------------------------------------------%
+
+    % Return "yes" if it is worth displaying times for this profile.
+    %
+:- func should_display_times(deep) = bool.
+
+:- func solidify_preference(deep, preferences_indication) = preferences.
+
+:- func default_preferences(deep) = preferences.
+
+:- func default_fields(deep) = fields.
+:- func all_fields = fields.
+:- func default_box = box.
+:- func default_colour_scheme = colour_scheme.
+:- func default_ancestor_limit = maybe(int).
+:- func default_summarize = summarize.
+:- func default_order_criteria = order_criteria.
+:- func default_cost_kind = cost_kind.
+:- func default_incl_desc = include_descendants.
+:- func default_scope = measurement_scope.
+:- func default_contour = contour.
+:- func default_time_format = time_format.
+:- func default_inactive_items = inactive_items.
+
+:- func query_separator_char = char.
+
+:- func preferences_to_string(preferences) = string.
+:- func cmd_to_string(cmd) = string.
+:- func string_to_cmd(string, cmd) = cmd.
+:- func string_to_maybe_cmd(string) = maybe(cmd).
+:- func string_to_maybe_pref(string) = maybe(preferences).
+
+%-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
 :- implementation.
@@ -35,6 +261,7 @@
 :- import_module html_format.
 :- import_module measurements.
 :- import_module top_procs.
+:- import_module util.
 
 :- import_module array.
 :- import_module assoc_list.
@@ -1871,6 +2098,11 @@
 pair_contour(Deep, ExcludeSpec, CSDPtr) =
     apply_contour_exclusion(Deep, ExcludeSpec, CSDPtr) - CSDPtr.
 
+:- func contour_file_name(string) = string.
+
+contour_file_name(DataFileName) =
+    DataFileName ++ ".contour".
+
 %-----------------------------------------------------------------------------%
 
 :- func proc_summary_to_html(preferences, deep, proc_static_ptr) = string.
@@ -2001,6 +2233,617 @@
         Str = string.format("<A HREF=%s>%s</A>",
             [s(URL), s(escape_break_html_string(Str0))])
     ).
+%-----------------------------------------------------------------------------%
+
+    % Display times only if the profile was derived from a run that ran for
+    % at least this many quanta.
+    %
+:- func minimum_meaningful_quanta = int.
+
+minimum_meaningful_quanta = 10.
+
+should_display_times(Deep) =
+    ( Deep ^ profile_stats ^ user_quanta > minimum_meaningful_quanta ->
+        yes
+    ;
+        no
+    ).
+
+solidify_preference(Deep, PrefInd) = Pref :-
+    (
+        PrefInd = given_pref(Pref)
+    ;
+        PrefInd = default_pref,
+        Pref = default_preferences(Deep)
+    ;
+        PrefInd = all_pref,
+        Pref = default_preferences(Deep) ^ pref_fields := all_fields
+    ).
+
+default_preferences(Deep) =
+    preferences(
+        default_fields(Deep),
+        default_box,
+        default_colour_scheme,
+        default_ancestor_limit,
+        default_summarize,
+        default_order_criteria,
+        default_contour,
+        default_time_format,
+        default_inactive_items
+    ).
+
+default_fields(Deep) = Fields :-
+    ShouldDisplayTimes = should_display_times(Deep),
+    (
+        ShouldDisplayTimes = yes,
+        Time = ticks
+    ;
+        ShouldDisplayTimes = no,
+        Time = no_time
+    ),
+    Fields = fields(port, Time, callseqs, no_alloc, memory(units_words)).
+all_fields = fields(port, ticks_and_time_and_percall, callseqs_and_percall,
+    alloc, memory(units_words)).
+default_box = box.
+default_colour_scheme = colour_column_groups.
+default_ancestor_limit = yes(5).
+default_summarize = dont_summarize.
+default_order_criteria = by_context.
+default_cost_kind = cost_callseqs.
+default_incl_desc = self_and_desc.
+default_scope = overall.
+default_contour = no_contour.
+default_time_format = scale_by_thousands.
+default_inactive_items = inactive_items(inactive_hide, inactive_hide).
+%-----------------------------------------------------------------------------%
+
+:- func cmd_separator_char = char.
+:- func pref_separator_char = char.
+:- func criteria_separator_char = char.
+:- func field_separator_char = char.
+:- func limit_separator_char = char.
+
+query_separator_char = ('&').
+cmd_separator_char = ('/').
+pref_separator_char = ('/').
+criteria_separator_char = ('-').
+field_separator_char = ('-').
+limit_separator_char = ('-').
+
+%-----------------------------------------------------------------------------%
+
+cmd_to_string(Cmd) = CmdStr :-
+    (
+        Cmd = deep_cmd_quit,
+        CmdStr = "quit"
+    ;
+        Cmd = deep_cmd_restart,
+        CmdStr = "restart"
+    ;
+        Cmd = deep_cmd_timeout(Minutes),
+        CmdStr = string.format("timeout%c%d",
+            [c(cmd_separator_char), i(Minutes)])
+    ;
+        Cmd = deep_cmd_menu,
+        CmdStr = "menu"
+    ;
+        Cmd = deep_cmd_root(MaybePercent),
+        (
+            MaybePercent = yes(Percent),
+            CmdStr = string.format("root%c%d",
+                [c(cmd_separator_char), i(Percent)])
+        ;
+            MaybePercent = no,
+            CmdStr = string.format("root%c%s",
+                [c(cmd_separator_char), s("no")])
+        )
+    ;
+        Cmd = deep_cmd_clique(CliqueNum),
+        CmdStr = string.format("clique%c%d",
+            [c(cmd_separator_char), i(CliqueNum)])
+    ;
+        Cmd = deep_cmd_proc(ProcNum),
+        CmdStr = string.format("proc%c%d",
+            [c(cmd_separator_char), i(ProcNum)])
+    ;
+        Cmd = deep_cmd_proc_callers(ProcNum, GroupCallers, BunchNum),
+        GroupCallersStr = caller_groups_to_string(GroupCallers),
+        CmdStr = string.format("proc_callers%c%d%c%s%c%d",
+            [c(cmd_separator_char), i(ProcNum),
+            c(cmd_separator_char), s(GroupCallersStr),
+            c(cmd_separator_char), i(BunchNum)])
+    ;
+        Cmd = deep_cmd_modules,
+        CmdStr = "modules"
+    ;
+        Cmd = deep_cmd_module(ModuleName),
+        CmdStr = string.format("module%c%s",
+            [c(cmd_separator_char), s(ModuleName)])
+    ;
+        Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
+        LimitStr = limit_to_string(Limit),
+        CostKindStr = cost_kind_to_string(CostKind),
+        InclDescStr = incl_desc_to_string(InclDesc),
+        ScopeStr = scope_to_string(Scope),
+        CmdStr = string.format("top_procs%c%s%c%s%c%s%c%s",
+            [c(cmd_separator_char), s(LimitStr),
+            c(cmd_separator_char), s(CostKindStr),
+            c(cmd_separator_char), s(InclDescStr),
+            c(cmd_separator_char), s(ScopeStr)])
+    ;
+        Cmd = deep_cmd_proc_static(PSI),
+        CmdStr = string.format("proc_static%c%d",
+            [c(cmd_separator_char), i(PSI)])
+    ;
+        Cmd = deep_cmd_proc_dynamic(PDI),
+        CmdStr = string.format("proc_dynamic%c%d",
+            [c(cmd_separator_char), i(PDI)])
+    ;
+        Cmd = deep_cmd_call_site_static(CSSI),
+        CmdStr = string.format("call_site_static%c%d",
+            [c(cmd_separator_char), i(CSSI)])
+    ;
+        Cmd = deep_cmd_call_site_dynamic(CSDI),
+        CmdStr = string.format("call_site_dynamic%c%d",
+            [c(cmd_separator_char), i(CSDI)])
+    ;
+        Cmd = deep_cmd_raw_clique(CI),
+        CmdStr = string.format("raw_clique%c%d",
+            [c(cmd_separator_char), i(CI)])
+    ).
+
+preferences_to_string(Pref) = PrefStr :-
+    Pref = preferences(Fields, Box, Colour, MaybeAncestorLimit,
+        Summarize, Order, Contour, Time, InactiveItems),
+    (
+        MaybeAncestorLimit = yes(AncestorLimit),
+        MaybeAncestorLimitStr =
+            string.format("%d", [i(AncestorLimit)])
+    ;
+        MaybeAncestorLimit = no,
+        MaybeAncestorLimitStr = "no"
+    ),
+    PrefStr = string.format("%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s%c%s",
+        [s(fields_to_string(Fields)),
+        c(pref_separator_char), s(box_to_string(Box)),
+        c(pref_separator_char), s(colour_scheme_to_string(Colour)),
+        c(pref_separator_char), s(MaybeAncestorLimitStr),
+        c(pref_separator_char), s(summarize_to_string(Summarize)),
+        c(pref_separator_char), s(order_criteria_to_string(Order)),
+        c(pref_separator_char), s(contour_to_string(Contour)),
+        c(pref_separator_char), s(time_format_to_string(Time)),
+        c(pref_separator_char),
+        s(inactive_items_to_string(InactiveItems))
+    ]).
+
+string_to_cmd(QueryString, DefaultCmd) = Cmd :-
+    MaybeCmd = string_to_maybe_cmd(QueryString),
+    (
+        MaybeCmd = yes(Cmd)
+    ;
+        MaybeCmd = no,
+        Cmd = DefaultCmd
+    ).
+
+string_to_maybe_cmd(QueryString) = MaybeCmd :-
+    split(QueryString, pref_separator_char, Pieces),
+    (
+        Pieces = ["root", MaybePercentStr],
+        ( MaybePercentStr = "no" ->
+            MaybePercent = no
+        ; string.to_int(MaybePercentStr, Percent) ->
+            MaybePercent = yes(Percent)
+        ;
+            fail
+        )
+    ->
+        MaybeCmd = yes(deep_cmd_root(MaybePercent))
+    ;
+        Pieces = ["clique", CliqueNumStr],
+        string.to_int(CliqueNumStr, CliqueNum)
+    ->
+        MaybeCmd = yes(deep_cmd_clique(CliqueNum))
+    ;
+        Pieces = ["proc", PSIStr],
+        string.to_int(PSIStr, PSI)
+    ->
+        MaybeCmd = yes(deep_cmd_proc(PSI))
+    ;
+        Pieces = ["proc_callers", PSIStr, GroupCallersStr, BunchNumStr],
+        string.to_int(PSIStr, PSI),
+        string.to_int(BunchNumStr, BunchNum),
+        string_to_caller_groups(GroupCallersStr, GroupCallers)
+    ->
+        MaybeCmd = yes(deep_cmd_proc_callers(PSI, GroupCallers, BunchNum))
+    ;
+        Pieces = ["modules"]
+    ->
+        MaybeCmd = yes(deep_cmd_modules)
+    ;
+        Pieces = ["module", ModuleName]
+    ->
+        MaybeCmd = yes(deep_cmd_module(ModuleName))
+    ;
+        Pieces = ["top_procs", LimitStr, CostKindStr, InclDescStr, ScopeStr],
+        string_to_limit(LimitStr, Limit),
+        string_to_cost_kind(CostKindStr, CostKind),
+        string_to_incl_desc(InclDescStr, InclDesc),
+        string_to_scope(ScopeStr, Scope)
+    ->
+        MaybeCmd = yes(deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope))
+    ;
+        Pieces = ["menu"]
+    ->
+        MaybeCmd = yes(deep_cmd_menu)
+    ;
+        Pieces = ["proc_static", PSIStr],
+        string.to_int(PSIStr, PSI)
+    ->
+        MaybeCmd = yes(deep_cmd_proc_static(PSI))
+    ;
+        Pieces = ["proc_dynamic", PDIStr],
+        string.to_int(PDIStr, PDI)
+    ->
+        MaybeCmd = yes(deep_cmd_proc_dynamic(PDI))
+    ;
+        Pieces = ["call_site_static", CSSIStr],
+        string.to_int(CSSIStr, CSSI)
+    ->
+        MaybeCmd = yes(deep_cmd_call_site_static(CSSI))
+    ;
+        Pieces = ["call_site_dynamic", CSDIStr],
+        string.to_int(CSDIStr, CSDI)
+    ->
+        MaybeCmd = yes(deep_cmd_call_site_dynamic(CSDI))
+    ;
+        Pieces = ["raw_clique", CliqueNumStr],
+        string.to_int(CliqueNumStr, CliqueNum)
+    ->
+        MaybeCmd = yes(deep_cmd_raw_clique(CliqueNum))
+    ;
+        Pieces = ["timeout", TimeOutStr],
+        string.to_int(TimeOutStr, TimeOut)
+    ->
+        MaybeCmd = yes(deep_cmd_timeout(TimeOut))
+    ;
+        Pieces = ["restart"]
+    ->
+        MaybeCmd = yes(deep_cmd_restart)
+    ;
+        Pieces = ["quit"]
+    ->
+        MaybeCmd = yes(deep_cmd_quit)
+    ;
+        MaybeCmd = no
+    ).
+
+string_to_maybe_pref(QueryString) = MaybePreferences :-
+    split(QueryString, pref_separator_char, Pieces),
+    (
+        Pieces = [FieldsStr, BoxStr, ColourStr, MaybeAncestorLimitStr,
+            SummarizeStr, OrderStr, ContourStr, TimeStr,
+            InactiveItemsStr],
+        string_to_fields(FieldsStr, Fields),
+        string_to_box(BoxStr, Box),
+        string_to_colour_scheme(ColourStr, Colour),
+        ( string.to_int(MaybeAncestorLimitStr, AncestorLimit) ->
+            MaybeAncestorLimit = yes(AncestorLimit)
+        ; MaybeAncestorLimitStr = "no" ->
+            MaybeAncestorLimit = no
+        ;
+            fail
+        ),
+        string_to_summarize(SummarizeStr, Summarize),
+        string_to_order_criteria(OrderStr, Order),
+        string_to_contour(ContourStr, Contour),
+        string_to_time_format(TimeStr, Time),
+        string_to_inactive_items(InactiveItemsStr, InactiveItems)
+    ->
+        Preferences = preferences(Fields, Box, Colour, MaybeAncestorLimit,
+            Summarize, Order, Contour, Time, InactiveItems),
+        MaybePreferences = yes(Preferences)
+    ;
+        MaybePreferences = no
+    ).
+
+%-----------------------------------------------------------------------------%
+
+:- func port_fields_to_string(port_fields) = string.
+
+port_fields_to_string(PortFields) = String :-
+    string_to_port_fields(String, PortFields).
+
+:- pred string_to_port_fields(string, port_fields).
+:- mode string_to_port_fields(in, out) is semidet.
+:- mode string_to_port_fields(out, in) is det.
+
+string_to_port_fields("_", no_port).
+string_to_port_fields("p", port).
+
+:- func time_fields_to_string(time_fields) = string.
+
+time_fields_to_string(TimeFields) = String :-
+    string_to_time_fields(String, TimeFields).
+
+:- pred string_to_time_fields(string, time_fields).
+:- mode string_to_time_fields(in, out) is semidet.
+:- mode string_to_time_fields(out, in) is det.
+
+string_to_time_fields("_",   no_time).
+string_to_time_fields("q",   ticks).
+string_to_time_fields("t",   time).
+string_to_time_fields("qt",  ticks_and_time).
+string_to_time_fields("tp",  time_and_percall).
+string_to_time_fields("qtp", ticks_and_time_and_percall).
+
+:- func callseqs_fields_to_string(callseqs_fields) = string.
+
+callseqs_fields_to_string(AllocFields) = String :-
+    string_to_callseqs_fields(String, AllocFields).
+
+:- pred string_to_callseqs_fields(string, callseqs_fields).
+:- mode string_to_callseqs_fields(in, out) is semidet.
+:- mode string_to_callseqs_fields(out, in) is det.
+
+string_to_callseqs_fields("_", no_callseqs).
+string_to_callseqs_fields("s", callseqs).
+string_to_callseqs_fields("S", callseqs_and_percall).
+
+:- func alloc_fields_to_string(alloc_fields) = string.
+
+alloc_fields_to_string(AllocFields) = String :-
+    string_to_alloc_fields(String, AllocFields).
+
+:- pred string_to_alloc_fields(string, alloc_fields).
+:- mode string_to_alloc_fields(in, out) is semidet.
+:- mode string_to_alloc_fields(out, in) is det.
+
+string_to_alloc_fields("_", no_alloc).
+string_to_alloc_fields("a", alloc).
+string_to_alloc_fields("A", alloc_and_percall).
+
+:- func memory_fields_to_string(memory_fields) = string.
+
+memory_fields_to_string(MemoryFields) = String :-
+    string_to_memory_fields(String, MemoryFields).
+
+:- pred string_to_memory_fields(string, memory_fields).
+:- mode string_to_memory_fields(in, out) is semidet.
+:- mode string_to_memory_fields(out, in) is det.
+
+string_to_memory_fields("_", no_memory).
+string_to_memory_fields("b", memory(units_bytes)).
+string_to_memory_fields("w", memory(units_words)).
+string_to_memory_fields("B", memory_and_percall(units_bytes)).
+string_to_memory_fields("W", memory_and_percall(units_words)).
+
+:- func fields_to_string(fields) = string.
+
+fields_to_string(fields(Port, Time, CallSeqs, Allocs, Memory)) =
+    port_fields_to_string(Port) ++
+    string.char_to_string(field_separator_char) ++
+    time_fields_to_string(Time) ++
+    string.char_to_string(field_separator_char) ++
+    callseqs_fields_to_string(CallSeqs) ++
+    string.char_to_string(field_separator_char) ++
+    alloc_fields_to_string(Allocs) ++
+    string.char_to_string(field_separator_char) ++
+    memory_fields_to_string(Memory).
+
+:- pred string_to_fields(string::in, fields::out) is semidet.
+
+string_to_fields(FieldsStr, Fields) :-
+    (
+        split(FieldsStr, field_separator_char, Pieces),
+        Pieces = [PortStr, TimeStr, CallSeqsStr, AllocStr, MemoryStr],
+        string_to_port_fields(PortStr, Port),
+        string_to_time_fields(TimeStr, Time),
+        string_to_callseqs_fields(CallSeqsStr, CallSeqs),
+        string_to_alloc_fields(AllocStr, Alloc),
+        string_to_memory_fields(MemoryStr, Memory)
+    ->
+        Fields = fields(Port, Time, CallSeqs, Alloc, Memory)
+    ;
+        fail
+    ).
+
+:- func caller_groups_to_string(caller_groups) = string.
+
+caller_groups_to_string(CallerGroups) = String :-
+    string_to_caller_groups(String, CallerGroups).
+
+:- pred string_to_caller_groups(string, caller_groups).
+:- mode string_to_caller_groups(in, out) is semidet.
+:- mode string_to_caller_groups(out, in) is det.
+
+string_to_caller_groups("cs", group_by_call_site).
+string_to_caller_groups("pr", group_by_proc).
+string_to_caller_groups("mo", group_by_module).
+string_to_caller_groups("cl", group_by_clique).
+
+:- func cost_kind_to_string(cost_kind) = string.
+
+cost_kind_to_string(CostKind) = String :-
+    string_to_cost_kind(String, CostKind).
+
+:- pred string_to_cost_kind(string, cost_kind).
+:- mode string_to_cost_kind(in, out) is semidet.
+:- mode string_to_cost_kind(out, in) is det.
+
+string_to_cost_kind("calls",    cost_calls).
+string_to_cost_kind("redos",    cost_redos).
+string_to_cost_kind("time",     cost_time).
+string_to_cost_kind("callseqs", cost_callseqs).
+string_to_cost_kind("allocs",   cost_allocs).
+string_to_cost_kind("words",    cost_words).
+
+:- func incl_desc_to_string(include_descendants) = string.
+
+incl_desc_to_string(InclDesc) = String :-
+    string_to_incl_desc(String, InclDesc).
+
+:- pred string_to_incl_desc(string, include_descendants).
+:- mode string_to_incl_desc(in, out) is semidet.
+:- mode string_to_incl_desc(out, in) is det.
+
+string_to_incl_desc("self", self).
+string_to_incl_desc("both", self_and_desc).
+
+:- func limit_to_string(display_limit) = string.
+
+limit_to_string(rank_range(Lo, Hi)) =
+    string.format("%d%c%d", [i(Lo), c(limit_separator_char), i(Hi)]).
+limit_to_string(threshold_percent(Threshold)) =
+    string.format("p%g", [f(Threshold)]).
+limit_to_string(threshold_value(Value)) =
+    string.format("v%g", [f(Value)]).
+
+:- pred string_to_limit(string::in, display_limit::out) is semidet.
+
+string_to_limit(LimitStr, Limit) :-
+    (
+        split(LimitStr, limit_separator_char, Pieces),
+        Pieces = [FirstStr, LastStr],
+        string.to_int(FirstStr, First),
+        string.to_int(LastStr, Last)
+    ->
+        Limit = rank_range(First, Last)
+    ;
+        string.append("p", PercentStr, LimitStr),
+        string.to_float(PercentStr, Threshold)
+    ->
+        Limit = threshold_percent(Threshold)
+    ;
+        string.append("v", ValueStr, LimitStr),
+        string.to_float(ValueStr, Value)
+    ->
+        Limit = threshold_value(Value)
+    ;
+        fail
+    ).
+
+:- func summarize_to_string(summarize) = string.
+
+summarize_to_string(summarize)      = "sum".
+summarize_to_string(dont_summarize) = "nosum".
+
+:- pred string_to_summarize(string::in, summarize::out) is semidet.
+
+string_to_summarize("sum",   summarize).
+string_to_summarize("nosum", dont_summarize).
+
+:- func order_criteria_to_string(order_criteria) = string.
+
+order_criteria_to_string(by_context) = "context".
+order_criteria_to_string(by_name) = "name".
+order_criteria_to_string(by_cost(CostKind, InclDesc, Scope)) =
+    "cost" ++
+    string.char_to_string(criteria_separator_char) ++
+    cost_kind_to_string(CostKind) ++
+    string.char_to_string(criteria_separator_char) ++
+    incl_desc_to_string(InclDesc) ++
+    string.char_to_string(criteria_separator_char) ++
+    scope_to_string(Scope).
+
+:- pred string_to_order_criteria(string::in, order_criteria::out) is semidet.
+
+string_to_order_criteria(CriteriaStr, Criteria) :-
+    (
+        CriteriaStr = "context"
+    ->
+        Criteria = by_context
+    ;
+        CriteriaStr = "name"
+    ->
+        Criteria = by_name
+    ;
+        split(CriteriaStr, criteria_separator_char, Pieces),
+        Pieces = ["cost", CostKindStr, InclDescStr, ScopeStr],
+        string_to_cost_kind(CostKindStr, CostKind),
+        string_to_incl_desc(InclDescStr, InclDesc),
+        string_to_scope(ScopeStr, Scope)
+    ->
+        Criteria = by_cost(CostKind, InclDesc, Scope)
+    ;
+        fail
+    ).
+
+:- func scope_to_string(measurement_scope) = string.
+
+scope_to_string(Scope) = String :-
+    string_to_scope(String, Scope).
+
+:- pred string_to_scope(string, measurement_scope).
+:- mode string_to_scope(in, out) is semidet.
+:- mode string_to_scope(out, in) is det.
+
+string_to_scope("pc", per_call).
+string_to_scope("oa",  overall).
+
+:- func contour_to_string(contour) = string.
+
+contour_to_string(Contour) = String :-
+    string_to_contour(String, Contour).
+
+:- pred string_to_contour(string, contour).
+:- mode string_to_contour(in, out) is semidet.
+:- mode string_to_contour(out, in) is det.
+
+string_to_contour("ac", apply_contour).
+string_to_contour("nc", no_contour).
+
+:- func time_format_to_string(time_format) = string.
+
+time_format_to_string(no_scale)           = "no".
+time_format_to_string(scale_by_millions)  = "mi".
+time_format_to_string(scale_by_thousands) = "th".
+
+:- pred string_to_time_format(string, time_format).
+:- mode string_to_time_format(in, out) is semidet.
+:- mode string_to_time_format(out, in) is det.
+
+string_to_time_format("no", no_scale).
+string_to_time_format("mi", scale_by_millions).
+string_to_time_format("th", scale_by_thousands).
+
+:- func inactive_items_to_string(inactive_items) = string.
+
+inactive_items_to_string(Items) = String :-
+    string_to_inactive_items(String, Items).
+
+:- pred string_to_inactive_items(string, inactive_items).
+:- mode string_to_inactive_items(in, out) is semidet.
+:- mode string_to_inactive_items(out, in) is det.
+
+string_to_inactive_items("hh", inactive_items(inactive_hide, inactive_hide)).
+string_to_inactive_items("sh", inactive_items(inactive_show, inactive_hide)).
+string_to_inactive_items("hs", inactive_items(inactive_hide, inactive_show)).
+string_to_inactive_items("ss", inactive_items(inactive_show, inactive_show)).
+
+:- func colour_scheme_to_string(colour_scheme) = string.
+
+colour_scheme_to_string(Scheme) = String :-
+    string_to_colour_scheme(String, Scheme).
+
+:- pred string_to_colour_scheme(string, colour_scheme).
+:- mode string_to_colour_scheme(in, out) is semidet.
+:- mode string_to_colour_scheme(out, in) is det.
+
+string_to_colour_scheme("cols", colour_column_groups).
+string_to_colour_scheme("none", colour_none).
+
+:- func box_to_string(box) = string.
+
+box_to_string(Box) = String :-
+    string_to_box(String, Box).
+
+:- pred string_to_box(string, box).
+:- mode string_to_box(in, out) is semidet.
+:- mode string_to_box(out, in) is det.
+
+string_to_box("box",   box).
+string_to_box("nobox", nobox).
 
 %----------------------------------------------------------------------------%
 :- end_module query.
Index: deep_profiler/top_procs.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/top_procs.m,v
retrieving revision 1.12
diff -u -u -r1.12 top_procs.m
--- deep_profiler/top_procs.m	23 Nov 2007 07:35:52 -0000	1.12
+++ deep_profiler/top_procs.m	18 Apr 2008 02:41:37 -0000
@@ -18,9 +18,9 @@
 :- module top_procs.
 :- interface.
 
-:- import_module interface.
 :- import_module measurements.
 :- import_module profile.
+:- import_module query.
 
 :- import_module list.
 :- import_module maybe.

--------------------------------------------------------------------------
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