[m-rev.] for post-commit review: clean up ssdb.m

Zoltan Somogyi zs at csse.unimelb.edu.au
Mon Dec 24 10:42:33 AEDT 2007


For post commit review by anyone.

Zoltan.

ssdb/ssdb.m:
	Major cleanup.

	Replace the single large predicate that used to handle all commands
	with one predicate per ssdb command, plus a table mapping command names
	to the id of the commands. This should make it easy to add of a command
	alias system.

	By grouping all forms of a command together (some used to be
	discontinous), this design provides obvious places for the inclusion
	of better (more situation-specific) help messages, and points out
	places where debugger commands should be able to handle more arguments.

	The code used to make pervasive use of semipure/impure code to get
	and set mutables. This was unnecessary, since the mutables were
	already attached to the I/O state and the I/O state was in fact
	available in most places and could trivially made available in the
	other places.

	Give some predicates names that better reflect their purpose.

	Add an XXX asking for the fix of some cut-and-paste programming.

cvs diff: Diffing .
Index: ssdb.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/ssdb/ssdb.m,v
retrieving revision 1.14
diff -u -b -r1.14 ssdb.m
--- ssdb.m	18 Dec 2007 07:51:10 -0000	1.14
+++ ssdb.m	23 Dec 2007 23:41:00 -0000
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
+% vim: ft=mercury ts=4 sw=4 et
 %---------------------------------------------------------------------------%
 % Copyright (C) 2007 The University of Melbourne.
 % This file may only be copied under the terms of the GNU Library General
@@ -18,7 +18,6 @@
 %----------------------------------------------------------------------------%
 %----------------------------------------------------------------------------%
 
-
 :- module ssdb.
 :- interface.
 :- import_module list.
@@ -36,15 +35,13 @@
     ;       ssdb_call_nondet
     ;       ssdb_exit_nondet
     ;       ssdb_redo_nondet
-    ;       ssdb_fail_nondet
-    .
+    ;       ssdb_fail_nondet.
 
     % Type to determine if it is necessary to do a retry.
     %
 :- type ssdb_retry
     --->    do_retry
-    ;       do_not_retry
-    .
+    ;       do_not_retry.
 
     % The list of all variables in use in a procedure.
     %
@@ -67,7 +64,6 @@
     %
 :- type pos == int.
 
-
     % This routine is called at each call event that occurs.
     %
 :- impure pred handle_event_call(ssdb_proc_id::in, list_var_value::in) is det.
@@ -102,7 +98,6 @@
 :- impure pred handle_event_redo_nondet(ssdb_proc_id::in, 
     list_var_value::in) is det.
 
-
 %----------------------------------------------------------------------------%
 %----------------------------------------------------------------------------%
 
@@ -175,8 +170,8 @@
 
 %----------------------------------------------------------------------------%
 
-    % Type used by the prompt predicate to configure the next step in the
-    % handle_event predicate.
+    % Type used by the read_and_execute_cmd predicate to configure
+    % the next step in the handle_event predicate.
     %
 :- type what_next
     --->    wn_step
@@ -194,9 +189,8 @@
     ;       wn_finish(ground)
     ;       wn_goto(ground).
 
-
     % Type used by the handle_event predicate to determine the next stop of
-    % the prompt predicate.
+    % the read_and_execute_cmd predicate.
     %
 :- type next_stop
     --->    ns_step
@@ -218,7 +212,6 @@
     ;       ns_goto(int).
             % Stop at the Event Number given in argument.
 
-
     % A breakpoint is represented by his module and procedure name.
     %
 :- type breakpoint
@@ -241,9 +234,11 @@
 :- mutable(cur_ssdb_event_number, int, 0, ground, 
     [untrailed, attach_to_io_state]).
 
-:- mutable(cur_ssdb_csn, int, 0, ground, [untrailed, attach_to_io_state]).
+:- mutable(cur_ssdb_csn, int, 0, ground,
+    [untrailed, attach_to_io_state]).
 
-:- mutable(cur_ssdb_depth, int, 0, ground, [untrailed, attach_to_io_state]).
+:- mutable(cur_ssdb_depth, int, 0, ground,
+    [untrailed, attach_to_io_state]).
 
 :- mutable(cur_ssdb_next_stop, cur_ssdb_next_stop, ns_step, ground, 
     [untrailed, attach_to_io_state]).
@@ -263,7 +258,6 @@
 :- mutable(debugger_state, debugger_state, init_debugger_state, ground, 
     [untrailed, attach_to_io_state]).
 
-
 :- func init_debugger_state = debugger_state is det.
 
 init_debugger_state = DebuggerState :-
@@ -284,41 +278,36 @@
 
 %----------------------------------------------------------------------------%
 
-    % Call at call port. It writes the event out and call the prompt.
+    % Call at call port. It writes out the event and calls
+    % read_and_execute_cmd.
     %
 handle_event_call(ProcId, ListVarValue) :-
-    semipure get_debugger_state(DebuggerState),
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     ( 
         DebuggerState = debugger_on,
         
         Event = ssdb_call,
-        impure get_ssdb_event_number_inc(EventNum),
-        impure get_ssdb_csn_inc(CSN),
-        impure get_ssdb_depth_inc(PrintDepth),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_ssdb_csn_inc(CSN, !IO),
+            get_ssdb_depth_inc(PrintDepth, !IO),
 
         % Push the new stack frame on top of the shadow stack.
-        semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+            get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
         StackFrame = elem(EventNum, CSN, PrintDepth, ProcId, ListVarValue),
         stack.push(ShadowStack0, StackFrame, ShadowStack),
-        impure set_cur_ssdb_shadow_stack(ShadowStack),
+            set_cur_ssdb_shadow_stack(ShadowStack, !IO),
 
-        semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop, 
-            _AutoRetry),
+            should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop,
+                _AutoRetry, !IO),
         (
             Stop = yes,
-            some [!IO] 
-            (
-                impure invent_io(!:IO),
-                
                 print_event_info(Event, EventNum, ProcId, PrintDepth, CSN, 
                     !IO),
-             
-                impure prompt(Event, ShadowStack, 0, WhatNext, !IO),
-
-                impure consume_io(!.IO),
-
-                impure what_next_stop(EventNum, CSN, WhatNext, _Retry)
-            )
+                read_and_execute_cmd(Event, ShadowStack, 0, WhatNext, !IO),
+                what_next_stop(EventNum, CSN, WhatNext, _Retry, !IO)
         ;
             Stop = no
         )
@@ -326,50 +315,45 @@
         DebuggerState = debugger_off
     ;
         DebuggerState = debugger_disabled
+        ),
+        impure consume_io(!.IO)
     ).
 
-
-    % Call at call port of nondet procedure. It writes the event out and call 
-    % the prompt.
+    % Call at call port of nondet procedure. It writes out the event and calls
+    % read_and_execute_cmd.
     %
 handle_event_call_nondet(ProcId, ListVarValue) :-
-    semipure get_debugger_state(DebuggerState),
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     ( 
         DebuggerState = debugger_on,
         
         Event = ssdb_call_nondet,
-        impure get_ssdb_event_number_inc(EventNum),
-        impure get_ssdb_csn_inc(CSN),
-        impure get_ssdb_depth_inc(PrintDepth),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_ssdb_csn_inc(CSN, !IO),
+            get_ssdb_depth_inc(PrintDepth, !IO),
 
         % Push the new stack frame on top of the shadow stack.
         StackFrame = elem(EventNum, CSN, PrintDepth, ProcId, ListVarValue),
         
-        semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+            get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
         stack.push(ShadowStack0, StackFrame, ShadowStack),
-        impure set_cur_ssdb_shadow_stack(ShadowStack),
+            set_cur_ssdb_shadow_stack(ShadowStack, !IO),
 
-        semipure get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet0),
+            get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet0, !IO),
         stack.push(ShadowStackNonDet0, StackFrame, ShadowStackNonDet),
-        impure set_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet),
+            set_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet, !IO),
 
-        semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop, 
-            _AutoRetry),
+            should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop,
+                _AutoRetry, !IO),
         (
             Stop = yes,
-            some [!IO] 
-            (
-                impure invent_io(!:IO),
-                
                 print_event_info(Event, EventNum, ProcId, PrintDepth, CSN, 
                     !IO),
-             
-                impure prompt(Event, ShadowStack, 0, WhatNext, !IO),
-
-                impure consume_io(!.IO),
-
-                impure what_next_stop(EventNum, CSN, WhatNext, _Retry)
-            )
+                read_and_execute_cmd(Event, ShadowStack, 0, WhatNext, !IO),
+                what_next_stop(EventNum, CSN, WhatNext, _Retry, !IO)
         ;
             Stop = no
         )
@@ -377,98 +361,93 @@
         DebuggerState = debugger_off
     ;
         DebuggerState = debugger_disabled
+        ),
+        impure consume_io(!.IO)
     ).
 
-
-    % Call at exit port. Write the event out and call the prompt.
+    % Call at exit port. Writes out the event and calls read_and_execute_cmd.
     %
 handle_event_exit(ProcId, ListVarValue, Retry) :-
-    semipure get_debugger_state(DebuggerState),
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     ( 
         DebuggerState = debugger_on,
         
         Event = ssdb_exit,
-        impure get_ssdb_event_number_inc(EventNum),
-        semipure get_cur_ssdb_depth(PrintDepth),
-        impure set_list_var_value_in_shadow_stack(ListVarValue),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_cur_ssdb_depth(PrintDepth, !IO),
+            set_list_var_value_in_shadow_stack(ListVarValue, !IO),
 
         % Just get the top stack frame. It will be popped at the end of
         % handle_event. We need to leave the frame in place, e.g. for
         % printing variables at the exit port of the procedure.
-        semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+            get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
         stack.top_det(ShadowStack0, StackFrame),
         CSN = StackFrame ^ se_csn,
         
-        semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop, 
-            AutoRetry),
+            should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop,
+                AutoRetry, !IO),
         (
             Stop = yes,
-            some [!IO] 
-            (
-                impure invent_io(!:IO),
-                
                 (
                     AutoRetry = do_retry,
                     EventNumF = StackFrame ^ se_event_number,
                     CSNF = StackFrame ^ se_csn,
-                    impure set_cur_ssdb_event_number(EventNumF-1),
-                    impure set_cur_ssdb_csn(CSNF-1),
+                    set_cur_ssdb_event_number(EventNumF - 1, !IO),
+                    set_cur_ssdb_csn(CSNF - 1, !IO),
                     WhatNext = wn_retry(CSN)
                 ;
                     AutoRetry = do_not_retry,
                     print_event_info(Event, EventNum, ProcId, PrintDepth, CSN,
                         !IO),
-             
-                    impure prompt(Event, ShadowStack0, 0, WhatNext, !IO)
+                    read_and_execute_cmd(Event, ShadowStack0, 0, WhatNext, !IO)
                 ),
-
-                impure consume_io(!.IO),
-
-                impure what_next_stop(EventNum, CSN, WhatNext, Retry)
-            )
+                what_next_stop(EventNum, CSN, WhatNext, Retry, !IO)
         ;
             Stop = no,
             Retry = do_not_retry
         ),
 
-        impure get_ssdb_depth_dec(_Depth),
+            get_ssdb_depth_dec(_Depth, !IO),
         stack.pop_det(ShadowStack0, _StackFrame1, ShadowStack),
-        impure set_cur_ssdb_shadow_stack(ShadowStack)
+            set_cur_ssdb_shadow_stack(ShadowStack, !IO)
     ;
         ( DebuggerState = debugger_off
         ; DebuggerState = debugger_disabled
         ),
         Retry = do_not_retry
+        ),
+        impure consume_io(!.IO)
     ).
 
-
     % Call at exit port of nondet procedure only.
     %
 handle_event_exit_nondet(ProcId, ListVarValue) :-
-    semipure get_debugger_state(DebuggerState),
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     ( 
         DebuggerState = debugger_on,
         
         Event = ssdb_exit_nondet,
-        impure get_ssdb_event_number_inc(EventNum),
-        semipure get_cur_ssdb_depth(PrintDepth),
-        impure set_list_var_value_in_shadow_stack(ListVarValue),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_cur_ssdb_depth(PrintDepth, !IO),
+            set_list_var_value_in_shadow_stack(ListVarValue, !IO),
 
         % Just get the top stack frame. It will be popped at the end of
         % handle_event. We need to leave the frame in place, e.g. for
         % printing variables at the exit port of the procedure.
-        semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+            get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
         stack.top_det(ShadowStack0, StackFrame),
         CSN = StackFrame ^ se_csn,
         
-        semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop, 
-            AutoRetry),
+            should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop,
+                AutoRetry, !IO),
         (
             Stop = yes,
-            some [!IO] 
-            (
-                impure invent_io(!:IO),
-                
                 (
                     AutoRetry = do_retry,
                     WhatNext = wn_retry(CSN)
@@ -476,213 +455,200 @@
                     AutoRetry = do_not_retry,
                     print_event_info(Event, EventNum, ProcId, PrintDepth, CSN,
                         !IO),
-             
-                    impure prompt(Event, ShadowStack0, 0, WhatNext, !IO)
+                    read_and_execute_cmd(Event, ShadowStack0, 0, WhatNext, !IO)
                 ),
-
-                impure consume_io(!.IO),
-        
-                impure what_next_stop(EventNum, CSN, WhatNext, _Retry)
-            )
+                what_next_stop(EventNum, CSN, WhatNext, _Retry, !IO)
         ;
             Stop = no
         ),
         
-        impure get_ssdb_depth_dec(_Depth),
+            get_ssdb_depth_dec(_Depth, !IO),
         stack.pop_det(ShadowStack0, _StackFrame1, ShadowStack),
-        impure set_cur_ssdb_shadow_stack(ShadowStack)
+            set_cur_ssdb_shadow_stack(ShadowStack, !IO)
     ;
         ( DebuggerState = debugger_off
         ; DebuggerState = debugger_disabled
         )
+        ),
+        impure consume_io(!.IO)
     ).
 
-
-    % Call at fail port. Write the event out and call the prompt.
+    % Call at fail port. Writes out the event and calls read_and_execute_cmd.
     %
 handle_event_fail(ProcId, _ListVarValue, Retry) :-
-    semipure get_debugger_state(DebuggerState),
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     ( 
         DebuggerState = debugger_on,
 
         Event = ssdb_fail,
-        impure get_ssdb_event_number_inc(EventNum),
-        semipure get_cur_ssdb_depth(PrintDepth),
-        semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_cur_ssdb_depth(PrintDepth, !IO),
+            get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
         stack.top_det(ShadowStack0, StackFrame),
         CSN = StackFrame ^ se_csn,
         
-        semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop, 
-            AutoRetry),
+            should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop,
+                AutoRetry, !IO),
         (
             Stop = yes,
-            some [!IO] 
-            (
-                impure invent_io(!:IO),
-                
                 (
                     AutoRetry = do_retry,
                     EventNumF = StackFrame ^ se_event_number,
                     CSNF = StackFrame ^ se_csn,
-                    impure set_cur_ssdb_event_number(EventNumF-1),
-                    impure set_cur_ssdb_csn(CSNF-1),
+                    set_cur_ssdb_event_number(EventNumF - 1, !IO),
+                    set_cur_ssdb_csn(CSNF - 1, !IO),
                     WhatNext = wn_retry(CSN)
                 ;
                     AutoRetry = do_not_retry,
                     print_event_info(Event, EventNum, ProcId, PrintDepth, CSN,
                         !IO),
-             
-                    impure prompt(Event, ShadowStack0, 0, WhatNext, !IO)
+                    read_and_execute_cmd(Event, ShadowStack0, 0, WhatNext, !IO)
                 ),
-
-                impure consume_io(!.IO),
-
-                impure what_next_stop(EventNum, CSN, WhatNext, Retry)
-            )
+                what_next_stop(EventNum, CSN, WhatNext, Retry, !IO)
         ;
             Stop = no,
             Retry = do_not_retry
         ),
         
-        impure get_ssdb_depth_dec(_Depth),
+            get_ssdb_depth_dec(_Depth, !IO),
         stack.pop_det(ShadowStack0, _StackFrame1, ShadowStack),
-        impure set_cur_ssdb_shadow_stack(ShadowStack)
+            set_cur_ssdb_shadow_stack(ShadowStack, !IO)
     ;
         ( DebuggerState = debugger_off
         ; DebuggerState = debugger_disabled
         ),
         Retry = do_not_retry
+        ),
+        impure consume_io(!.IO)
     ).
 
-
     % Call at fail port of nondet procedure only.
     %
 handle_event_fail_nondet(ProcId, _ListVarValue, Retry) :-
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     Event = ssdb_fail_nondet,
-    
-    semipure get_debugger_state(DebuggerState),
     ( 
         DebuggerState = debugger_on,
 
-        impure get_ssdb_event_number_inc(EventNum),
-        semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
         stack.top_det(ShadowStack0, StackFrame),
         CSN = StackFrame ^ se_csn,
-        semipure get_cur_ssdb_depth(PrintDepth),
-        semipure get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet0),
+            get_cur_ssdb_depth(PrintDepth, !IO),
+            get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet0, !IO),
         
-        semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop, 
-            AutoRetry),
+            should_stop_at_this_event(Event, EventNum, CSN, ProcId, Stop,
+                AutoRetry, !IO),
         (
             Stop = yes,
-
-            some [!IO]
-            (
-                impure invent_io(!:IO),
-                
                 (
                     AutoRetry = do_retry,
+                    get_frame_at_depth_nondet(ProcId, PrintDepth,
+                        MaybeStackFrameFound, !IO),
                     (
-                        semipure get_correct_frame_nondet(ProcId, PrintDepth, 
-                            StackFrameFound)
-                    ->
+                        MaybeStackFrameFound = yes(StackFrameFound),
                         EventNumF = StackFrameFound ^ se_event_number,
                         CSNF = StackFrameFound ^ se_csn,
-                        impure set_cur_ssdb_event_number(EventNumF-1),
-                        impure set_cur_ssdb_csn(CSNF-1)
+                        set_cur_ssdb_event_number(EventNumF - 1, !IO),
+                        set_cur_ssdb_csn(CSNF - 1, !IO)
                     ;
-                        error("Unexpected error : ssdb/ssdb.m " ++ 
-                            "get_correct_frame_nondet failed")
+                        MaybeStackFrameFound = no,
+                        error("Unexpected error: ssdb/ssdb.m " ++
+                            "get_frame_at_depth_nondet failed")
                     ),
                     WhatNext = wn_retry(CSN)
                 ;
                     AutoRetry = do_not_retry,
                     print_event_info(Event, EventNum, ProcId, PrintDepth, CSN, 
                         !IO),
-                    impure prompt(Event, ShadowStack0, 0, WhatNext, !IO)
+                    read_and_execute_cmd(Event, ShadowStack0, 0, WhatNext, !IO)
                 ),
-
-                impure consume_io(!.IO),
-
-                impure what_next_stop(EventNum, CSN, WhatNext, Retry)
-            )
+                what_next_stop(EventNum, CSN, WhatNext, Retry, !IO)
         ;
             Stop = no,
             Retry = do_not_retry
         ),
 
-        impure get_ssdb_depth_dec(_Depth),
+            get_ssdb_depth_dec(_Depth, !IO),
         stack.pop_det(ShadowStack0, _StackFrame, ShadowStack),
-        stack.pop_det(ShadowStackNonDet0, _StackFrameNonDet, ShadowStackNonDet),
-        impure set_cur_ssdb_shadow_stack(ShadowStack),
-        impure set_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet)
+            stack.pop_det(ShadowStackNonDet0, _StackFrameNonDet,
+                ShadowStackNonDet),
+            set_cur_ssdb_shadow_stack(ShadowStack, !IO),
+            set_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet, !IO)
     ;
         DebuggerState = debugger_off,
-
-        semipure get_cur_ssdb_depth(Depth),
-        (   % if this frame is the required frame
-            semipure get_correct_frame_nondet(ProcId, Depth+1, _StackFrame)
-        ->  % then debugger will stop at next event
-            impure set_debugger_state(debugger_on),
+            get_cur_ssdb_depth(Depth, !IO),
+            % If this is the required frame, then make the debugger stop
+            % at the next event; otherwise continue.
+            get_frame_at_depth_nondet(ProcId, Depth + 1, MaybeStackFrame, !IO),
+            (
+                MaybeStackFrame = yes(_StackFrame),
+                set_debugger_state(debugger_on, !IO),
             Retry = do_retry
-        ;   % otherwise continue
+            ;
+                MaybeStackFrame = no,
             Retry = do_not_retry
         )
     ;
         DebuggerState = debugger_disabled,
         Retry = do_not_retry
+        ),
+        impure consume_io(!.IO)
     ).
 
-
-    % Call at redo port in nondet procedure. Write the event out and call 
-    % the prompt.
+    % Call at redo port in nondet procedure. Writes out the event and calls
+    % read_and_execute_cmd.
     %
 handle_event_redo_nondet(ProcId, _ListVarValue) :-
-    semipure get_debugger_state(DebuggerState),
+    some [!IO]
+    (
+        impure invent_io(!:IO),
+        get_debugger_state(DebuggerState, !IO),
     ( 
         DebuggerState = debugger_on,
 
         Event = ssdb_redo_nondet,
-        impure get_ssdb_event_number_inc(EventNum),
-        impure get_ssdb_depth_inc(PrintDepth),
+            get_ssdb_event_number_inc(EventNum, !IO),
+            get_ssdb_depth_inc(PrintDepth, !IO),
 
+            get_frame_at_depth_nondet(ProcId, PrintDepth, MaybeStackFrame,
+                !IO),
         (
-            semipure get_correct_frame_nondet(ProcId, PrintDepth, StackFrame)
-        ->
-            semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+                MaybeStackFrame = yes(StackFrame),
+                get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
             stack.push(ShadowStack0, StackFrame, ShadowStack),
-            impure set_cur_ssdb_shadow_stack(ShadowStack),
+                set_cur_ssdb_shadow_stack(ShadowStack, !IO),
             CSN = StackFrame ^ se_csn,
         
-            semipure should_stop_at_this_event(Event, EventNum, CSN, ProcId, 
-                Stop, _AutoRetry),
+                should_stop_at_this_event(Event, EventNum, CSN, ProcId,
+                    Stop, _AutoRetry, !IO),
             (
                 Stop = yes,
-                some [!IO] 
-                (
-                    impure invent_io(!:IO),
-                
                     print_event_info(Event, EventNum, ProcId, PrintDepth, CSN,
                         !IO),
-             
-                    impure prompt(Event, ShadowStack, 0, WhatNext, !IO),
-
-                    impure consume_io(!.IO),
-
-                    impure what_next_stop(EventNum, CSN, WhatNext, _Retry)
-                )
+                    read_and_execute_cmd(Event, ShadowStack, 0, WhatNext, !IO),
+                    what_next_stop(EventNum, CSN, WhatNext, _Retry, !IO)
             ;
                 Stop = no
             )
         ;
-            error("Unexpected error : ssdb/ssdb.m : " ++
-                "get_correct_frame_nondet failed")
+                MaybeStackFrame = no,
+                error("Unexpected error: ssdb/ssdb.m : " ++
+                    "get_frame_at_depth_nondet failed")
         )
 
     ;
         ( DebuggerState = debugger_off
         ; DebuggerState = debugger_disabled
         )
+        ),
+        impure consume_io(!.IO)
     ).
 
 %----------------------------------------------------------------------------%
@@ -695,70 +661,66 @@
 is_same_int(IntA, IntB, IsSame) :-
     IsSame = (IntA = IntB -> yes ; no).
 
-
     % Increment the CSN and return the new value.
     %
-:- impure pred get_ssdb_csn_inc(int::out) is det.
+:- pred get_ssdb_csn_inc(int::out, io::di, io::uo) is det.
 
-get_ssdb_csn_inc(CSN) :-
-    semipure get_cur_ssdb_csn(CSN0),
+get_ssdb_csn_inc(CSN, !IO) :-
+    get_cur_ssdb_csn(CSN0, !IO),
     CSN = CSN0 + 1,
-    impure set_cur_ssdb_csn(CSN).
-
+    set_cur_ssdb_csn(CSN, !IO).
 
     % Increment the Event Number and return the new value.
     %
-:- impure pred get_ssdb_event_number_inc(int::out) is det.
+:- pred get_ssdb_event_number_inc(int::out, io::di, io::uo) is det.
 
-get_ssdb_event_number_inc(EventNum) :-
-    semipure get_cur_ssdb_event_number(EventNum0),
+get_ssdb_event_number_inc(EventNum, !IO) :-
+    get_cur_ssdb_event_number(EventNum0, !IO),
     EventNum = EventNum0 + 1,
-    impure set_cur_ssdb_event_number(EventNum).
+    set_cur_ssdb_event_number(EventNum, !IO).
 
     % Increment the depth and return the new value.
     %
-:- impure pred get_ssdb_depth_inc(int::out) is det.
+:- pred get_ssdb_depth_inc(int::out, io::di, io::uo) is det.
 
-get_ssdb_depth_inc(Depth) :-
-    semipure get_cur_ssdb_shadow_stack(ShadowStack),
+get_ssdb_depth_inc(Depth, !IO) :-
+    get_cur_ssdb_shadow_stack(ShadowStack, !IO),
     Depth0 = stack.depth(ShadowStack),
     Depth = Depth0 + 1,
-    impure set_cur_ssdb_depth(Depth).
-
+    set_cur_ssdb_depth(Depth, !IO).
     
     % Decrement the depth and return the new value.
     %
-:- impure pred get_ssdb_depth_dec(int::out) is det.
+:- pred get_ssdb_depth_dec(int::out, io::di, io::uo) is det.
 
-get_ssdb_depth_dec(Depth) :-
-    semipure get_cur_ssdb_shadow_stack(ShadowStack),
+get_ssdb_depth_dec(Depth, !IO) :-
+    get_cur_ssdb_shadow_stack(ShadowStack, !IO),
     Depth0 = stack.depth(ShadowStack),
     Depth = Depth0 - 1,
-    impure set_cur_ssdb_depth(Depth).
-
+    set_cur_ssdb_depth(Depth, !IO).
     
     % Setter of the se_list_var_value in the first stack_elem.
     %
-:- impure pred set_list_var_value_in_shadow_stack(list(var_value)::in) is det.
+:- pred set_list_var_value_in_shadow_stack(list(var_value)::in,
+    io::di, io::uo) is det.
 
-set_list_var_value_in_shadow_stack(ListVarValue) :-
-    semipure get_cur_ssdb_shadow_stack(ShadowStack0),
+set_list_var_value_in_shadow_stack(ListVarValue, !IO) :-
+    get_cur_ssdb_shadow_stack(ShadowStack0, !IO),
     stack.pop_det(ShadowStack0, StackFrame0, PopedStack),
     StackFrame = StackFrame0 ^ se_list_var_value := ListVarValue,
     stack.push(PopedStack, StackFrame, ShadowStack),
-    impure set_cur_ssdb_shadow_stack(ShadowStack).
-
+    set_cur_ssdb_shadow_stack(ShadowStack, !IO).
 
     % should_stop_at_the_event(Event, CSN, EventNum, ProcId, Stop, AutoRetry).
     %
-    % Set Stop, if Stop equals yes, the prompt will be call.
+    % Figure out whether we should stop execution and start user interaction.
     %
-:- semipure pred should_stop_at_this_event(ssdb_event_type::in, int::in, 
-    int::in, ssdb_proc_id::in, bool::out, ssdb_retry::out) is det.
+:- pred should_stop_at_this_event(ssdb_event_type::in, int::in, int::in,
+    ssdb_proc_id::in, bool::out, ssdb_retry::out, io::di, io::uo) is det.
 
 should_stop_at_this_event(Event, EventNum, CSN, ProcId, ShouldStopAtEvent, 
-        AutoRetry) :-
-    semipure get_cur_ssdb_next_stop(NextStop),
+        AutoRetry, !IO) :-
+    get_cur_ssdb_next_stop(NextStop, !IO),
     (
         NextStop = ns_step,
         ShouldStopAtEvent = yes,
@@ -769,16 +731,17 @@
         AutoRetry = do_not_retry
     ;
         NextStop = ns_continue,
-        semipure get_cur_ssdb_breakpoints(BreakPoints),
+        get_cur_ssdb_breakpoints(BreakPoints, !IO),
         (
             map.search(BreakPoints, 
                 pair(ProcId ^ module_name, ProcId ^ proc_name), BreakPoint)
         ->
+            BreakPointState = BreakPoint ^ bp_state,
             (
-                BreakPoint ^ bp_state = bp_state_enabled
-            ->
+                BreakPointState = bp_state_enabled,
                 ShouldStopAtEvent = yes
             ;
+                BreakPointState = bp_state_disabled,
                 ShouldStopAtEvent = no
             )
         ;
@@ -822,17 +785,16 @@
         AutoRetry = do_not_retry
     ).
 
-
     % what_next_stop(CSN, EventNum, WhatNext, Retry).
     %
     % Set the NextStop and the Retry variable according to the WhatNext value.
     % In the case where the WathNext is set for a retry, it modify the 
     % debugger_state at his old value which it had at the call point.
     %
-:- impure pred what_next_stop(int::in, int::in, what_next::in, 
-    ssdb_retry::out) is det.
+:- pred what_next_stop(int::in, int::in, what_next::in, ssdb_retry::out,
+    io::di, io::uo) is det.
 
-what_next_stop(EventNum, CSN, WhatNext, Retry) :-
+what_next_stop(EventNum, CSN, WhatNext, Retry, !IO) :-
     (
         WhatNext = wn_step,
         NextStop = ns_step,
@@ -851,9 +813,7 @@
         Retry = do_not_retry
     ;
         WhatNext = wn_retry(RetryCSN),
-        (
-            RetryCSN = CSN
-        ->
+        ( RetryCSN = CSN ->
             NextStop = ns_step,
             Retry = do_retry
         ;
@@ -862,15 +822,11 @@
         )
      ;
          WhatNext = wn_retry_nondet(RetryCSN),
-         (
              NextStop = ns_final_port_nondet(RetryCSN, do_retry),
              Retry = do_not_retry
-         )
     ;
         WhatNext = wn_goto(EventNumToGo),
-        (
-            EventNum = EventNumToGo
-        ->
+        ( EventNum = EventNumToGo ->
             NextStop = ns_step,
             Retry = do_not_retry
         ;
@@ -878,28 +834,24 @@
             Retry = do_not_retry
         )
     ),
-    impure set_cur_ssdb_next_stop(NextStop).
+    set_cur_ssdb_next_stop(NextStop, !IO).
 
-
-    % This two following predicates get the right informations in the 
-    % shadow_stack_nondet about the current procedure.
+    % Look up the procedure at the specified depth in the nondet shadow stack.
     %
-:- semipure pred get_correct_frame_nondet(ssdb_proc_id::in, int::in, 
-    stack_elem::out) is semidet.
-
-get_correct_frame_nondet(ProcId, Depth, StackFrame) :-
-    semipure get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet),
-    get_correct_frame_nondet_2(ProcId, Depth, ShadowStackNonDet, StackFrame).
+:- pred get_frame_at_depth_nondet(ssdb_proc_id::in, int::in,
+    maybe(stack_elem)::out, io::di, io::uo) is det.
 
+get_frame_at_depth_nondet(ProcId, Depth, StackFrame, !IO) :-
+    get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet, !IO),
+    get_frame_at_depth_nondet_2(ProcId, Depth, ShadowStackNonDet, StackFrame).
 
-:- pred get_correct_frame_nondet_2(ssdb_proc_id::in, int::in, 
-    stack(stack_elem)::in, stack_elem::out) is semidet.
+:- pred get_frame_at_depth_nondet_2(ssdb_proc_id::in, int::in,
+    stack(stack_elem)::in, maybe(stack_elem)::out) is det.
 
-get_correct_frame_nondet_2(ProcId, Depth, ShadowStackNonDet0, StackFrame) :-
-    (
-        stack.is_empty(ShadowStackNonDet0)
-    ->
-        fail
+get_frame_at_depth_nondet_2(ProcId, Depth, ShadowStackNonDet0,
+        MaybeStackFrame) :-
+    ( stack.is_empty(ShadowStackNonDet0) ->
+        MaybeStackFrame = no
     ;
         stack.pop_det(ShadowStackNonDet0, Frame, ShadowStackNonDet),
         (
@@ -907,19 +859,15 @@
             Frame ^ se_proc_id ^ proc_name = ProcId ^ proc_name,
             Frame ^ se_depth = Depth
         ->
-            StackFrame = Frame
+            MaybeStackFrame = yes(Frame)
         ;
-            get_correct_frame_nondet_2(ProcId, Depth, ShadowStackNonDet, 
-                StackFrame)
+            get_frame_at_depth_nondet_2(ProcId, Depth, ShadowStackNonDet,
+                MaybeStackFrame)
         )
     ).
 
-
 %----------------------------------------------------------------------------%
 
-    %
-    % Display the prompt to debug.
-    %
     % h     :: help
     % f     :: finish (go to the next exit or fail of the current call)
     % n     :: next
@@ -934,53 +882,209 @@
     % u     :: up
     % d     :: down
     % g N   :: goto Nth event number
-    %
 
-:- impure pred prompt(ssdb_event_type::in, stack(stack_elem)::in, int::in, 
-                what_next::out, io::di, io::uo) is det.
+:- type ssdb_cmd
+    --->    ssdb_help
+
+    ;       ssdb_step
+    ;       ssdb_next
+    ;       ssdb_goto
+    ;       ssdb_continue
+    ;       ssdb_finish
+
+    ;       ssdb_retry
+
+    ;       ssdb_stack
+    ;       ssdb_print
+    ;       ssdb_browse
+    ;       ssdb_down
+    ;       ssdb_up
+
+    ;       ssdb_break
+    ;       ssdb_enable
+    ;       ssdb_disable
+    ;       ssdb_delete
+
+    ;       ssdb_exit.
+
+:- pred ssdb_cmd_name(string::in, ssdb_cmd::out) is semidet.
+
+ssdb_cmd_name("h",          ssdb_help).
+ssdb_cmd_name("help",       ssdb_help).
+
+ssdb_cmd_name("s",          ssdb_step).
+ssdb_cmd_name("step",       ssdb_step).
+ssdb_cmd_name("n",          ssdb_next).
+ssdb_cmd_name("next",       ssdb_next).
+ssdb_cmd_name("g",          ssdb_goto).
+ssdb_cmd_name("goto",       ssdb_goto).
+ssdb_cmd_name("c",          ssdb_continue).
+ssdb_cmd_name("continue",   ssdb_continue).
+ssdb_cmd_name("f",          ssdb_finish).
+ssdb_cmd_name("finish",     ssdb_finish).
+
+ssdb_cmd_name("r",          ssdb_retry).
+ssdb_cmd_name("retry",      ssdb_retry).
+
+ssdb_cmd_name("st",         ssdb_stack).
+ssdb_cmd_name("stack",      ssdb_stack).
+ssdb_cmd_name("print",      ssdb_print).
+ssdb_cmd_name("browse",     ssdb_browse).
+ssdb_cmd_name("d",          ssdb_down).
+ssdb_cmd_name("down",       ssdb_down).
+ssdb_cmd_name("u",          ssdb_up).
+ssdb_cmd_name("up",         ssdb_up).
+
+ssdb_cmd_name("b",          ssdb_up).
+ssdb_cmd_name("break",      ssdb_up).
+ssdb_cmd_name("enable",     ssdb_enable).
+ssdb_cmd_name("disable",    ssdb_disable).
+ssdb_cmd_name("delete",     ssdb_delete).
+
+ssdb_cmd_name("exit",       ssdb_exit).
+
+%---------------------------------------------------------------------------%
+
+    % Display the prompt, read a user command, and execute it.
+    %
+:- pred read_and_execute_cmd(ssdb_event_type::in, stack(stack_elem)::in,
+    int::in, what_next::out, io::di, io::uo) is det.
 
-prompt(Event, ShadowStack, Depth, WhatNext, !IO) :-
+read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO) :-
     % XXX use stdout_stream
     io.write_string("ssdb> ", !IO),
     % Read a string in input and return a string.
     io.read_line_as_string(io.stdin_stream, Result, !IO), 
     (
         Result = ok(String0),
-        % String minus any single trailing newline character.
+        % Delete the trailing newline character.
         String = string.chomp(String0),
         Words = string.words(String), 
-
         ( 
-            ( Words = ["h"]
-            ; Words = ["help"]
+            Words = [],
+            % We execute the default command. Alternatively, we could just do
+            % nothing, and call read_and_execute_cmd recursively.
+            execute_cmd(ssdb_step, [], Event, ShadowStack, Depth, WhatNext,
+                !IO)
+        ;
+            Words = [CmdWord | ArgWords],
+            % Implementing aliases would require only looking up an alias map
+            % here.
+            ( ssdb_cmd_name(CmdWord, Cmd) ->
+                execute_cmd(Cmd, ArgWords, Event, ShadowStack, Depth, WhatNext,
+                    !IO)
+            ;
+                io.format("%s: unknown command (try \"help\")\n", [s(CmdWord)],
+                    !IO),
+                read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             )
-        ->
-                print_help(!IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        )
+    ;
+        Result = eof,
+        execute_cmd(ssdb_exit, [], Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Result = error(Error),
+        io.error_message(Error, Msg),
+        io.format("could not read command: %s\n", [s(Msg)], !IO),
+        execute_cmd(ssdb_exit, [], Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+    % Execute a command.
+    %
+:- pred execute_cmd(ssdb_cmd::in, list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
+execute_cmd(Cmd, Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Cmd = ssdb_help,
+        execute_ssdb_help(Args, Event, ShadowStack, Depth, WhatNext, !IO)
         ; 
-            ( Words = ["p"] 
-            ; Words = ["print"]
-            )
-        ->
-                get_correct_frame_with_num(Depth, ShadowStack, CurrentFrame),
-                ListVarValue = CurrentFrame ^ se_list_var_value,
-                print_vars(ListVarValue, !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Cmd = ssdb_step,
+        execute_ssdb_step(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_next,
+        execute_ssdb_next(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_goto,
+        execute_ssdb_goto(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_continue,
+        execute_ssdb_continue(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_finish,
+        execute_ssdb_finish(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_retry,
+        execute_ssdb_retry(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_stack,
+        execute_ssdb_stack(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_print,
+        execute_ssdb_print(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_browse,
+        execute_ssdb_browse(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_down,
+        execute_ssdb_down(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_up,
+        execute_ssdb_up(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_break,
+        execute_ssdb_break(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_enable,
+        execute_ssdb_enable(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_disable,
+        execute_ssdb_disable(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_delete,
+        execute_ssdb_delete(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Cmd = ssdb_exit,
+        execute_ssdb_exit(Args, Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+%---------------------------------------------------------------------------%
+
+:- pred execute_ssdb_help(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
+execute_ssdb_help(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        print_help(!IO)
         ; 
-            ( Words = ["st"]
-            ; Words = ["stack"] 
-            )
-        ->
-                print_frames_list(0, ShadowStack, Depth, !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [_ | _],
+        % We should provide more detailed help if the user specifies a command
+        % name.
+        print_help(!IO)
+    ),
+    read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO).
+
+:- pred execute_ssdb_step(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
+execute_ssdb_step(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        WhatNext = wn_step
         ; 
-            ( Words = ["n"] 
-            ; Words = ["next"]
-            ) 
-        ->
+        Args = [_ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_next(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_next(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
                 ( 
                     ( Event = ssdb_call 
                     ; Event = ssdb_call_nondet
@@ -989,54 +1093,62 @@
                 ->
                     WhatNext = wn_next
                 ;
-                    io.write_string("Impossible at exit or fail port\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("The `next' command can be executed "
+                ++ "only at a call or redo port.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
-
         ;
-            ( Words = []
-            ; Words = ["s"]
-            ; Words = ["step"]
-            )
-        ->
-                WhatNext = wn_step
+        Args = [_ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
 
-        ; 
-            ( Words = ["c"] 
-            ; Words = ["continue"]
-            )
-        ->
-                WhatNext = wn_continue
+:- pred execute_ssdb_goto(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
+execute_ssdb_goto(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
         ; 
-            ( Words = ["b", ModuleName, ProcedureName]
-            ; Words = ["break", ModuleName, ProcedureName]
-            )
-        ->
-                semipure get_cur_ssdb_breakpoints(BreakPoints0),
-                Key = pair(ModuleName, ProcedureName),
-                ( map.contains(BreakPoints0, Key)
-                ->
-                    io.write_string("The new breakpoint already exist\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [EventNumToGoStr],
+        ( string.to_int(EventNumToGoStr, EventNumToGo) ->
+            WhatNext = wn_goto(EventNumToGo)
                 ;   
-                    semipure get_cur_ssdb_number_of_breakpoint(Number),
-                    NewBreakPoint = breakpoint(Number+1, ModuleName, 
-                        ProcedureName, bp_state_enabled),
-                    map.det_insert(BreakPoints0, Key, NewBreakPoint, 
-                        BreakPoints),
-                    BreakPointsListValue = map.values(BreakPoints),
-                    print_breakpoints(BreakPointsListValue, !IO),
-                    impure set_cur_ssdb_breakpoints(BreakPoints),
-                    impure set_cur_ssdb_number_of_breakpoint(Number+1),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("The event number to go to must be an integer.\n",
+                !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
+    ;
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_continue(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
         
+execute_ssdb_continue(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        WhatNext = wn_continue
         ; 
-            ( Words = ["f"] 
-            ; Words = ["finish"]
-            )
-        ->
+        Args = [_ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_finish(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_finish(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
                 ( 
                     ( Event = ssdb_call
                     ; Event = ssdb_call_nondet
@@ -1047,80 +1159,49 @@
                     CSN = FrameStack ^  se_csn,
                     WhatNext = wn_finish(CSN)
                 ;
-                    io.write_string("impossible at exit or fail port\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("The `finish' command can be executed "
+                ++ "only at a call or redo port.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
-
         ; 
-            ( Words = ["f", NStr] 
-            ; Words = ["finish", NStr]
-            ) 
-        ->
-                ( 
-                    string.to_int(NStr, Num),
-                    semipure get_cur_ssdb_depth(CurDepth)
-                ->
+        Args = [Arg],
+        ( string.to_int(Arg, Num) ->
+            get_cur_ssdb_depth(CurDepth, !IO),
                     (
                         Num >= 0,
                         Num =< CurDepth - 1
                     ->
-                        get_correct_frame_with_num(Num, ShadowStack, 
-                            StackFrame),
+                get_correct_frame_with_num(Num, ShadowStack, StackFrame),
                         CSN = StackFrame ^ se_csn,
                         WhatNext = wn_finish(CSN)
                     ;
-                        io.format("The number must be between 1 and %i\n", 
+                io.format("The depth must be between 1 and %i.\n",
                             [i(CurDepth)], !IO),
-                        impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
-                    )
-                ;
-                    io.write_string("The number must be an integer\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+                read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
-
         ; 
-            ( Words = ["d"] 
-            ; Words = ["down"] 
+            io.write_string("The depth must be an integer.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             ) 
-        ->
-                (
-                    DownDepth = Depth - 1,
-                    DownDepth >= 0
-                ->
-                    get_correct_frame_with_num(DownDepth, ShadowStack, 
-                        FrameToPrint),
-                    print_frame_info(FrameToPrint, !IO),
-                    impure prompt(Event, ShadowStack, DownDepth, WhatNext, !IO)
                 ;
-                    io.write_string("Impossible to go down\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
-                )
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
             
-        ; 
-            ( Words = ["u"] 
-            ; Words = ["up"]
-            )
-        ->
-                (
-                    UpDepth = Depth + 1,
-                    UpDepth < stack.depth(ShadowStack) 
-                ->
-                    get_correct_frame_with_num(UpDepth, ShadowStack, 
-                        FrameToPrint),
-                    print_frame_info(FrameToPrint, !IO),
-                    impure prompt(Event, ShadowStack, UpDepth, WhatNext, !IO)
-                ;
-                    io.write_string("Impossible to go up\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
-                )
+:- pred execute_ssdb_retry(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
-        ; 
-            ( Words = ["r"] 
-            ; Words = ["retry"] 
-            ; Words = ["r", "0"] 
-            ; Words = ["retry", "0"] 
-            )
-        ->
+execute_ssdb_retry(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    % XXX: The cases for empty argument list and an argument list consisting of
+    % one number look to be the result of cut-and-paste programming: we should
+    % instead use common code parameterised in the appropriate places.
+    %
+    % XXX: For some reason, the original code here handled the case of the
+    % number argument being zero as if the command had no argument at all.
+    (
+        Args = [],
                 (
                     ( Event = ssdb_exit
                     ; Event = ssdb_fail
@@ -1129,40 +1210,40 @@
                     stack.top_det(ShadowStack, FrameStack),
                     EventNum = FrameStack ^ se_event_number,
                     CSN = FrameStack ^ se_csn,
-                    impure set_cur_ssdb_event_number(EventNum-1),
-                    impure set_cur_ssdb_csn(CSN-1),
+            set_cur_ssdb_event_number(EventNum - 1, !IO),
+            set_cur_ssdb_csn(CSN - 1, !IO),
                     WhatNext = wn_retry(CSN)
                 ;
                     Event = ssdb_exit_nondet,
                     stack.top_det(ShadowStack, FrameStack),
                     EventNum = FrameStack ^ se_event_number,
                     CSN = FrameStack ^ se_csn,
-                    impure set_debugger_state(debugger_off),
-                    % Set the event number and the CSN minus 1 because it will 
-                    % be increment at the next event. So, we need to set the 
-                    % value at the event just before the retried procedure.
-                    impure set_cur_ssdb_event_number(EventNum-1),
-                    impure set_cur_ssdb_csn(CSN-1),
+            set_debugger_state(debugger_off, !IO),
+            % Set the event number to CSN - 1 because it will be incremented
+            % at the next event. So, we need to set it to the number of the
+            % event just *before* the call to the retried procedure.
+            set_cur_ssdb_event_number(EventNum - 1, !IO),
+            set_cur_ssdb_csn(CSN - 1, !IO),
                     WhatNext = wn_retry(CSN)
                 ;
                     ( Event = ssdb_call
                     ; Event = ssdb_call_nondet
                     ; Event = ssdb_redo_nondet
                     ),
-                    io.write_string("Impossible at call or redo port\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("Cannot execute retry " ++
+                "at a call or redo port.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
-
         ; 
-            ( Words = ["r", NStr] 
-            ; Words = ["retry", NStr]
-            )
-        ->
+        Args = [Arg],
+        get_cur_ssdb_depth(CurDepth, !IO),
+        ( string.to_int(Arg, Num) ->
                 ( 
-                    string.to_int(NStr, Num),
-                    semipure get_cur_ssdb_depth(CurDepth)
+                Num = 0
                 ->
-                    (
+                execute_ssdb_retry([], Event, ShadowStack, Depth, WhatNext,
+                    !IO)
+            ;
                         Num >= 0,
                         Num =< CurDepth - 1
                     ->
@@ -1171,27 +1252,22 @@
                             ; Event = ssdb_fail
                             ; Event = ssdb_fail_nondet
                             ),
-                            get_correct_frame_with_num(Num, ShadowStack, 
-                                FrameStack),
+                    get_correct_frame_with_num(Num, ShadowStack, FrameStack),
                             EventNum = FrameStack ^ se_event_number,
                             CSN = FrameStack ^ se_csn,
-                            impure set_cur_ssdb_event_number(EventNum-1),
-                            impure set_cur_ssdb_csn(CSN-1),
+                    set_cur_ssdb_event_number(EventNum - 1, !IO),
+                    set_cur_ssdb_csn(CSN - 1, !IO),
                             WhatNext = wn_retry(CSN)
                         ;
                             Event = ssdb_exit_nondet,
-                            get_correct_frame_with_num(Num, ShadowStack, 
-                                FrameStack),
+                    get_correct_frame_with_num(Num, ShadowStack, FrameStack),
                             CSN = FrameStack ^ se_csn,
                             % Set the event number and the CSN minus 1 because 
                             % it will be increment at the next event. So, we 
                             % need to be at the event just before the call.
-                            semipure get_cur_ssdb_shadow_stack_nondet(
-                                ShadowStackNonDet),
-                            ( 
-                                csn_is_in_stack(CSN, ShadowStackNonDet)
-                            ->
-                                impure set_debugger_state(debugger_off),
+                    get_cur_ssdb_shadow_stack_nondet(ShadowStackNonDet, !IO),
+                    ( csn_is_in_stack(CSN, ShadowStackNonDet) ->
+                        set_debugger_state(debugger_off, !IO),
                                 WhatNext = wn_retry_nondet(CSN)
                             ;
                                 WhatNext = wn_retry(CSN)
@@ -1201,130 +1277,295 @@
                             ; Event = ssdb_call_nondet
                             ; Event = ssdb_redo_nondet
                             ),
-                            io.write_string("Impossible at call or redo 
-                                port\n", !IO),
-                            impure prompt(Event, ShadowStack, Depth, WhatNext, 
+                    io.write_string("Cannot execute retry " ++
+                        "at a call or redo port.\n", !IO),
+                    read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext,
                                 !IO)
                         )
                     ;
-                        io.format("The number must be between 1 and %i\n", 
+                io.format("The depth must be between 1 and %i.\n",
                             [i(CurDepth)], !IO),
-                        impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+                read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                     )
                 ;
-                    io.write_string("The number must be an integer\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("The depth must be an integer.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
+    ;
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_stack(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_stack(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        print_frames_list(0, ShadowStack, Depth, !IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Args = [_ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_print(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
+execute_ssdb_print(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        get_correct_frame_with_num(Depth, ShadowStack, CurrentFrame),
+        ListVarValue = CurrentFrame ^ se_list_var_value,
+        print_vars(ListVarValue, !IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
         ; 
-            ( Words = ["g", EventNumToGoStr] 
-            ; Words = ["goto", EventNumToGoStr]
-            )
-        ->
+        Args = [_ | _],
+        % We should allow users to specify what they want to print.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_browse(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_browse(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
                 ( 
-                    string.to_int(EventNumToGoStr, EventNumToGo) 
+        Args = [],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Args = [VarName],
+        (
+            get_correct_frame_with_num(0, ShadowStack, CurFrame),
+            ListVarValue = CurFrame ^ se_list_var_value,
+            list_var_value_to_assoc_list(ListVarValue, AssListVarValue),
+            assoc_list.search(AssListVarValue, VarName, Univ)
                 ->
-                    WhatNext = wn_goto(EventNumToGo)
+            io.stdin_stream(StdIn, !IO),
+            io.stdout_stream(StdOut, !IO),
+            browser_info.init_persistent_state(State0),
+            BT = browser_term.univ_to_browser_term(Univ),
+            promise_equivalent_solutions [!:IO] (
+                browse.browse_browser_term_no_modes(BT, StdIn, StdOut, _,
+                State0, _State1, !IO)
+            ),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 ;
-                    io.write_string("The number must be an integer\n", !IO),
-                    impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.format("There is no variable named `%s'.\n", [s(VarName)], !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
                 )
+    ;
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
 
+:- pred execute_ssdb_down(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_down(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        (
+            DownDepth = Depth - 1,
+            DownDepth >= 0
+        ->
+            get_correct_frame_with_num(DownDepth, ShadowStack, FrameToPrint),
+            print_frame_info(FrameToPrint, !IO),
+            read_and_execute_cmd(Event, ShadowStack, DownDepth, WhatNext, !IO)
         ; 
-            ( Words = ["b", "info"] 
-            ; Words = ["break", "info"]
+            io.write_string("Already at bottom stack frame.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             )
-        ->
-                semipure get_cur_ssdb_breakpoints(BreakPoints),
-                BreakPointsListValue = map.values(BreakPoints),
-                print_breakpoints(BreakPointsListValue, !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Args = [_ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
 
-        ; Words = ["disable", "*"] ->
-            impure modify_state_breakpoints(bp_state_disabled, !IO),
-            impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+:- pred execute_ssdb_up(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
-        ; Words = ["disable", NumStr] ->
+execute_ssdb_up(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
             ( 
-                string.to_int(NumStr, Num) 
+            UpDepth = Depth + 1,
+            UpDepth < stack.depth(ShadowStack)
             ->
-                impure modify_state_breakpoint_with_num(bp_state_disabled, Num, 
-                    !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            get_correct_frame_with_num(UpDepth, ShadowStack, FrameToPrint),
+            print_frame_info(FrameToPrint, !IO),
+            read_and_execute_cmd(Event, ShadowStack, UpDepth, WhatNext, !IO)
             ;
-                io.write_string("The number must be an integer\n", !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("Already at top stack frame.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             )
+    ;
+        Args = [_ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
 
-        ; Words = ["enable", "*"] ->
-            impure modify_state_breakpoints(bp_state_enabled, !IO),
-            impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+:- pred execute_ssdb_break(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
-        ; Words = ["enable", NumStr] ->
+execute_ssdb_break(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
             ( 
-                string.to_int(NumStr, Num) 
-            ->
-                impure modify_state_breakpoint_with_num(bp_state_enabled, Num, 
-                    !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             ;
-                io.write_string("The number must be an integer\n", !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [Arg],
+        ( Arg = "info" ->
+            get_cur_ssdb_breakpoints(BreakPoints, !IO),
+            BreakPointsListValue = map.values(BreakPoints),
+            print_breakpoints(BreakPointsListValue, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        ;
+            % We should provide more detailed help.
+            print_help(!IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        )
+    ;
+        Args = [ModuleName, ProcedureName],
+        get_cur_ssdb_breakpoints(BreakPoints0, !IO),
+        Key = pair(ModuleName, ProcedureName),
+        ( map.contains(BreakPoints0, Key) ->
+            io.write_string("The new breakpoint already exist\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        ;
+            get_cur_ssdb_number_of_breakpoint(Number, !IO),
+            NewBreakPoint = breakpoint(Number + 1, ModuleName,
+                ProcedureName, bp_state_enabled),
+            map.det_insert(BreakPoints0, Key, NewBreakPoint, BreakPoints),
+            BreakPointsListValue = map.values(BreakPoints),
+            print_breakpoints(BreakPointsListValue, !IO),
+            set_cur_ssdb_breakpoints(BreakPoints, !IO),
+            set_cur_ssdb_number_of_breakpoint(Number + 1, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             )
+    ;
+        Args = [_, _, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
 
-        ; Words = ["delete", "*"] ->
-            BreakPoints = map.init,
-            impure set_cur_ssdb_breakpoints(BreakPoints),
-            io.write_string("All breakpoints have been deleted.\n", !IO),
-            impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+:- pred execute_ssdb_enable(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
-        ; Words = ["delete", NumStr] ->
+execute_ssdb_enable(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
             ( 
-                string.to_int(NumStr, Num) 
-            ->
-                impure delete_breakpoint_with_num(Num, !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             ;
-                io.write_string("The number must be an integer\n", !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [Arg],
+        ( Arg = "*" ->
+            modify_state_breakpoints(bp_state_enabled, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        ; string.to_int(Arg, Num) ->
+            modify_state_breakpoint_with_num(bp_state_enabled, Num, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        ;
+            % We should provide more detailed help.
+            print_help(!IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             )
+    ;
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
 
-        ; Words = ["browse", VarName] ->
+:- pred execute_ssdb_disable(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_disable(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
             (
-                get_correct_frame_with_num(0, ShadowStack, CurFrame),
-                ListVarValue = CurFrame ^ se_list_var_value,
-                list_var_value_to_assoc_list(ListVarValue, AssListVarValue),
-                assoc_list.search(AssListVarValue, VarName, Univ)
-            ->
-                io.stdin_stream(StdIn, !IO),
-                io.stdout_stream(StdOut, !IO),
-                browser_info.init_persistent_state(State0),
-                BT = browser_term.univ_to_browser_term(Univ),
-                promise_equivalent_solutions [!:IO] (
-                    browse.browse_browser_term_no_modes(BT, StdIn, StdOut, _, 
-                    State0, _State1, !IO)),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+        Args = [],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Args = [Arg],
+        ( Arg = "*" ->
+            modify_state_breakpoints(bp_state_disabled, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        ; string.to_int(Arg, Num) ->
+            modify_state_breakpoint_with_num(bp_state_disabled, Num, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             ;
-                io.write_string("\nError in browse command\n", !IO),
-                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("The number must be an integer\n", !IO),
+            % We should provide more detailed help.
+            print_help(!IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
             )
+    ;
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
         
-        ; Words = ["exit"] ->
-                exit_debugger(!IO),
-                WhatNext = wn_step
+:- pred execute_ssdb_delete(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
 
+execute_ssdb_delete(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ;
+        Args = [Arg],
+        ( Arg = "*" ->
+            BreakPoints = map.init,
+            set_cur_ssdb_breakpoints(BreakPoints, !IO),
+            io.write_string("All breakpoints have been deleted.\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+        ; string.to_int(Arg, Num) ->
+            delete_breakpoint_with_num(Num, !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
         ;
-            io.write_string("huh?\n", !IO),
-            impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
+            io.write_string("The number must be an integer\n", !IO),
+            read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
         )
     ;
-        Result = eof,
-        error("eof from read_line_as_string")
+        Args = [_, _ | _],
+        % We should provide more detailed help.
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
+    ).
+
+:- pred execute_ssdb_exit(list(string)::in, ssdb_event_type::in,
+    stack(stack_elem)::in, int::in, what_next::out, io::di, io::uo) is det.
+
+execute_ssdb_exit(Args, Event, ShadowStack, Depth, WhatNext, !IO) :-
+    (
+        Args = [],
+        exit_debugger(!IO),
+        WhatNext = wn_step
     ;
-        Result = error(_),
-        error("error from read_line_as_string")
+        Args = [_ | _],
+        % Should we exit even in this case?
+        print_help(!IO),
+        read_and_execute_cmd(Event, ShadowStack, Depth, WhatNext, !IO)
     ).
 
+%---------------------------------------------------------------------------%
 
     % csn_is_in_stack(CSN, Stack).
     %
@@ -1334,15 +1575,12 @@
 
 csn_is_in_stack(CSN, ShadowStack0) :-
     stack.pop(ShadowStack0, Frame, ShadowStack),
-    (
-        CSN = Frame ^ se_csn
-    ->
+    ( CSN = Frame ^ se_csn ->
         true
     ;
         csn_is_in_stack(CSN, ShadowStack)
     ).
 
-
     % Transform the list(var_value) into a assoc_list. As it is for the browser 
     % use, only the bound variable are put into the assoc_list structure.
     %
@@ -1366,7 +1604,6 @@
         AssocListVarValue = [pair(Name, ValueUniv) | AssocListVarValue0]
     ).
 
-
     % get_correct_frame_with_num(Num, ShadowStack, Frame).
     %
     % Get the Nth frame from the shadow stack, beginning from the top.
@@ -1379,28 +1616,23 @@
 get_correct_frame_with_num(Num, ShadowStack0, StackFrame) :-
     ( Num = 0 ->
         stack.top_det(ShadowStack0, StackFrame)
-
     ; Num > 0 ->
         stack.pop_det(ShadowStack0, _Frame, ShadowStack),
         get_correct_frame_with_num(Num-1, ShadowStack, StackFrame)
-
     ;
-        % it shouldn't arrive here.
         error("Unexpected error : get_correct_frame_with_num")
     ).
 
-
     % Disable or enable all breakpoints.
     %
-:- impure pred modify_state_breakpoints(bp_state::in, io::di, io::uo) is det.
+:- pred modify_state_breakpoints(bp_state::in, io::di, io::uo) is det.
 
 modify_state_breakpoints(State, !IO) :-
-    semipure get_cur_ssdb_breakpoints(BreakPoints),
+    get_cur_ssdb_breakpoints(BreakPoints, !IO),
     BreakPointListValue = map.values(BreakPoints),
     modify_state_breakpoint(State, BreakPointListValue, BreakPoints, 
         BreakPointsModified, !IO),
-    impure set_cur_ssdb_breakpoints(BreakPointsModified).
-
+    set_cur_ssdb_breakpoints(BreakPointsModified, !IO).
 
     % Modify state (enable or disable) of one breakpoint.
     %
@@ -1418,51 +1650,44 @@
         BreakPoint, !:BreakPoints),
     modify_state_breakpoint(State, BreakPoints, !BreakPoints, !IO).
 
-
     % modify_state_breakpoint_with_num(State, Num, !IO).
     %
     % Modify the state of the breakpoint with the number which match Num.
     %
-:- impure pred modify_state_breakpoint_with_num(bp_state::in, int::in, 
+:- pred modify_state_breakpoint_with_num(bp_state::in, int::in,
     io::di, io::uo) is det.
 
 modify_state_breakpoint_with_num(State, Num, !IO) :-
-    (
-        semipure get_cur_ssdb_breakpoints(BreakPoints),
+    get_cur_ssdb_breakpoints(BreakPoints, !IO),
         BreakPointListValue = map.values(BreakPoints),
-        find_breakpoint_with_num(Num, BreakPointListValue, BreakPointToModify)
-    ->
+    ( find_breakpoint_with_num(Num, BreakPointListValue, BreakPointToModify) ->
         modify_state_breakpoint(State, [BreakPointToModify], BreakPoints, 
             BreakPointsModified, !IO),
-        impure set_cur_ssdb_breakpoints(BreakPointsModified)
+        set_cur_ssdb_breakpoints(BreakPointsModified, !IO)
     ;
         io.write_string("No breakpoint found.\n", !IO)
     ).
 
-
     % delete_breakpoint_with_num(Num, !IO).
     %
     % Delete the breakpoint that match with Num.
     %
-:- impure pred delete_breakpoint_with_num(int::in, io::di, io::uo) is det.
+:- pred delete_breakpoint_with_num(int::in, io::di, io::uo) is det.
 
 delete_breakpoint_with_num(Num, !IO) :-
-    (
-        semipure get_cur_ssdb_breakpoints(BreakPoints0),
+    get_cur_ssdb_breakpoints(BreakPoints0, !IO),
         BreakPointsListValue = map.values(BreakPoints0),
-        find_breakpoint_with_num(Num, BreakPointsListValue, BPToDelete)
-    ->
+    ( find_breakpoint_with_num(Num, BreakPointsListValue, BPToDelete) ->
         Module = BPToDelete ^ bp_module_name,
         Procedure = BPToDelete ^ bp_pred_name,
         map.delete(BreakPoints0, pair(Module, Procedure), BreakPoints),
-        impure set_cur_ssdb_breakpoints(BreakPoints),
+        set_cur_ssdb_breakpoints(BreakPoints, !IO),
         io.format("Breakpoint on %s.%s deleted\n", [s(Module), s(Procedure)], 
             !IO)
     ;
         io.write_string("No breakpoint found.\n", !IO)
     ).
 
-
     % find_breakpoint_with_num(Num, ListBreakPoint, BreakPointFound)
     %
     % As the structure of a breakpoint have a Number, this predicate will 
@@ -1472,15 +1697,12 @@
     breakpoint::out) is semidet.
 
 find_breakpoint_with_num(Num, [BP|ListBreakPoint], BreakPointFound) :-
-    (
-        BP ^ bp_number = Num
-    ->
+    ( BP ^ bp_number = Num ->
         BreakPointFound = BP 
     ;
         find_breakpoint_with_num(Num, ListBreakPoint, BreakPointFound)
     ).
 
-
     % Exit the debugger.
     %
 :- pred exit_debugger(io::di, io::uo) is det.
@@ -1493,7 +1715,6 @@
     IO = IO0;
 ").
 
-
 %----------------------------------------------------------------------------%
 
     % Print the current informations at this event point.
@@ -1534,7 +1755,6 @@
     io.write_string(ProcId ^ proc_name, !IO),
     io.nl(!IO).
 
-
     % print_frame_info(Frame, !IO).
     %
     % Print the information of the frame gave in argument.
@@ -1558,8 +1778,6 @@
     io.write_string(ProcId ^ proc_name, !IO),
     io.nl(!IO).
 
-
-
     % Print a summary of the commands.
     %
 :- pred print_help(io::di, io::uo) is det.
@@ -1591,7 +1809,6 @@
         "/ssdb/SSDB_COMMAND_HELP.txt for details", !IO),
     io.nl(!IO).
 
-
     % Print the Stack Trace. Predicate call at the 'stack' command.
     %
 :- pred print_frames_list(int::in, stack(stack_elem)::in, int::in, 
@@ -1610,7 +1827,6 @@
         true
     ).
 
-
     % print_stack_frame(Starred, Level, Frame, !IO).
     %
     % Print the given Frame. The Level is the place of this frame in the 
@@ -1620,8 +1836,8 @@
     io::di, io::uo) is det.
 
 print_stack_frame(Starred, Level, Frame, !IO) :-
-    Module = Frame ^ se_proc_id ^ module_name ,
-    Procedure = Frame ^ se_proc_id ^ proc_name ,
+    Module = Frame ^ se_proc_id ^ module_name,
+    Procedure = Frame ^ se_proc_id ^ proc_name,
 
     (
         Starred = yes,
@@ -1635,7 +1851,6 @@
     print_vars(ListVarValue, !IO),
     io.write_string("   )\n", !IO).
 
-
     % Print the given list of variables and their values, if bound.
     % XXX We should treat the io.state better.
     % XXX The pprint.write predicate is used for the moment instead of 
@@ -1692,7 +1907,6 @@
     io.nl(!IO),
     io.flush_output(!IO).
 
-    
     % Print the current list of breakpoints with their details.
     % 
 :- pred print_breakpoints(list(breakpoint)::in, io::di, io::uo) is det.
@@ -1719,46 +1933,63 @@
     ),
     io.nl(!IO).
 
-
 %----------------------------------------------------------------------------%
 
-
+:- pragma inline(invent_io/1).
 :- impure pred invent_io(io::uo) is det.
 
 :- pragma foreign_proc("C",
     invent_io(_IO::uo),
-    [will_not_call_mercury, thread_safe], "").
+    [will_not_call_mercury, thread_safe],
+"
+").
 
 :- pragma foreign_proc("Erlang",
     invent_io(_IO::uo),
-    [will_not_call_mercury, thread_safe], "void").
+    [will_not_call_mercury, thread_safe],
+"
+    void
+").
 
 :- pragma foreign_proc("C#",
     invent_io(_IO::uo),
-    [will_not_call_mercury, thread_safe], "").
+    [will_not_call_mercury, thread_safe],
+"
+").
 
 :- pragma foreign_proc("Java",
     invent_io(_IO::uo),
-    [will_not_call_mercury, thread_safe], "").
-
+    [will_not_call_mercury, thread_safe],
+"
+").
 
+:- pragma inline(consume_io/1).
 :- impure pred consume_io(io::di) is det.
 
 :- pragma foreign_proc("C",
     consume_io(_IO::di),
-    [will_not_call_mercury, thread_safe], "").
+    [will_not_call_mercury, thread_safe],
+"
+").
 
 :- pragma foreign_proc("Erlang",
     consume_io(_IO::di),
-    [will_not_call_mercury, thread_safe], "void").
+    [will_not_call_mercury, thread_safe],
+"
+    void
+").
 
 :- pragma foreign_proc("C#",
     consume_io(_IO::di),
-    [will_not_call_mercury, thread_safe], "").
+    [will_not_call_mercury, thread_safe],
+"
+").
 
 :- pragma foreign_proc("Java",
     consume_io(_IO::di),
-    [will_not_call_mercury, thread_safe], "").
+    [will_not_call_mercury, thread_safe],
+"
+").
 
 %----------------------------------------------------------------------------%
 %----------------------------------------------------------------------------%
--------------------------------------------------------------------------
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