home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w055 / 4.ddi / SOURCES.LIF / DEBUG.PEL < prev    next >
Encoding:
Text File  |  1990-09-27  |  32.6 KB  |  1,387 lines

  1. # $Header:   P:/source/ppee/macros/debug.pev   1.46   13 Aug 1990 12:54:38   ericj  $
  2.  
  3. ##############################################################################
  4. #
  5. #           Sage Software - POLYTRON Division
  6. #             1700 NW 167th Place
  7. #               Beaverton, OR 97006
  8. #
  9. #   Copyright 1990, Sage Software, Inc.
  10. #
  11. #   Permission is hereby granted for licensed users of Sage Professional
  12. #   Editor and PolyAwk to copy and modify this source code for their own
  13. #   personal use.  These derivative works may be distributed only to other
  14. #   licensed Sage Professional Editor and PolyAwk users.  All other usage
  15. #   is prohibited without express written permission from Sage Software.
  16. #
  17. ##############################################################################
  18.  
  19. #### $Workfile:   debug.pel  $: sageedit debugger entry points
  20. #
  21.  
  22. global debug_color_border = 0x02
  23. global debug_color_text   = 0x07
  24. global debug_color_highlight = 0x1F
  25. global debug_color_title  = 0x02
  26.  
  27. global debug_flip = 1;
  28. local debug_window;
  29. local debug_empty_name = "Debug Window: no function active"
  30. local debug_keymap;
  31. local debug_buffer;
  32. local debug_filename = "";
  33. local command_mode;
  34. local debug_enabled        # True if debug has been called
  35. local original_window;        # Saved when function is debugged.
  36. local original_buffer;
  37. local win_top = 3
  38. local command_win_height = 7
  39. local display_win_height = 15
  40. local win_left, win_width;
  41. local debug_id;
  42. local debug_tabs = default_buffer_tabs;
  43. local debug_view_file = "???"
  44. local debug_num_steps = 0;
  45.  
  46. #
  47. # debug_fun_breakpoints is an array of function gids to break on.
  48. # The index is the gid as a string.  The value is the gid itself.
  49. # The distinction is important because function_name requires the gid itself.
  50. # debug_fun_lineno are the line numbers of the start of the function,
  51. # determined when we hit it.
  52. #
  53. local debug_fun_breakpoints;
  54. local debug_fun_breakpoint_names;
  55. local debug_fun_bp_types;        # 0 = disabled, 1 = enabled, 2 = goto point
  56. local debug_bp_linenos;
  57. local breakpoints_visible = 0;
  58. local ctrl_break_attached = 0;
  59.  
  60.  
  61. local BP_ENABLED        = 0x01;
  62. local BP_GOTO_POINT        = 0x02;
  63.  
  64. local debug_gid, debug_lineno = 0; # GID and lineno of current debugged function
  65. local debug_step_gid;        # GID of function during debug_step
  66. local debug_go_mode;
  67.  
  68. local debug_command_keymap
  69. local debug_command_window
  70. local debug_command_buffer
  71.  
  72. local CTRL_G = 8711
  73. local CTRL_T = 5140
  74.  
  75. global debugger_running = 0;
  76.  
  77.  
  78.  
  79. global function debug_reset(){
  80.     debug_gid        = 0;
  81.     debug_filename   = "";
  82. }
  83.  
  84.  
  85. local function debug_init()
  86. {
  87.     local    cw;
  88.     local    cb;
  89.     local    insert_id = function_id( "debug_insert_key" );
  90.     local    i;
  91.     local    win_height
  92.  
  93.     if (!current_window) {
  94.         current_window = create_window( 0, 0, display_width, display_height);
  95.         attach_window_buffer( current_window, current_buffer );
  96.     }
  97.  
  98.     cw = current_window
  99.     cb = current_buffer
  100.  
  101.     if (debug_enabled) { return; }
  102.     debug_enabled = 1
  103.  
  104.     debug_go_mode = 0;
  105.     debug_id = function_id( "debug_fun" );
  106.  
  107.     # determine the size of the debug window
  108.     win_left = display_width / 4;
  109.     win_width = win_left * 3 - 1;
  110.     win_height = display_height - win_top - 2 - command_win_height;
  111.  
  112.     current_window = 
  113.     debug_window = create_factory_window( win_left, win_top, win_width, display_win_height,
  114.                 WINDOW_SYSTEM + \
  115.                 WINDOW_SB_RIGHT + \
  116.                 WINDOW_TITLE )
  117.     linenumber_format = "%5d: "
  118.     color_text = color_linenumbers = debug_color_text;
  119.     color_border = debug_color_border;
  120.     color_title = debug_color_title;
  121.  
  122.     debug_buffer = create_buffer( \
  123.             debug_empty_name, \
  124.             "", \
  125.             BUFFER_SYSTEM + BUFFER_NO_UNDO + BUFFER_READ_ONLY )
  126.     attach_window_buffer( debug_window, debug_buffer );
  127.     
  128.     debug_keymap = create_keymap(empty_keymap)
  129.     push_keymap(debug_keymap)
  130.  
  131.     #
  132.     # define command keymap bindings for the debug window and
  133.     # the command window.
  134.     #
  135.     for (i = 32; i < 127; i++)
  136.         assign_key( "\\" chr(i), insert_id );
  137.     assign_key( "\\#", insert_id );
  138.     assign_key( "\\\\", insert_id );
  139.  
  140.     assign_key( "<Up>",        "debug_up" );
  141.     assign_key( "<Down>",        "debug_down" );
  142.     assign_key( "<Left>",        "debug_left" );
  143.     assign_key( "<Right>",        "right" );
  144.     assign_key( "<PgUp>",        "debug_page_up");
  145.     assign_key( "<PgDn>",        "debug_page_dn");
  146.     assign_key( "<Ctrl-PgUp>",    "debug_home");
  147.     assign_key( "<Ctrl-PgDn>",    "debug_end" );
  148.     assign_key( "<Ctrl-T>",        "debug_resize_window" );
  149.     assign_key( "<Ctrl-G>",        "debug_resize_window" );
  150.     assign_key( "<Enter>",        "debug_enter" );
  151.     assign_key( "<Bksp>",        "debug_backspace" );
  152.     assign_key( "<Del>",        "debug_delete_chars" );
  153.     assign_key( "<F1>",        "debug_help" );
  154.     assign_key( "<F4>",        "debug_prev_screen" );
  155.     assign_key( "<F5>",        "debug_go" );
  156.     assign_key( "<F6>",        "debug_toggle_windows" );
  157.     assign_key( "<F8>",        "debug_trace" );
  158.     assign_key( "<F10>",        "debug_step" );
  159.     assign_key( "#61440",        "debug_left_press" )
  160.     assign_key( "<End>",        "goto_eol" );
  161.     assign_key( "<Alt-H>",        "debug_help" );
  162.     assign_key( "<Ctrl-C>",        "debug_break" );
  163.     assign_key( "<Alt-C>",        "debug_callstack" );
  164.  
  165.     debug_command_keymap = create_keymap( debug_keymap )
  166.     
  167.  
  168.     # now the keys specific to the debug_window
  169.     #
  170.     assign_key( "<Home>",        "goto_bol" );
  171.     assign_key( "<F9>",        "bp_line" );
  172.  
  173.     pop_keymap()
  174.  
  175.     #
  176.     # create a command line window, buffer, and keymap
  177.     #
  178.     current_window =
  179.     debug_command_window = create_factory_window( win_left, win_top + display_win_height - 1,
  180.                 win_width, command_win_height,
  181.                 WINDOW_SYSTEM + \
  182.                 WINDOW_SB_RIGHT )
  183.     scroll_context_top = 0;
  184.     scroll_context_bottom = 0;
  185.     color_text = debug_color_text;
  186.     color_border = debug_color_border;
  187.     color_title = debug_color_title;
  188.  
  189.  
  190.     current_buffer =
  191.     debug_command_buffer = create_buffer( \
  192.             "", \
  193.             "", \
  194.             BUFFER_SYSTEM )
  195.     insert_key( ord(">") );
  196.     attach_window_buffer( debug_command_window, debug_command_buffer );
  197.     
  198.     push_keymap(debug_command_keymap)
  199.     
  200.     # now the keys specific to the debug_command_window
  201.     #
  202.     assign_key( "<Home>",        "debug_bol" );
  203.  
  204.     pop_keymap()
  205.  
  206.     assign_current_window( cw );
  207.     current_buffer = cb;
  208.  
  209.     command_mode = 1;
  210. }
  211.  
  212.  
  213. # Invoke this to start debugging.
  214. #
  215. function debug()
  216. {
  217.     local gid;
  218.  
  219.     attach_break_handler()
  220.  
  221.     debug_function( 0 );
  222.     debug_init()
  223.  
  224.     # Put debugger in trace mode.
  225.     debug_step_gid = 0
  226.     debug_go_mode = 0
  227.     debug_num_steps = 0;
  228.  
  229.     for (gid in debug_fun_breakpoints)
  230.         if ( and(debug_fun_bp_types[gid], BP_GOTO_POINT))
  231.             debug_remove_goto_point( gid );
  232.  
  233.     if (debugger_running)
  234.         debugger_running = 0;
  235.  
  236.     debug_fun( 0, 1 );
  237.  
  238. }
  239.  
  240.  
  241. # Contents is an array of strings to go in the popup window
  242. # This is a message() function that works
  243. # Used for debugging.
  244. #    local function mymessage(msg)
  245. #    {
  246. #        local x
  247. #        x[1] = msg
  248. #        popup("Here is a message",x)
  249. #    }
  250. #
  251. local function popup(winname,contents)
  252. {
  253.     local i
  254.     local width = length(winname)
  255.     local height
  256.     local curbuf = current_buffer
  257.     local curwin = current_window
  258.     for (i in contents) {
  259.         if (length(contents[i]) > width) { width = length(contents[i]); }
  260.         height++
  261.     }
  262.     width += 3;  # Add 2 for borders and 1 for a pleasing space
  263.     height += 2; # Add 2 for borders.
  264.     if (width > display_width) { width = display_width; }
  265.     if (height < 4) { height = 4; }        # Minimum height
  266.     current_window = create_factory_window( (display_width - width) / 2,
  267.                 3,
  268.                 width,
  269.                 height )
  270.     current_buffer = create_buffer( \
  271.             "DEBUG", \
  272.             "",
  273.             BUFFER_SYSTEM + BUFFER_NO_UNDO )
  274.     attach_window_buffer(current_window,current_buffer)
  275.     window_name = winname
  276.  
  277.     for (i in contents) {
  278.         insert_string(contents[i])
  279.         insert_newline()
  280.     }
  281.  
  282.     goto_buffer_top()
  283.     display_update()
  284.     getkey()
  285.     delete_buffer(current_buffer)
  286.     delete_window(current_window)
  287.     current_buffer = curbuf
  288.     assign_current_window( curwin );
  289. }
  290.  
  291.  
  292.  
  293.  
  294. # Print the call stack
  295. function debug_callstack()
  296. {
  297.     local i, n, x, argc, arglist = ""
  298.     local popbuf
  299.  
  300.     if (!debug_gid)
  301.         return;
  302.  
  303.     for (n=1; (x = debug_get_frame(n)); n++) {
  304.         # x[1] is gid, x[2] is lineno, x[3] is argc, x[4] is param list
  305.         # Create the list of function arguments
  306.         argc = x[3]
  307.         for (i = 1; i <= argc; i++) {
  308.             arglist = arglist debug_get_stack_var(n,i)
  309.             if (i != argc) arglist = arglist ","
  310.         }
  311.         popbuf[n*2] = substr(function_name(x[1]) "(" arglist ")", 1, 60)
  312.         popbuf[n*2+1] = sprintf("    at %s:%d",
  313.             get_source_file_name(x[1]),x[2]);
  314.     }
  315.     popup("Call Stack",popbuf)
  316. }
  317.  
  318.  
  319. function debug_prev_screen(){
  320.     if (debugger_running) {
  321.         assign_current_window( original_window );
  322.         current_buffer = original_buffer;
  323.         display_update();
  324.  
  325.         getkey();
  326.  
  327.         current_window = debug_window;
  328.         current_window = debug_command_window;
  329.         current_window = (command_mode) ? debug_command_window : debug_window;
  330.         display_update();
  331.     }
  332. }
  333.  
  334. function debug_break(){
  335.     debug_go_mode = 0
  336.     debug_step_gid = 0
  337. }
  338.  
  339.  
  340.  
  341. # Step over function call.
  342. # This will not work if the function is called recursively.
  343. function debug_step()
  344. {
  345.     debug_go_mode = 0
  346.     debug_step_gid = debug_gid
  347.     process_end(1)        # Run function some more.
  348. }
  349.  
  350.  
  351. function debug_trace() {
  352.     debug_go_mode = 0
  353.     debug_step_gid = 0
  354.     process_end(1)
  355. }
  356.  
  357.  
  358. function debug_esc() {
  359.     debug_go_mode = 0
  360.     debug_step_gid = 0
  361.     debug_view_file = "???";
  362.     debug_filename = ""
  363.     delete_buffer( debug_buffer )
  364.     process_end(0)
  365.     remove_break_handler()
  366. }
  367.  
  368.  
  369. # Print the value of a variable in the message box.
  370. local function print_val(varname,val)
  371. {
  372.     local typo
  373.  
  374.     current_window = debug_command_window;
  375.     current_buffer = debug_command_buffer;
  376.  
  377.     typo = typeof( val )
  378.  
  379.     if ( typo == "array" ) {
  380.         display_array( val )
  381.         return;
  382.     } else if( 0 + val ) {
  383.         val = sprintf( "%s  (hex 0x%04X)", val, val )
  384.     } else if( typo == "string" ){
  385.         val = "\"" val "\""
  386.     }
  387.  
  388.     debug_message( sprintf("%s == %s, type: %s", varname, val, typo ))
  389.     debug_newline();
  390. }
  391.  
  392.  
  393. # If name is a function parameter or local variable of the current
  394. # function being debugged, then return the index of that variable.
  395. # stframe is the frame number of the function desired.
  396. local function debug_find_stvar(varname,stframe)
  397. {
  398.     local x, list,list1,n,i
  399.     if ((x = debug_get_frame(stframe))) {
  400.         split(x[4],list1,";")        # x[4] is the parameter;local list
  401.         n = split(list1[1],list)    # list1[1] is the parameters
  402.         for (i = 1; i <= n; i++) {
  403.             if (list[i] == varname) return(i)
  404.         }
  405.         n = split(list1[2],list)    # list1[2] is the locals
  406.         for (i = 1; i <= n; i++) {
  407.             if (list[i] == varname) return(- i)
  408.         }
  409.     }
  410.     return(0)
  411. }
  412.  
  413.  
  414. #
  415. # List Breakpoints
  416. #
  417. function bl()
  418. {
  419.     local    i,j = 0;
  420.     local    gid = 0;
  421.     local    cw;
  422.     local    top, bottom;
  423.  
  424.     for (i in debug_fun_breakpoint_names) {
  425.         if (!j)   debug_message( "Breakpoints" );
  426.         debug_newline( 1 );
  427.         debug_message( sprintf( "%4d %s %s", j++, 
  428.             and(debug_fun_bp_types[i],BP_ENABLED) ? "e" : "d", \
  429.                 debug_fun_breakpoint_names[i] ));
  430.     }
  431.  
  432.     if (debug_filename && 
  433.             (current_window == debug_window) || 
  434.             (current_window == debug_command_window)) {
  435.         cw = current_window;
  436.         current_window = debug_window;
  437.         top = window_first;
  438.         bottom = current_line + distance_to_window_bottom();
  439.         while (top <= bottom) {
  440.             if ((top != current_line) && 
  441.                 ((debug_filename ":" top) in debug_fun_breakpoint_names)) {
  442.                 highlight_window( 0, top - window_first, 
  443.                     window_text_width, 1, 0x000F,
  444.                     debug_window );
  445.             }
  446.             top++;
  447.         }
  448.         breakpoints_visible = 1;
  449.         assign_current_window( cw );
  450.     }
  451.  
  452.     if (!j)
  453.         debug_message( "No Breakpoints Set" );
  454.  
  455.     debug_newline();
  456. }
  457.  
  458.  
  459. #
  460. # Clear Breakpoint
  461. #
  462. function bc( str )
  463. {
  464.     local gid,i;
  465.  
  466.     i = (str == "*" ? -1 : atoi( str ));
  467.     if ((i == 0) && (str != "0"))
  468.         return;
  469.     
  470.     if (i >= 0) {
  471.         gid = bpindex_to_gid( i );
  472.         if ((gid) && (gid in debug_fun_breakpoints)) {
  473.             delete debug_fun_breakpoints[gid]
  474.             delete debug_fun_breakpoint_names[gid]
  475.             delete debug_fun_bp_types[gid];
  476.         } else {
  477.             debug_message("Breakpoint " i " not set.")
  478.             debug_newline();
  479.         }
  480.     } else {
  481.         # Clear all breakpoints
  482.         delete debug_fun_breakpoints
  483.         delete debug_fun_breakpoint_names;
  484.         delete debug_fun_bp_types;
  485.     }
  486. }
  487.  
  488.  
  489. #
  490. # Disable Breakpoint
  491. #
  492. function bd( str ){
  493.     local gid,i;
  494.  
  495.     i = (str == "*" ? -1 : atoi( str ));
  496.     if ((i == 0) && (str != "0"))
  497.         return;
  498.     
  499.     if (i >= 0) {
  500.         gid = bpindex_to_gid( i );
  501.         if ((gid) && (gid in debug_fun_breakpoints))
  502.             debug_fun_bp_types[gid] = and( debug_fun_bp_types[gid], not(BP_ENABLED));
  503.     } else {
  504.         for (gid in debug_fun_bp_types)
  505.             debug_fun_bp_types[gid] = and( debug_fun_bp_types[gid], not(BP_ENABLED));
  506.     }
  507. }
  508.  
  509. #
  510. # Enable Breakpoint
  511. #
  512. function be( str ){
  513.     local gid,i;
  514.  
  515.     i = (str == "*" ? -1 : atoi( str ));
  516.     if ((i == 0) && (str != "0"))
  517.         return;
  518.     
  519.     if (i >= 0) {
  520.         gid = bpindex_to_gid( i );
  521.         if (gid) 
  522.             debug_fun_bp_types[gid] = or( debug_fun_bp_types[gid], BP_ENABLED);
  523.     } else {
  524.         for (gid in debug_fun_bp_types)
  525.             debug_fun_bp_types[gid] = or( debug_fun_bp_types[gid], BP_ENABLED);
  526.     }
  527. }
  528.  
  529.  
  530.  
  531. # Set Breakpoints
  532. #
  533. function bp(funname)
  534. {
  535.     local    gid;
  536.     local    i = 0;
  537.     local    msglvl = message_level;
  538.  
  539.     debug_init()
  540.  
  541.     message_level = 2;
  542.     gid = function_id(funname)
  543.     message_level = msglvl;
  544.  
  545.     # This is magic: acceptable gids lie in the range 1000 to 8000
  546.     if (!gid || (gid < 1000 || gid >= 8000)) {
  547.         debug_message("Invalid break address: " funname)
  548.         debug_newline();
  549.         return 0
  550.     }
  551.  
  552.     debug_fun_breakpoints[gid] = 0
  553.     debug_fun_breakpoint_names[gid] = function_name( gid );
  554.     debug_fun_bp_types[gid] = debug_go_mode ? BP_ENABLED + BP_GOTO_POINT : BP_ENABLED;
  555.  
  556.     if (!debugger_running) {
  557.         #
  558.         # don't make the windows visible unless the breakpoints
  559.         # were set from within the debugger.
  560.         #
  561.         hide_window( debug_window );
  562.         hide_window( debug_command_window );
  563.  
  564.         debug_go_mode = 1;
  565.         debug_step_gid = 0;
  566.         debug_function(debug_id)
  567.     }
  568.     return gid;
  569. }
  570.  
  571.  
  572. function bp_line(){
  573.     local    fn;
  574.  
  575.     if (debug_view_file) {
  576.         fn = buildpath( debug_view_file ) ":" current_line;
  577.  
  578.         if  (debug_lineno && (current_line != debug_lineno))
  579.             highlight_window( 0, current_line - window_first, 
  580.                 window_text_width, 1, debug_color_text,
  581.                 debug_window );
  582.         if (fn in debug_fun_breakpoints) {
  583.             delete( debug_fun_breakpoints[fn] );
  584.             delete( debug_fun_bp_types[fn] );
  585.             delete( debug_fun_breakpoint_names[fn] );
  586.         } else {
  587.             debug_bp_linenos[ current_line ] = 0;
  588.             debug_fun_breakpoints[ fn ] = current_line;
  589.             debug_fun_bp_types[ fn ] = BP_ENABLED;
  590.             debug_fun_breakpoint_names[ fn ] = fn;
  591.             highlight_window( 0, current_line - window_first, 
  592.                 window_text_width, 1, 0x000F,
  593.                 debug_window );
  594.             breakpoints_visible = 1;
  595.         }
  596.     }
  597. }
  598.  
  599.  
  600.  
  601. function debug_go()
  602. {
  603.     debug_step_gid = 0;
  604.     debug_go_mode = 1
  605.     process_end(1)
  606. }
  607.  
  608.  
  609. # Function to perform ? debug command.
  610. # Prompt for variable, then print it out.
  611. #
  612. function debug_query( varname )
  613. {
  614.     local msglev = message_level
  615.     local fid,n
  616.     local val
  617.  
  618.     if (!varname)
  619.         return;
  620.  
  621.     assign_current_window( original_window );
  622.     current_buffer = original_buffer;
  623.  
  624.     # Look for local or parameter, then module local var, then global.
  625.     # Turn off error messages while we are doing this.
  626.     message_level = 2
  627.     if (debug_gid && (n = debug_find_stvar(varname,1))) {
  628.         print_val(varname,debug_get_stack_var(1,n))
  629.     }
  630.     else if ((fid = quoted_function_id(path_fname(debug_filename) ":" varname)) ||
  631.             (fid = quoted_function_id(varname))) {
  632.         print_val(varname,execute_function(fid))
  633.     }
  634.     else {
  635.         current_window = debug_command_window;
  636.         current_buffer = debug_command_buffer;
  637.         debug_message("Variable \"" varname "\" not found.");
  638.         debug_newline();
  639.     }
  640.     message_level = msglev
  641.  
  642.     current_window = debug_command_window;
  643.     current_window = debug_window;
  644.     current_window = debug_command_window;
  645. }
  646.  
  647.  
  648. # Call this with the gid and line number of function being debugged,
  649. # or with gid == 0 to just bring up the debugger on nothing.
  650. # debug_session returns 1 to continue debugging, 0 to quit
  651. local function debug_session(){
  652.     local    filename = debug_filename;
  653.     local    cb;
  654.  
  655.     attach_break_handler()
  656.  
  657.     original_window = current_window
  658.     original_buffer = current_buffer
  659.  
  660.     if (!debugger_running) {
  661.         restore_window( debug_window );
  662.         restore_window( debug_command_window );
  663.         debugger_running = 1;
  664.     }
  665.  
  666.     unhighlight_line();
  667.  
  668.     current_window = debug_command_window;
  669.  
  670.     debug_at()
  671.  
  672.     if (command_mode)
  673.         current_window = debug_command_window;
  674.  
  675.     push_keymap( command_mode ? debug_command_keymap : debug_keymap );
  676.  
  677.     debugger_running = process_begin()+0
  678.  
  679.     pop_keymap()
  680.  
  681.     if (!debugger_running) {
  682.         hide_window( debug_command_window );
  683.         hide_window( debug_window );
  684.     }
  685.  
  686.     assign_current_window( original_window);
  687.     current_buffer = original_buffer;
  688.  
  689.     if ( !( debugger_running && !debug_flip) )
  690.         display_update()
  691.  
  692.     return(debugger_running)
  693. }
  694.  
  695.  
  696.  
  697. local function debug_file_display( filename ){
  698.     local def_buf_eol = default_buffer_eol_string;
  699.  
  700.     debug_view_file = filename;
  701.     delete_buffer( debug_buffer )
  702.  
  703.  
  704.     default_buffer_eol_string = "\r\n"
  705.     current_buffer =
  706.     debug_buffer = create_buffer( debug_gid    \
  707.             ? "FILE: " debug_filename " FUNCTION: " function_name(debug_gid) \
  708.             : debug_empty_name,
  709.         debug_filename,
  710.         BUFFER_SYSTEM + BUFFER_NO_UNDO + BUFFER_READ_ONLY)
  711.     default_buffer_eol_string = def_buf_eol;
  712.  
  713.     buffer_tabs = debug_tabs;
  714.     attach_window_buffer( current_window, current_buffer );
  715. }
  716.  
  717. function debug_at()
  718. {
  719.     current_window = debug_window;
  720.     
  721.  
  722.     #
  723.     # if the current file displayed doesn't equal the one that's
  724.     # suppose to be displayed, find the one to display
  725.     #
  726.     if (debug_filename != debug_view_file) {
  727.         debug_filename  = debug_gid ? get_source_file_name(debug_gid) : "";
  728.         debug_file_display( debug_filename );
  729.     }
  730.  
  731.     if (debug_gid) {
  732.         current_line = debug_lineno;
  733.         center_cursor();
  734.         highlight_line( debug_color_highlight );
  735.     }
  736.  
  737. }
  738.  
  739.  
  740. local    currentFrame = 1;
  741.  
  742. # Gid is the function_id of the function being executed.
  743. # lineno is the line number in that function.
  744. #
  745. function debug_fun(gid,lineno)
  746. {
  747.     local    fn;
  748.     local    i,ln;
  749.     local    x;
  750.  
  751.     # If we are performing a debug_step function,
  752.     # keep going until we get back to the function
  753.     # we did the step in or stepping out of.
  754.     #
  755.     if (debug_step_gid && (gid != debug_step_gid)) {
  756.         if ( debug_get_frame(currentFrame) ) {
  757.             debug_function(debug_id)
  758.             return;
  759.         }
  760.     }
  761.  
  762.     if (debug_num_steps) {
  763.         if (debug_num_steps != -1)
  764.             --debug_num_steps;
  765.         if (debug_num_steps) {
  766.             if (!keyboard_input_pending || debug_step_gid) {
  767.                 original_window = current_window
  768.                 original_buffer = current_buffer
  769.  
  770.                 if (debug_gid != gid) {
  771.                     debug_filename = gid ? get_source_file_name(gid) : "";
  772.                     debug_gid = gid;
  773.                 }
  774.  
  775.                 debug_lineno = lineno;
  776.                 unhighlight_line();
  777.                 debug_at();
  778.                 if (!debug_gid)
  779.                     highlight_line( debug_color_highlight ); 
  780.     display_update();
  781.  
  782.                 assign_current_window( original_window );
  783.                 current_buffer = original_buffer;
  784.  
  785.                 debug_function(debug_id)
  786.  
  787.                 return;
  788.             }
  789.             if (!debug_step_gid)
  790.                 getkey();
  791.             debug_num_steps = 0;
  792.         }
  793.         debug_step_gid = 0;
  794.     }
  795.  
  796.     # If we are performing a debug_go function, keep going
  797.     # until a breakpoint is reached.
  798.     # We remember the first line number of each function.
  799.     if (debug_go_mode) {
  800.         if ( (gid in debug_fun_breakpoints) &&
  801.             and(debug_fun_bp_types[gid], BP_ENABLED) &&
  802.                     (!debug_fun_breakpoints[gid] ||
  803.                     (debug_fun_breakpoints[gid] == lineno))){
  804.             if (!debug_fun_breakpoints[gid])
  805.                 debug_fun_breakpoints[gid] = lineno;
  806.             if (and(debug_fun_bp_types[gid], BP_GOTO_POINT))
  807.                 debug_remove_goto_point( gid );
  808.         } else if (lineno in debug_bp_linenos) {
  809.             fn = gid ? get_source_file_name( gid ) ":" lineno : ""
  810.             if ( !((fn in debug_fun_breakpoints) &&
  811.                     (and(debug_fun_bp_types[fn], BP_ENABLED))) ) {
  812.                 debug_function(debug_id)
  813.                 return;
  814.             }
  815.             delete( debug_bp_linenos );
  816.             for (i in debug_fun_breakpoints)
  817.                 if ( (ln = debug_fun_breakpoints[i]) )
  818.                     debug_bp_linenos[ ln ] = ln;
  819.         } else {
  820.             debug_function(debug_id)
  821.             return;
  822.         }
  823.         debug_go_mode = 0;
  824.         debug_num_steps = 0;
  825.     }
  826.     
  827.     if (debug_gid != gid) {
  828.         debug_filename = gid ? get_source_file_name(gid) : "";
  829.         debug_gid = gid;
  830.     }
  831.  
  832.     debug_lineno = lineno;
  833.  
  834.     for (currentFrame=0; debug_get_frame(currentFrame+1); currentFrame++)
  835.         continue;
  836.  
  837.     remove_break_handler()
  838.     if ( debug_session() ) {
  839.         debug_function(debug_id)
  840.         attach_break_handler()
  841.     }
  842. }
  843.  
  844. local function debug_remove_goto_point( gid ){
  845.     delete( debug_fun_breakpoints[gid] )
  846.     delete( debug_fun_bp_types[gid] )
  847.     delete( debug_fun_breakpoint_names[gid] )
  848. }
  849.  
  850. local function bpindex_to_gid( index ){
  851.     local    gid;
  852.  
  853.     for( gid in debug_fun_bp_types) {
  854.         if (!index) return gid;
  855.         index--;
  856.     }
  857.     return 0;
  858. }
  859.  
  860.  
  861. #-------------------------------------------------------------------
  862. #
  863. #                      Keymap bound functions
  864. #
  865. #-------------------------------------------------------------------
  866.  
  867.  
  868. function debug_left(){ 
  869.     left();
  870.     if (current_column < command_mode+1) {
  871.         scroll_horizontal( -display_width );
  872.         right();
  873.     }
  874. }
  875. function debug_up(){ 
  876.     if (command_mode)
  877.         up(); 
  878.     else {
  879.         up(); 
  880.         highlight_line( debug_color_highlight ); 
  881.     }
  882. }
  883. function debug_down(){ 
  884.     if (command_mode)
  885.         down(); 
  886.     else {
  887.         down(); 
  888.         highlight_line( debug_color_highlight );
  889.     }
  890. }
  891. function debug_bol(){ 
  892.     goto_bol(); 
  893.     scroll_horizontal( -display_width ); 
  894.     right(); 
  895. }
  896. function debug_page_up(){ 
  897.     if (command_mode) { 
  898.         page_up(); current_column = 2;
  899.     } else { 
  900.         page_up();
  901.         highlight_line( debug_color_highlight );
  902.     }
  903. }
  904. function debug_page_dn(){
  905.     if (command_mode) { 
  906.         page_down(); current_column = 2;
  907.     } else { 
  908.         page_down();
  909.         highlight_line( debug_color_highlight );
  910.     }
  911. }
  912. function debug_home(){ 
  913.     goto_buffer_top(); 
  914.     scroll_window_top();
  915.     current_column = command_mode+1; 
  916.     highlight_line( debug_color_highlight );
  917. }
  918. function debug_end(){ 
  919.     goto_buffer_bottom(); 
  920.     scroll_window_bottom();
  921.     current_column = command_mode+1; 
  922.     highlight_line( debug_color_highlight );
  923. }
  924. function debug_backspace(){ 
  925.     if (!command_mode)
  926.         current_window = debug_command_window;
  927.  
  928.     if (current_column > 2) {
  929.         backspace(); 
  930.     }
  931.     
  932.     if (!command_mode)
  933.         current_window = debug_window;
  934. }
  935. function debug_delete_chars(){ 
  936.     if (!command_mode)
  937.         current_window = debug_command_window;
  938.     if (current_column <= current_line_width) {
  939.         delete_chars(1); 
  940.     }
  941.     if (!command_mode)
  942.         current_window = debug_window;
  943. }
  944. function debug_insert_key(){
  945.     if (!command_mode)
  946.         current_window = debug_command_window;
  947.     insert_key( current_key );
  948.     if (!command_mode)
  949.         current_window = debug_window;
  950. }
  951. function debug_resize_window(){
  952.     local    cw = current_window;
  953.  
  954.     if (((current_key == CTRL_G) && command_mode) ||
  955.         ((current_key == CTRL_T) && !command_mode)) {
  956.          current_window = debug_window;
  957.         if (window_height > 3 ) {
  958.             # make the command window larger
  959.              frame_window( window_x0, window_y0, \
  960.                 window_width, window_height - 1 );
  961.             current_window = debug_command_window;
  962.             frame_window( window_x0, window_y0 - 1, \
  963.                 window_width, window_height + 1);
  964.         } 
  965.     } else {
  966.         current_window = debug_command_window;
  967.         if (window_height > 3 ) {
  968.             # make the debug window larger
  969.             frame_window( window_x0, window_y0 + 1, \
  970.                 window_width, window_height - 1);
  971.              current_window = debug_window;
  972.              frame_window( window_x0, window_y0, \
  973.                 window_width, window_height + 1 );
  974.         }
  975.     }
  976.     assign_current_window( cw );
  977. }
  978. function debug_toggle_windows(){
  979.     if ( (command_mode = !command_mode) ) {
  980.         current_window = debug_command_window;
  981.         pop_keymap();
  982.         push_keymap( debug_command_keymap );
  983.     } else {
  984.         current_window = debug_window;
  985.         pop_keymap();
  986.         push_keymap( debug_keymap );
  987.     }
  988. }
  989. function debug_message( str ){
  990.     if (current_window == debug_command_window)
  991.         insert_string( str );
  992.     else
  993.         notify( str );
  994. }
  995.  
  996. function debug_newline( no_prmpt ){
  997.     if (current_window == debug_command_window) {
  998.         insert_newline();
  999.         insert_key( ord(no_prmpt ? " " : ">") );
  1000.         delete_to_eol();
  1001.     }
  1002. }
  1003.  
  1004. function debug_help()
  1005. {
  1006.     display_help_item( "debug" );
  1007. }
  1008.  
  1009. function debug_enter(){
  1010.     local    cmnd;
  1011.     local    cw = current_window;
  1012.     local    cb = current_buffer;
  1013.     local    ch;
  1014.     local    str;
  1015.     local    orig_cmnd;
  1016.     local    upper_cmnd;
  1017.     local    nch;
  1018.     local    id;
  1019.  
  1020.     current_window = debug_command_window;
  1021.     current_buffer = debug_command_buffer;
  1022.  
  1023.     # read the command from the current line
  1024.     #
  1025.     current_column = 2;
  1026.     cmnd = read_buffer();
  1027.     goto_buffer_bottom();
  1028.  
  1029.     debug_newline();
  1030.  
  1031.     if (distance_to_window_bottom() < 0)
  1032.         scroll_window_bottom();
  1033.     else if (distance_to_window_top() < 0)
  1034.         scroll_window_top();
  1035.  
  1036.     orig_cmnd = cmnd;
  1037.     cmnd = compress( ltrim( trim( cmnd, " \t" ), " \t" ), " \t" );
  1038.     upper_cmnd = toupper( cmnd );
  1039.     ch = substr(upper_cmnd,1,1);
  1040.  
  1041.     if (cmnd) {
  1042.         ch == toupper( substr(cmnd,1,1) );
  1043.         if (ch == "B") {
  1044.             # Breakpoints
  1045.             #
  1046.             cmnd = substr( cmnd, 2 );
  1047.             ch = toupper( substr( cmnd,1,1 ));
  1048.             if (upper_cmnd == "BL") {
  1049.                 bl();
  1050.             } else if (ch == "P") {
  1051.                 bp( substr( cmnd,2 ) );
  1052.             } else {
  1053.                 str = ltrim( substr( cmnd,2 ));
  1054.                 if (ch == "C")
  1055.                     bc( str );
  1056.                 else if (ch == "E")
  1057.                     be( str );
  1058.                 else if (ch == "D")
  1059.                     bd( str );
  1060.                 else
  1061.                     debug_bad_command( orig_cmnd );
  1062.             }
  1063.         } else if ( (id = function_id( cmnd )) ) {
  1064.             assign_current_window( original_window );
  1065.             current_buffer = original_buffer;
  1066.             execute_function( id );
  1067.         } else {
  1068.             if (cmnd == ".") {
  1069.                 # Restore position
  1070.                 #
  1071.                 debug_at();
  1072.             } else if (ch == "?") {
  1073.                 # Query
  1074.                 #
  1075.                 debug_query( ltrim(trim(substr( cmnd,2 ))));
  1076.             } else if (upper_cmnd == "E") {
  1077.                 # Execute
  1078.                 #
  1079.                 debug_num_steps = -1;
  1080.                 debug_trace();
  1081.             } else if (ch == "G") {
  1082.                 # Go
  1083.                 #
  1084.                 cmnd = ltrim( substr( cmnd,2 ));
  1085.                 if (cmnd != "") {
  1086.                     debug_go_mode = 1
  1087.                     if (bp( cmnd ))
  1088.                         debug_go();
  1089.                 } else
  1090.                     debug_go();
  1091.             } else if (upper_cmnd == "H") {
  1092.                 # Help
  1093.                 #
  1094.                 debug_help();
  1095.             } else if (ch == "P") {
  1096.                 # Step over
  1097.                 #
  1098.                 cmnd = ltrim( substr( cmnd,2 ));
  1099.                 if (cmnd != "") {
  1100.                     if ( (debug_num_steps = atoi( cmnd )) > 0 );
  1101.                         debug_step();
  1102.                 } else
  1103.                     debug_step();
  1104.             } else if ((upper_cmnd == "Q") || (upper_cmnd == "EXIT")) {
  1105.                 # Quit
  1106.                 #
  1107.                 debug_esc();
  1108.             } else if (cmnd== "@") {
  1109.                 # redraw display
  1110.                 #
  1111.                 display_redraw();
  1112.             } else if (cmnd == "K" || cmnd == "k") {
  1113.                 # Stack Trace
  1114.                 #
  1115.                 debug_callstack();
  1116.             } else if (ch == "#") {
  1117.                 # Tabs
  1118.                 #
  1119.                 current_window = debug_window;
  1120.                 current_buffer = debug_buffer;
  1121.                 debug_tabs =
  1122.                 buffer_tabs = substr( cmnd,2 );
  1123.                 display_update();
  1124.                 current_window = debug_command_window;
  1125.                 current_buffer = debug_command_buffer;
  1126.             } else if (ch == "T") {
  1127.                 # Trace
  1128.                 #
  1129.                 cmnd = ltrim( substr( cmnd,2 ));
  1130.                 if (cmnd != "") {
  1131.                     if ( (debug_num_steps = atoi( cmnd )) > 0);
  1132.                         debug_trace();
  1133.                 } else
  1134.                     debug_trace();
  1135.             } else if (ch == "V") {
  1136.                 # View new file
  1137.                 #
  1138.                  current_window = debug_window;
  1139.                 current_buffer = debug_buffer;
  1140.  
  1141.                 debug_view( substr( cmnd,2 ) );
  1142.                  current_window = debug_command_window;
  1143.                 current_buffer = debug_command_buffer;
  1144.             } else if (ch == "/") {
  1145.                 # Search
  1146.                 #
  1147.                  current_window = debug_window;
  1148.                 current_buffer = debug_buffer;
  1149.                 debug_search( orig_cmnd );
  1150.                  current_window = debug_command_window;
  1151.                 current_buffer = debug_command_buffer;
  1152.             } else if (ch == "O") {
  1153.                 cmnd = substr( cmnd, 2 );
  1154.                 ch = toupper( substr( cmnd,1,1 ));
  1155.                 nch = toupper( ltrim(substr( cmnd, 2 )));
  1156.                 if (ch == "R") {
  1157.                     # regex searching option
  1158.                     if (nch == "+")
  1159.                         debug_search_flags = or( debug_search_flags, SEARCH_REGEX )
  1160.                     else if (nch == "-")
  1161.                         debug_search_flags = and( debug_search_flags, not(SEARCH_REGEX) )
  1162.                     else 
  1163.                         debug_bad_command( orig_cmnd );
  1164.                     debug_show_options( OR_OPTION );
  1165.                 } else if (ch == "F") {
  1166.                     # flipping screen
  1167.                     if (nch == "+")
  1168.                         debug_flip = 1;
  1169.                     else if (nch == "-")
  1170.                         debug_flip = 0;
  1171.                     else debug_bad_command( orig_cmnd );
  1172.                     debug_show_options( OF_OPTION );
  1173.                 } else if (ch == "C") {
  1174.                     # case sensitive searching option
  1175.                     if (nch == "+")
  1176.                         debug_search_flags = and( debug_search_flags, not(SEARCH_IGNORE_CASE) )
  1177.                     else if (nch == "-")
  1178.                         debug_search_flags = or( debug_search_flags, SEARCH_IGNORE_CASE )
  1179.                     else 
  1180.                         debug_bad_command( orig_cmnd );
  1181.                     debug_show_options( OC_OPTION );
  1182.                 } else if (ch == "") {
  1183.                     debug_show_options( O_OPTION );
  1184.                 } else {
  1185.                     debug_bad_command( orig_cmnd );
  1186.                 }
  1187.             } else {
  1188.                 debug_bad_command( orig_cmnd );
  1189.             }
  1190.         }
  1191.     }
  1192.  
  1193.  
  1194.     if (distance_to_window_bottom() < 0)
  1195.         scroll_window_bottom();
  1196.     else if (distance_to_window_top() < 0)
  1197.         scroll_window_top();
  1198.  
  1199.  
  1200.     assign_current_window( cw );
  1201.     current_buffer = cb;
  1202. }
  1203.  
  1204. function debug_bad_command( cmnd ){
  1205.     debug_message( "Unknown command: " cmnd );
  1206.     debug_newline();
  1207. }
  1208.  
  1209.  
  1210. function debug_left_press(){
  1211.     local    mp;
  1212.     local    wc = window_containing( mouse_event_x, mouse_event_y );
  1213.  
  1214.     if (wc == debug_window) {
  1215.         current_window = debug_window;
  1216.         command_mode = 0;
  1217.     } else if (wc == debug_command_window) {
  1218.         current_window = debug_command_window;
  1219.         command_mode = 1;
  1220.     } else
  1221.         return;
  1222.  
  1223.     if (window_border_contains( mouse_event_x, mouse_event_y, debug_window ) ||
  1224.       window_border_contains( mouse_event_x, mouse_event_y, debug_command_window )) {
  1225.         mp = mouse_position( 1 );
  1226.         if ( and(mp, MOUSE_N + MOUSE_E ) && !and(mp, MOUSE_W) ) {
  1227.             if (!command_mode) 
  1228.                 unhighlight_line();
  1229.             left_press( 1 );
  1230.             if (!command_mode) 
  1231.                 highlight_line( debug_color_highlight );
  1232.         }
  1233.     }
  1234. }
  1235.  
  1236.  
  1237. local    last_search = "";
  1238. local    debug_search_flags = 0;
  1239.  
  1240. function debug_search( cmnd ){
  1241.     if (!debug_search_flags)
  1242.         debug_search_flags = SEARCH_FORWARD    + \
  1243.                     SEARCH_IGNORE_CASE + \
  1244.                     SEARCH_ADVANCE    + \
  1245.                     SEARCH_WRAPS    + \
  1246.                     SEARCH_MAXIMAL_MATCH;
  1247.  
  1248.     if ( length( cmnd ) > index( cmnd, "/") )
  1249.         last_search = substr( cmnd, index( cmnd, "/" )+1 );
  1250.  
  1251.     if (search( last_search, debug_search_flags ))
  1252.         center_cursor();
  1253.     highlight_line( debug_color_highlight );
  1254. }
  1255.  
  1256. function debug_view( fname ){
  1257.     local    cb = current_buffer;
  1258.     local def_buf_eol = default_buffer_eol_string;
  1259.  
  1260.  
  1261.     fname = ltrim( trim( fname ) )
  1262.  
  1263.     default_buffer_eol_string = "\r\n"
  1264.     current_buffer = create_buffer( \
  1265.             "FILE: " path_fname(fname) path_ext(fname),
  1266.             fname,
  1267.             BUFFER_SYSTEM + BUFFER_NO_UNDO + BUFFER_READ_ONLY)
  1268.     default_buffer_eol_string = def_buf_eol;
  1269.  
  1270.     if (buffer_size) {
  1271.         buffer_tabs = debug_tabs;
  1272.  
  1273.         delete_buffer( debug_buffer )
  1274.         debug_buffer = current_buffer;
  1275.  
  1276.         debug_view_file = fname;
  1277.         attach_window_buffer( debug_window, debug_buffer)
  1278.     }
  1279.  
  1280.     current_buffer = cb;
  1281. }
  1282.  
  1283.  
  1284. #
  1285. # options settings to be shown
  1286. #
  1287. local OR_OPTION = 0x01
  1288. local OF_OPTION = 0x02
  1289. local OC_OPTION = 0x04
  1290. local O_OPTION  = 0x07
  1291.  
  1292. local function debug_show_options( option ){
  1293.     if ( and(option, OR_OPTION) ) {
  1294.         if (and(debug_search_flags, SEARCH_REGEX))
  1295.             debug_message( "Regular Expression Searching On.")
  1296.         else
  1297.             debug_message( "Regular Expression Searching Off.")
  1298.         debug_newline();
  1299.     }
  1300.     if ( and(option, OF_OPTION) ) {
  1301.         if (debug_flip)
  1302.             debug_message( "Window Flipping On.")
  1303.         else
  1304.             debug_message( "Window Flipping Off.")
  1305.         debug_newline();
  1306.     }
  1307.     if ( and(option, OC_OPTION) ) {
  1308.         if (and(debug_search_flags, SEARCH_IGNORE_CASE))
  1309.             debug_message( "Case Searching Off.")
  1310.         else
  1311.             debug_message( "Case Searching On.")
  1312.         debug_newline();
  1313.     }
  1314. }
  1315.  
  1316.  
  1317.  
  1318. local y_highlight = -1;
  1319. local y_ext = -1;
  1320. local x_ext = -1;
  1321.  
  1322. local function highlight_line( attr ){
  1323.  
  1324.  
  1325.     display_update();    # this will set window_first appropriately
  1326.     unhighlight_line();
  1327.  
  1328.     y_highlight = debug_lineno - window_first;
  1329.  
  1330.     y_ext = window_text_height;
  1331.     x_ext = window_text_width;
  1332.  
  1333.     if ((y_highlight < 0) || (y_highlight >= y_ext))
  1334.         return;
  1335.  
  1336.     highlight_window( 0, y_highlight, x_ext, 1, attr, debug_window );
  1337. }
  1338.  
  1339. local function unhighlight_line(){
  1340.  
  1341.     if (breakpoints_visible) {
  1342.         breakpoints_visible = 0;
  1343.         display_redraw();
  1344.     } else {
  1345.         # use the last highlighted line setting to unhighlight
  1346.         #
  1347.         if ((y_highlight >= 0) && (y_highlight < y_ext))
  1348.             highlight_window( 0, y_highlight, x_ext, 1, debug_color_text,
  1349.                 debug_window );
  1350.     }
  1351.     y_highlight = -1;
  1352. }
  1353.  
  1354.  
  1355.  
  1356. local function get_source_file_name( gid ){
  1357.     local    fn = source_file_name( gid );
  1358.     local    src_name;
  1359.  
  1360.     if (findfirst( fn ) == "")
  1361.         return buildpath( path_fname( fn ) path_ext( fn ) );
  1362.     return fn;
  1363. }
  1364.  
  1365. global function debug_ctrl_break(){
  1366.     debug_num_steps = 0;
  1367.     debug_go_mode = 0;
  1368. }
  1369.  
  1370.  
  1371. function attach_break_handler(){
  1372.     if (!ctrl_break_attached) {
  1373.         attach_event_handler( EVENT_CTRL_BREAK, function_id( "debug_ctrl_break" ));
  1374.         ctrl_break_attached = 1;
  1375.     }
  1376. }
  1377.  
  1378.  
  1379. function remove_break_handler(){
  1380.     if (ctrl_break_attached) {
  1381.         delete_event( EVENT_CTRL_BREAK, function_id( "debug_ctrl_break" ));
  1382.         ctrl_break_attached = 0;
  1383.     }
  1384. }
  1385.  
  1386.