Branch: refs/heads/master Author: Dimitar Zhekov dimitar.zhekov@gmail.com Committer: Dimitar Zhekov dimitar.zhekov@gmail.com Date: Mon, 24 Jun 2013 18:07:01 UTC Commit: 0e1fa2d3980cf1891b2d9603e522d3fd827da23d https://github.com/geany/geany-plugins/commit/0e1fa2d3980cf1891b2d9603e522d3...
Log Message: ----------- scope - added Registers, small changes and fixes; v0.90
Modified Paths: -------------- scope/ChangeLog scope/NEWS scope/NOTES scope/TODO scope/data/scope.glade scope/docs/codes.html scope/docs/scope.html scope/src/Makefile.am scope/src/break.c scope/src/common.h scope/src/conterm.c scope/src/debug.c scope/src/debug.h scope/src/inspect.c scope/src/inspect.h scope/src/local.c scope/src/parse.c scope/src/program.c scope/src/register.c scope/src/register.h scope/src/scope.c scope/src/stack.c scope/src/thread.c scope/src/utils.c scope/src/utils.h scope/src/views.c scope/src/views.h
Modified: scope/ChangeLog 37 files changed, 37 insertions(+), 0 deletions(-) =================================================================== @@ -1,3 +1,40 @@ +2013-06-24 Dimitar Zhekov dimitar.zhekov@gmail.com + + * data/scope.glade, docs/codes.html, docs/scope.html, + src/Makefile.am, src/break.c, src/common.h, src/debug.c, + src/inspect.c, src/inspect.h, src/parse.c, src/program.c, + src/register.c, src/register.h, src/scope.c, src/stack.c, + src/thread.c, src/views.c, src/views.h: + Added Registers next to Inspect. + * docs/codes.html: + Small syntax changes, explanation about the <> values. + * docs/scope.html, src/break.c, src/debug.c, src/debug.h, + src/local.c, src/stack.c, src/views.c, src/thread.c, + src/views.c, src/views.h: + Small syntax changes/fixes. + * src/conterm.c: + Clear the console with a single function call. + * src/inspect.c: + Fixed hexadecimal format. + Only set "editable" if an eleemnt is selected. + * src/common.h, src/local.src/utils.c, src/utils.h: + A (mostly) common mechanism to send/receive thread+frame. + * src/utils.c: + Display win32 error texts instead of codes. + * src/views.c: + Changing the thread/frame honours "Update all views". + Fixed the automatic text selection when the command dialog + is invoked. + * docs/scope.html, src/scope.c: + Increased version to 0.90. + + +2013-05-23 Dimitar Zhekov dimitar.zhekov@gmail.com + + * scope/src/inspect.c: + Fixed new value receiving after Format change. + + 2013-05-17 Dimitar Zhekov dimitar.zhekov@gmail.com
* scope/src/prefs.c:
Modified: scope/NEWS 9 files changed, 9 insertions(+), 0 deletions(-) =================================================================== @@ -1,3 +1,12 @@ +Scope 0.90 (2013-05-17) + + * Added Registers next to Inspect. + + * Display win32 error texts instead of codes. + + * Changing the thread/frame honours "Update all views". + + Scope 0.89 (2013-05-17)
* Small fixes and improvements. This should be the last version
Modified: scope/NOTES 79 files changed, 31 insertions(+), 48 deletions(-) =================================================================== @@ -1,3 +1,7 @@ +register modified is 07 since we may have watches and inspects containing +registers, and changing a register ($dh, $mm1.uint64) may change another +($dx, $st1); even if local variables can't be changed, that's enough + when switching to stack...memory and update is not possible, the subpage contents will be kept if an update command for this page was sent on the last thread stop/changed; otherwise it'll be cleared @@ -5,14 +9,14 @@ last thread stop/changed; otherwise it'll be cleared "^done,value="", '7' matches 07-var-assign, handled later as "^done", '7'
the only way to fix unnecessary inspect drop target expansion is to block -INTO, so deriving GtkTreeStore and altering GtkTreeDragDest make no sense +INTO, so deriving GtkTreeStore and altering GtkTreeDragDest makes no sense
"new_children: If new children were added to a dynamic varobj [...]" "A varobj's contents may be provided by a Python-based pretty-printer In this case the varobj is known as a dynamic varobj" - not supported
shift-clicking send/busy to send a command without closing the dialog can be -implemented, but is very ugly; shortcut for GDB command plus typing in the +implemented, but is very ugly; shortcut for "GDB command" plus typing in the debug console should suffice
gtk tooltips send lots of queries, and can't be explicitly shown/hidden; @@ -28,21 +32,21 @@ mixed with the program stdin/stdout, leading to gigo in foreground execution, GDB waits for the program to report that _some_ thread has stopped before prompting for another command
-clicking a button with response 0, and then gtk_dialog_response(ACCEPT) via -program code or clicking an accept button, may still generate 0 +clicking a button with response 0, and then clicking an accept button or +gtk_dialog_response(ACCEPT), may generate 0 instead of accept
breakpoints don't need unapply: they can be disabled, and all relevant columns are editable
--var-create for globals symbols allows any frame +-var-create for global symbols allows any frame -set-update-range seems to have no effect on my system
-global object may be evaluated (including as variable objects) in hang +global objects may be evaluated (including as variable objects) in hang state, but modification requires running inferior
parse with string in VR_COMPACT / VR_NEUTRAL is slower for texts with less than 100 characters, but with such shorts texts, the difference is -insignificant; with large texts, using string is faster, but not much +insignificant; for large texts, using string is faster, but not much
CPU load on F8 with vte console: ~88% with context: ~80%, null output: ~75% @@ -50,11 +54,11 @@ with context: ~80%, null output: ~75% win~1 hang with poll_pipe(): 1 second for 3h25m win~1 send on 50ms: 2 seconds for 1h, 1445 KB sent
-GtkTextView with wrapping CHAR: the last character of a wrapped line can not -be selected with the mouse, keyboard selection is ok +GtkTextView with wrapping CHAR: the last character of a wrapped line can be +selected with the mouse only by moving to the next line
-Geany under Win~1 with FF also running eats 7-8% CPU time other -applications/conditions may cause this CPU load too +Geany under Win~1, with FF also running, eats 7-8% CPU time, other +applications/conditions may cause such CPU load too; scope doesn't matter
http://sourceware.org/bugzilla/show_bug.cgi?id=9659
@@ -65,7 +69,7 @@ set print elements 10: "\a01\002\003\004\005\006\a\b\t\n"... '\000' <repeats 100 times>, '\001' <repeats 100 times>
GDB does specify that individual breakpoint location may be enabled or -disabled, but not deleted; no mention of condition, ignore, script though +disabled, but not deleted; no mention of condition/ignore/script though
pending breakpoints are handled either at thread stopped, or by async modified message; parsing =library-loaded seems pointless @@ -82,10 +86,6 @@ count -i -break-passcount -break-after script = -break-commands fast trace = -break-insert -a -h
-source files check list: - :break :debug :inspect :local :menu :parse :plugme :prefs - :program :scope :stack :thread :unused :utils :views :watch - " " is valid executable name, but not valid source name - gdb requires certain suffixes (.c .c++ etc.); thus we can validate_column(file, TRUE)
@@ -94,27 +94,20 @@ project close: geany close message, then scope message
gdb manual states that "which commands will work in the context of a running thread is highly target dependent", but "commands that try to operate on -thread's stack will not work, on any target"; some commands are ds_sendable -or ds_not_busy, even if unlikely to execute (for example global watchpoint) - -scid is required because the list positions are async-gdb-output volatile - -there is no reason to keep the stack frame selection, the upper-frame values -are unlikely to change +thread's stack will not work, on any target"; some commands are DS_SENDABLE +or DS_NOT_BUSY, even if unlikely to execute (like a global watchpoint)
-there is no reason to clear thread list on regular thread info, the async -messages keep it current +scid is required because all list positions are async-gdb-output volatile
break filename may be specified as known source name (test.c) or absolute -name (/home/build/test.c); names relative to inferior working directory -do not work any more than these relative to gdb directory +name (/home/build/test.c); neither inferior nor gdb relative names work
would be nice to have 02-thread-info to fully refresh the thread list, if we -missed a thread message, but needs effort, and we compute gdb status (and -send commands) based on threads, so that's a circular dependency +missed a thread message, but needs some effort, and we compute gdb status +(and send commands) based on threads, so that'll be very tricky
-gdb recommends full refresh after error but errors in refresh (04) commands -must be ignored to avoid an endless loop +gdb recommends full refresh after error, but at least the errors from +refresh (04) commands errors must be ignored avoid an endless loop
applying break/watchpoints to a thread is promlematic: -break-list does not contain such info, and the thread identifiers are different on restart @@ -122,30 +115,20 @@ contain such info, and the thread identifiers are different on restart tested with "unsuccessful" program pty creation - no idea where the terminal I/O comes from or goes to
-we don't reload terminal prefs on save settings since they are either empty, -for new file, or old (the signal is before save) +we don't reload terminal prefs on save settings since the signal is before +save and they are they are either empty (for new .conf file) or old
scite mark "arrow" is actually triangle
-> Run in a debugger with the G_DEBUG env var set to "fatal-warnings", -> so the program will abort and let you see where/when/how it happened. - --var-list-children expands an expression (or -variable?) with a single command - --var-delete -c VAR deletes the children only - --var-info|evaluate-expression for unexpanded? - --all | --thread-group N commands: -exec-continue -exec-interrupt -exec-run
-"If the `--thread-group' options is specified, then -all threads in that thread group are resumed." +"If the `--thread-group' options is specified, then all threads in that +thread group are resumed."
-*stopped "all" means all threads from this group? +*stopped "all" means from this group or everything?
-running "all" does not specify a thread; the first running is "all", others -are thread - but that's from experience only, gdb.info says nothing +running "all" does not specify a thread/group; the first running is "all", +others are thread - but that's from observation, gdb.info says nothing
Modified: scope/TODO 2 files changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -1,3 +1,5 @@ +proper support for @ inspect frame + various tests, source code checks etc.
add clear icon to entries? not very useful
Modified: scope/data/scope.glade 172 files changed, 167 insertions(+), 5 deletions(-) =================================================================== @@ -1197,6 +1197,99 @@ </object> </child> </object> + <object class="GtkMenu" id="register_menu"> + <child> + <object class="GtkImageMenuItem" id="register_refresh"> + <property name="label">gtk-refresh</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="register_separator1"> + <property name="visible">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="register_copy"> + <property name="label">gtk-copy</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + <child> + <object class="GtkMenuItem" id="register_format"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Format</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="register_format_menu"> + <child> + <object class="GtkRadioMenuItem" id="register_format_natural"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Natural</property> + <property name="use_underline">True</property> + </object> + </child> + <child> + <object class="GtkRadioMenuItem" id="register_format_hex"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Hex</property> + <property name="use_underline">True</property> + <property name="group">register_format_natural</property> + </object> + </child> + <child> + <object class="GtkRadioMenuItem" id="register_format_decimal"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Decimal</property> + <property name="use_underline">True</property> + <property name="group">register_format_natural</property> + </object> + </child> + <child> + <object class="GtkRadioMenuItem" id="register_format_octal"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Octal</property> + <property name="use_underline">True</property> + <property name="group">register_format_natural</property> + </object> + </child> + <child> + <object class="GtkRadioMenuItem" id="register_format_binary"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Binary</property> + <property name="use_underline">True</property> + <property name="group">register_format_natural</property> + </object> + </child> + <child> + <object class="GtkRadioMenuItem" id="register_format_raw"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Raw</property> + <property name="use_underline">True</property> + <property name="group">register_format_natural</property> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="register_separator2"> + <property name="visible">True</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="register_query"> + <property name="visible">True</property> + <property name="label">_Query</property> + <property name="use_underline">True</property> + </object> + </child> + </object> <object class="GtkMenuItem" id="popup_item"> <property name="visible">True</property> <property name="label" translatable="yes">Debu_g</property> @@ -1432,6 +1525,25 @@ <column type="gchararray" utf8_collate="false"/> </columns> </object> + <object class="ScpTreeStore" id="register_store"> + <property name="sublevels">True</property> + <columns> + <!-- column-name register_store_path --> + <column type="gchararray" utf8_collate="false"/> + <!-- column-name register_store_display --> + <column type="gchararray" utf8_collate="false"/> + <!-- column-name register_store_value --> + <column type="gchararray" utf8_collate="false"/> + <!-- column-name register_hb_mode --> + <column type="gint"/> + <!-- column-name register_store_name --> + <column type="gchararray" utf8_collate="false"/> + <!-- column-name register_store_id --> + <column type="gint"/> + <!-- column-name register_store_format --> + <column type="gint"/> + </columns> + </object> <object class="ScpTreeStore" id="command_store"> <property name="sublevels">False</property> <columns> @@ -2132,6 +2244,52 @@ </object> </child> </object> + <object class="GtkFrame" id="register_page"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label_xalign">0</property> + <property name="shadow_type">in</property> + <child> + <object class="GtkScrolledWindow" id="register_window"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <object class="GtkTreeView" id="register_view"> + <property name="can_focus">True</property> + <property name="model">register_store</property> + <property name="headers_visible">False</property> + <property name="headers_clickable">False</property> + <child> + <object class="GtkTreeViewColumn" id="register_name_column"> + <property name="resizable">True</property> + <property name="sizing">autosize</property> + <child> + <object class="GtkCellRendererText" id="register_name"/> + <attributes> + <attribute name="text">4</attribute> + </attributes> + </child> + </object> + </child> + <child> + <object class="GtkTreeViewColumn" id="register_display_column"> + <property name="resizable">True</property> + <property name="expand">True</property> + <child> + <object class="GtkCellRendererText" id="register_display"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + </object> + </child> + </object> + </child> + </object> <object class="GtkDialog" id="command_dialog"> <property name="modal">True</property> <property name="type_hint">normal</property> @@ -2682,7 +2840,7 @@ <property name="spacing">6</property> <child> <object class="GtkCheckButton" id="program_delete_all_items"> - <property name="label" translatable="yes">_Delete all breakpoints, watches and inspects</property> + <property name="label" translatable="yes">_Delete all breakpoints, watches, inspects and registers</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> @@ -3772,13 +3930,17 @@ <property name="visible">True</property> <property name="label" translatable="yes">Inspect</property> </object> + <object class="GtkLabel" id="register_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Registers</property> + </object> <object class="GtkSizeGroup" id="program_size_group"> <widgets> - <widget name="program_load_script_label"/> - <widget name="program_working_dir_label"/> - <widget name="program_environment_label"/> - <widget name="program_arguments_label"/> <widget name="program_executable_label"/> + <widget name="program_arguments_label"/> + <widget name="program_environment_label"/> + <widget name="program_working_dir_label"/> + <widget name="program_load_script_label"/> </widgets> </object> <object class="GtkSizeGroup" id="inspect_size_group">
Modified: scope/docs/codes.html 50 files changed, 42 insertions(+), 8 deletions(-) =================================================================== @@ -35,6 +35,10 @@ <td class="tab">un/check break enabled column</td> <td class="tab">set breakpoint enabled column, remark breakpoint</td></tr>
+<tr><td class="nowrap">02[01]<scid>-break-disable</td> + <td class="tab">un/check break enabled column</td> + <td class="tab">set breakpoint enabled column, remark breakpoint</td></tr> + <tr><td class="nowrap">022<id>-break-after</td> <td class="tab">breakpoint <em>Ignore</em> column edited</td> <td class="tab"><id>-break-info</td></tr> @@ -87,10 +91,22 @@ <td class="tab"><em>Syncronize</em> stack</td> <td class="tab">select the current gdb frame</td></tr>
-<tr><td class="nowrap">02<tid><fid>-stack-list-variables</td> +<tr><td class="nowrap">02<fid>-stack-list-variables</td> <td class="tab"><em>Refresh</em> locals</td> <td class="tab">clear locals list and load local variables into it</td></tr>
+<tr><td class="nowrap">02-data-list-register-names</td> + <td class="tab"><em>Query</em> register names</td> + <td class="tab">029<fid>-data-list-register-values <all></td> + +<tr><td class="nowrap">029<fid>-data-list-register-values</td> + <td class="tab"><em>Refresh</em> registers, see above</td> + <td class="tab">update register values</td> + +<tr><td class="nowrap">02<f><fid>-data-list-register-values</td> + <td class="tab">change register <em>Format</em></td> + <td class="tab">update register value and/or format</td> + <tr><td class="nowrap"> </td><td class="tab"> </td><td class="tab"> </td></tr>
<tr><td class="nowrap">03<scid>-data-evaluate-expression</td> @@ -101,7 +117,7 @@
<tr><td class="nowrap">04-break-list</td> <td class="tab">views idle update</td> - <td class="tab">same as 02-break-list</td></tr> + <td class="tab">same as 02</td></tr>
<tr><td class="nowrap">04-thread-info <id></td> <td class="tab">thread created -> fetch target id</td> @@ -121,15 +137,15 @@
<tr><td class="nowrap">04<tid>-stack-list-frames</td> <td class="tab">views idle update</td> - <td class="tab">same as 02<tid>-stack-list-frames</td></tr> + <td class="tab">same as 02</td></tr>
<tr><td class="nowrap">04<tid>-stack-list-arguments</td> <td class="tab">views idle update</td> - <td class="tab">same as 02<tid>-stack-list-arguments</td></tr> + <td class="tab">same as 02</td></tr>
-<tr><td class="nowrap">04<tid><fid>-stack-list-variables</td> +<tr><td class="nowrap">04<fid>-stack-list-variables</td> <td class="tab">views idle update</td> - <td class="tab">same as 02<tid>-stack-list-variables</td></tr> + <td class="tab">same as 02</td></tr>
<tr><td class="nowrap">04-data-read-memory-bytes</td> <td class="tab">views idle update</td> @@ -139,6 +155,14 @@ <td class="tab">at stopped thread without address</td> <td class="tab">fill the thread columns</td></tr>
+<tr><td class="nowrap">04<fid>-data-list-changed-registers</td> + <td class="tab">views idle update</td> + <td class="tab">049<fid>-data-list-register-values <changed></td> + +<tr><td class="nowrap">049<fid>-data-list-register-values</td> + <td class="tab">views idle update, see above</td> + <td class="tab">same as 02</td> + <tr><td class="nowrap"> </td><td class="tab"> </td><td class="tab"> </td></tr>
<tr><td class="nowrap">05</td> @@ -147,11 +171,11 @@
<tr><td class="nowrap">05</td> <td class="tab">after temp break insert <em>location</em></td> - <td class="tab">-exec-run if active breaks & no errors</td></tr> + <td class="tab">same as above</td></tr>
<tr><td class="nowrap">05</td> <td class="tab">after temp break insert <em>1st loc</em></td> - <td class="tab">-exec-run if active breaks & no errors</td></tr> + <td class="tab">same as above</td></tr>
<tr><td class="nowrap">05-list-features</td> <td class="tab">first time gdb startup</td> @@ -213,5 +237,15 @@
</table>
+<br> + +<table> +<tr><td><scid></td><td class="tab">internal id assigned by scope</td></tr> +<tr><td><id></td><td class="tab">gdb id</td> +<tr><td><tid></td><td class="tab">selected thread id</td> +<tr><td><fid></td><td class="tab">selected thread and frame id: <length of thread id +- 1><thread id><frame id></td></tr> +</table> + </body> </html>
Modified: scope/docs/scope.html 23 files changed, 16 insertions(+), 7 deletions(-) =================================================================== @@ -51,7 +51,10 @@ <li><a href="#local_watch">Locals/Watches</a></li> <li><a href="#console">Debug Console</a></li> </ul></li> - <li><a href="#inspect">Inspect page</a></li> + <li>Side panel<ul> + <li><a href="#inspect">Inspect</a></li> + <li><a href="#register">Registers</a></li> + </ul></li> </ul></li> <li><a href="#preferences">Preferences</a></li> <li><a href="#notes">Notes</a><ul> @@ -143,7 +146,7 @@ Tools.</li> <li>Debug page in the lower panel, with subpages that display the program output, threads, breakpoints etc.</li> -<li>Inspect page in the side panel.</li> +<li>Inspect and Registers page in the side panel.</li> <li>Toolbar items - identical to their Debug menu counterparts.</li> <li>Command Dialog - to enter gdb commands. Will be closed automatically if gdb exits.</li> <li>A small label on the right of your Geany status bar, which displays the current debugging @@ -412,8 +415,8 @@ <p><b><a name="watch">Watches</a></b></p>
<p>This is a flat list of expressions, evaluated each time the current thread stops or changes -(subject to <em>update_all_views</em>), in the context of the current thread and frame. Unlike -<em>Inspect</em>, any gdb-evaluatable expressions may be used, there is no need to apply +(subject to <em>Update all views</em>), in the context of the current thread and frame. Unlike +<em>Inspect</em>, any gdb-evaluatable expressions may be used, and there is no need to apply them.</p>
<p><b><a name="local_watch">Locals/Watches</a></b></p> @@ -456,7 +459,7 @@ immediately resuming the program execution; or the prompt may be followed by asynchronous messages. The Scope state (Busy, Debug etc.) is more accurate.</p>
-<p><b><a name="inspect">Inspect Page</a></b></p> +<p><b><a name="inspect">Inspect</a></b></p>
<p>All -var-* commands except -var-update will be ignored when entered from the command line, because their output does not provide enough information to identify the variable object.</p> @@ -482,6 +485,12 @@ <p>The format and 7-bit mode are saved only for the top-level variables, not for children (but see <a href="#keeping_modes">Keeping modes</a>).</p>
+<p><b><a name="registers">Registers</a></b></p> + +<p>Scope will query the register names once after a program is loaded, or when the gdb +executable is changed. If you switch to a different architecture, but your gdb name remains +the same, invoke <em>Query</em> from the local menu.</p> + <h3><a name="preferences">Preferences</a></h3>
<p>Once again, trivial items are not included.</p> @@ -491,7 +500,7 @@ <p><em>gdb_buffer_length</em> - the maximum length of a single gdb output message. Longer messages will be cut, and an "overflow" will be displayed in the debug console, possibly followed by a few other parsing errors. Default = 16383. Actual value is (the nearest larger -power of 2) - 1, for example 16384 becomes 65535. +power of 2) - 1, for example 32768 becomes 65535.
<p><em>gdb_wait_death</em> - hundreds of seconds to wait(3) gdb death on scope unload. Default = 20. When closing Geany, gdb will be destroyed by the operating system.</p> @@ -713,7 +722,7 @@
<b><a name="copyright">Copyright</a></b>
-<p>Scope 0.88, Copyright (C) 2013 Dimitar Toshkov Zhekov</p> +<p>Scope 0.90, Copyright (C) 2013 Dimitar Toshkov Zhekov</p>
<p>The menu and toolbar icons are from <a href="http://netbeans.org">Netbeans</a>, except for BreakPoint.</p>
Modified: scope/src/Makefile.am 2 files changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -31,6 +31,8 @@ scope_la_SOURCES = \ prefs.h \ program.c \ program.h \ + register.c \ + register.h \ scope.c \ scope.h \ stack.c \
Modified: scope/src/break.c 4 files changed, 2 insertions(+), 2 deletions(-) =================================================================== @@ -913,7 +913,7 @@ void on_break_toggle(G_GNUC_UNUSED const MenuItem *menu_item) if (found && found != utils_atoi0(id)) { dialogs_show_msgbox(GTK_MESSAGE_INFO, - _("There are two or more breakpoints at %s:%d.\n" + _("There are two or more breakpoints at %s:%d.\n\n" "Use the breakpoint list to remove the exact one."), doc->file_name, doc_line); return; @@ -1130,7 +1130,7 @@ static gboolean on_break_query_tooltip(G_GNUC_UNUSED GtkWidget *widget, gint x, { if (has_tip) g_string_append(text, ", "); - g_string_append(text, func); + g_string_append_printf(text, "%s()", func); has_tip = TRUE; }
Modified: scope/src/common.h 2 files changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -24,6 +24,7 @@ extern GeanyFunctions *geany_functions;
typedef struct _MenuItem MenuItem; +#define FRAME_ARGS '0' + (int) strlen(thread_id) - 1, thread_id, frame_id
#include "break.h" #include "conterm.h" @@ -37,6 +38,7 @@ #include "plugme.h" #include "prefs.h" #include "program.h" +#include "register.h" #include "stack.h" #include "scope.h" #include "store.h"
Modified: scope/src/conterm.c 5 files changed, 1 insertions(+), 4 deletions(-) =================================================================== @@ -301,10 +301,7 @@ void dc_clear(void) else #endif { - GtkTextIter start, end; - - gtk_text_buffer_get_bounds(context, &start, &end); - gtk_text_buffer_delete(context, &start, &end); + gtk_text_buffer_set_text(context, "", -1); dc_chars = 0; } }
Modified: scope/src/debug.c 11 files changed, 6 insertions(+), 5 deletions(-) =================================================================== @@ -581,6 +581,7 @@ static void load_program(void) if (option_open_panel_on_load) open_debug_panel();
+ registers_query_names(); debug_send_commands(); } else @@ -729,18 +730,18 @@ void debug_send_format(gint tf, const char *format, ...) char *debug_send_evaluate(char token, gint scid, const gchar *expr) { char *locale = utils_get_locale_from_utf8(expr); - GString *string = g_string_sized_new(strlen(locale)); + GString *escaped = g_string_sized_new(strlen(locale)); const char *s;
for (s = locale; *s; s++) { if (*s == '"' || *s == '\') - g_string_append_c(string, '\'); - g_string_append_c(string, *s); + g_string_append_c(escaped, '\'); + g_string_append_c(escaped, *s); }
- debug_send_format(F, "0%c%d-data-evaluate-expression "%s"", token, scid, string->str); - g_string_free(string, TRUE); + debug_send_format(F, "0%c%d-data-evaluate-expression "%s"", token, scid, escaped->str); + g_string_free(escaped, TRUE); return locale; }
Modified: scope/src/debug.h 3 files changed, 1 insertions(+), 2 deletions(-) =================================================================== @@ -65,8 +65,7 @@ enum enum { N, T, F }; void debug_send_command(gint tf, const char *command); #define debug_send_thread(command) debug_send_command(T, (command)) -void debug_send_format(gint tf, const char *format, ...) - G_GNUC_PRINTF(2, 3); +void debug_send_format(gint tf, const char *format, ...) G_GNUC_PRINTF(2, 3); char *debug_send_evaluate(char token, gint scid, const gchar *expr); /* == locale(expr) */
void debug_init(void);
Modified: scope/src/inspect.c 45 files changed, 13 insertions(+), 32 deletions(-) =================================================================== @@ -245,8 +245,8 @@ static gint inspect_variable_store(GtkTreeIter *iter, const ParseVariable *var) return format; }
-static const char *const inspect_formats[FORMAT_COUNT] = { "natural", "decimal", "hex", - "octal", "binary" }; +static const char *const inspect_formats[FORMAT_COUNT] = { "natural", "decimal", + "hexadecimal", "octal", "binary" };
void on_inspect_variable(GArray *nodes) { @@ -295,7 +295,7 @@ void on_inspect_format(GArray *nodes) gchar *display = inspect_redisplay(&iter, value, NULL);
scp_tree_store_set(store, &iter, INSPECT_DISPLAY, display, INSPECT_VALUE, - &value, INSPECT_FORMAT, format, -1); + value, INSPECT_FORMAT, format, -1); g_free(display); } } @@ -499,15 +499,6 @@ gboolean inspects_update(void) return TRUE; }
-static GtkNotebook *geany_sidebar; -static GtkWidget *inspect_page; - -gboolean inspects_current(void) -{ - gint page_num = gtk_notebook_get_current_page(geany_sidebar); - return gtk_notebook_get_nth_page(geany_sidebar, page_num) == inspect_page; -} - static void inspect_iter_apply(GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata) { const char *frame; @@ -629,15 +620,19 @@ void inspects_update_state(DebugState state) static gboolean last_active = FALSE; gboolean active = state != DS_INACTIVE; GtkTreeIter iter; - const char *var1 = NULL; - gint numchild = 0;
- if ((state & DS_SENDABLE) && gtk_tree_selection_get_selected(selection, NULL, &iter)) + if (gtk_tree_selection_get_selected(selection, NULL, &iter)) { - scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_NUMCHILD, &numchild, - -1); + const char *var1 = NULL; + gint numchild = 0; + + if (state & DS_SENDABLE) + { + scp_tree_store_get(store, &iter, INSPECT_VAR1, &var1, INSPECT_NUMCHILD, + &numchild, -1); + } + g_object_set(inspect_display, "editable", var1 && !numchild, NULL); } - g_object_set(inspect_display, "editable", var1 && !numchild, NULL);
if (active != last_active) { @@ -1060,13 +1055,6 @@ static void on_inspect_menu_show(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED } }
-static void on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook *notebook, gpointer page, - G_GNUC_UNUSED gint page_num, G_GNUC_UNUSED gpointer gdata) -{ - if (page == inspect_page) - view_inspect_update(); -} - void inspect_init(void) { GtkWidget *menu; @@ -1075,12 +1063,6 @@ void inspect_init(void) jump_to_menu = GTK_CONTAINER(get_widget("inspect_jump_to_menu")); apply_item = menu_item_find(inspect_menu_items, "inspect_apply");
- inspect_page = get_widget("inspect_page"); - geany_sidebar = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook); - g_signal_connect(geany_sidebar, "switch-page", G_CALLBACK(on_geany_sidebar_switch_page), - NULL); - gtk_notebook_append_page(geany_sidebar, inspect_page, get_widget("inspect_label")); - tree = view_connect("inspect_view", &store, &selection, inspect_cells, "inspect_window", &inspect_display); g_signal_connect(tree, "test-expand-row", G_CALLBACK(inspect_test_expand_row), NULL); @@ -1119,7 +1101,6 @@ void inspect_init(void)
void inspect_finalize(void) { - gtk_widget_destroy(inspect_page); gtk_widget_destroy(inspect_dialog); gtk_widget_destroy(expand_dialog); g_free(jump_to_expr);
Modified: scope/src/inspect.h 1 files changed, 0 insertions(+), 1 deletions(-) =================================================================== @@ -29,7 +29,6 @@
void inspects_clear(void); gboolean inspects_update(void); -gboolean inspects_current(void); void inspects_apply(void);
#define EXPAND_MAX 99999
Modified: scope/src/local.c 15 files changed, 5 insertions(+), 10 deletions(-) =================================================================== @@ -82,11 +82,7 @@ static void local_node_variable(const ParseNode *node, const LocalData *ld)
void on_local_variables(GArray *nodes) { - const char *token = parse_grab_token(nodes); - size_t len = *token - '0' + 1; - - if (thread_id && frame_id && len == strlen(thread_id) && - !memcmp(++token, thread_id, len) && !strcmp(token + len, frame_id)) + if (utils_matches_frame(parse_grab_token(nodes))) { GtkTreeIter iter; LocalData ld = { NULL, stack_entry() }; @@ -105,10 +101,9 @@ void locals_clear(void) store_clear(store); }
-static void local_send_update(char token) +static void locals_send_update(char token) { - debug_send_format(F, "0%c%c%s%s-stack-list-variables 1", token, - '0' + (int) strlen(thread_id) - 1, thread_id, frame_id); + debug_send_format(F, "0%c%c%s%s-stack-list-variables 1", token, FRAME_ARGS); }
gboolean locals_update(void) @@ -117,7 +112,7 @@ gboolean locals_update(void) return FALSE;
if (frame_id) - local_send_update('4'); + locals_send_update('4'); else locals_clear();
@@ -133,7 +128,7 @@ void locals_update_state(DebugState state)
static void on_local_refresh(G_GNUC_UNUSED const MenuItem *menu_item) { - local_send_update('2'); + locals_send_update('2'); }
static void on_local_unsorted(G_GNUC_UNUSED const MenuItem *menu_item)
Modified: scope/src/parse.c 5 files changed, 4 insertions(+), 1 deletions(-) =================================================================== @@ -60,7 +60,7 @@ static void on_quiet_error(G_GNUC_UNUSED GArray *nodes)
static void on_data_modified(G_GNUC_UNUSED GArray *nodes) { - views_data_dirty(); + views_data_dirty(DS_BUSY); }
typedef struct _ParseRoute @@ -114,6 +114,9 @@ static void on_data_modified(G_GNUC_UNUSED GArray *nodes) { "^done,memory=[", on_memory_read_bytes, '\0', '\0', 1 }, { "^done,features=[", on_break_features, '5', '\0', 1 }, { "^done,features=[", on_target_features, '7', '\0', 1 }, + { "^done,register-names=[", on_register_names, '\0', '\0', 1 }, + { "^done,changed-registers=[", on_register_changes, '\0', '\0', 1 }, + { "^done,register-values=[", on_register_values, '*', '\0', 1 }, { "^running", on_debug_loaded, '1', '\0', 0 }, { "^done", on_debug_loaded, '1', '\0', 0 }, { "^done", on_break_done, '2', '\0', 0 },
Modified: scope/src/program.c 5 files changed, 4 insertions(+), 1 deletions(-) =================================================================== @@ -189,6 +189,7 @@ static void save_program_settings(void) breaks_save(config); watches_save(config); inspects_save(config); + registers_save(config); parse_save(config); utils_key_file_write_to_file(config, configfile); g_free(configfile); @@ -245,6 +246,7 @@ static void on_recent_menu_item_activate(G_GNUC_UNUSED GtkMenuItem *menuitem, co breaks_load(config); watches_load(config); inspects_load(config); + registers_load(config); parse_load(config); message = g_strdup_printf(_("Loaded debug settings for %s."), name); program_find(&iter, name); @@ -410,11 +412,12 @@ static void on_program_ok_button_clicked(G_GNUC_UNUSED GtkButton *button, gtk_widget_hide(program_dialog);
if (gtk_toggle_button_get_active(delete_all_items) && - dialogs_show_question(_("Delete all breakpoints, watches and inspects?"))) + dialogs_show_question(_("Delete all breakpoints, watches et cetera?"))) { breaks_delete_all(); watches_delete_all(); inspects_delete_all(); + registers_delete_all(); } } }
Modified: scope/src/register.c 543 files changed, 543 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,543 @@ +/* + * register.c + * + * Copyright 2013 Dimitar Toshkov Zhekov dimitar.zhekov@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#include "common.h" + +enum +{ + REGISTER_PATH, + REGISTER_DISPLAY, + REGISTER_VALUE, + REGISTER_HB_MODE, /* natural register as char(s)?.. */ + REGISTER_NAME, + REGISTER_ID, + REGISTER_FORMAT +}; + +static ScpTreeStore *store; +static GtkTreeSelection *selection; + +enum +{ + FORMAT_NATURAL, + FORMAT_HEX, + FORMAT_DECIMAL, + FORMAT_OCTAL, + FORMAT_BINARY, + FORMAT_RAW, + FORMAT_COUNT +}; + +static const char register_formats[FORMAT_COUNT] = { 'N', 'x', 'd', 'o', 't', 'r' }; + +static void register_iter_update(GtkTreeIter *iter, GString *commands[]) +{ + gint id, format; + + scp_tree_store_get(store, iter, REGISTER_ID, &id, REGISTER_FORMAT, &format, -1); + g_string_append_printf(commands[format], " %d", id); +} + +static void register_node_update(const ParseNode *node, GString *commands[]) +{ + iff (node->type == PT_VALUE, "changed-registers: contains array") + { + const char *id = (const char *) node->value; + GtkTreeIter iter; + + iff (store_find(store, &iter, REGISTER_ID, id), "%s: rid not found", id) + register_iter_update(&iter, commands); + } +} + +static void registers_send_update(GArray *nodes, char token) +{ + GString *commands[FORMAT_COUNT]; + guint format; + gsize empty; + + for (format = 0; format < FORMAT_COUNT; format++) + { + commands[format] = g_string_sized_new(0x7F); + g_string_append_printf(commands[format], "0%c9%c%s%s-data-list-register-values %c", + token, FRAME_ARGS, register_formats[format]); + } + + empty = commands[FORMAT_NATURAL]->len; + + if (nodes) + parse_foreach(nodes, (GFunc) register_node_update, commands); + else + store_foreach(store, (GFunc) register_iter_update, commands); + + for (format = 0; format < FORMAT_COUNT; format++) + { + if (commands[format]->len > empty) + debug_send_command(F, commands[format]->str); + + g_string_free(commands[format], TRUE); + } +} + +typedef struct _IndexData +{ + guint index; + guint count; +} IndexData; + +static void register_node_name(const ParseNode *node, IndexData *id) +{ + iff (node->type == PT_VALUE, "register-names: contains array") + { + const char *name = (const char *) node->value; + + if (*name) + { + GtkTreeIter iter, iter1; + + if (store_find(store, &iter1, REGISTER_NAME, name)) + { + scp_tree_store_iter_nth_child(store, &iter, NULL, id->count); + scp_tree_store_swap(store, &iter, &iter1); + } + else + { + scp_tree_store_insert_with_values(store, &iter, NULL, id->count, + REGISTER_PATH, name, REGISTER_NAME, name, REGISTER_HB_MODE, + HB_DEFAULT, REGISTER_FORMAT, FORMAT_NATURAL, -1); + } + + scp_tree_store_set(store, &iter, REGISTER_DISPLAY, NULL, REGISTER_VALUE, + NULL, REGISTER_ID, id->index, -1); + id->count++; + } + + id->index++; + } +} + +void on_register_names(GArray *nodes) +{ + IndexData id = { 0, 0 }; + gboolean valid; + GtkTreeIter iter; + const char *token = parse_grab_token(nodes); + + parse_foreach(parse_lead_array(nodes), (GFunc) register_node_name, &id); + valid = scp_tree_store_iter_nth_child(store, &iter, NULL, id.count); + while (valid) + valid = scp_tree_store_remove(store, &iter); + + if (token) + registers_send_update(NULL, '2'); +} + +static gboolean query_all_registers = TRUE; + +void on_register_changes(GArray *nodes) +{ + const char *token = parse_grab_token(nodes); + + if (token) + { + if (utils_matches_frame(token)) + registers_send_update(parse_lead_array(nodes), '4'); + } + else + query_all_registers = TRUE; /* external changes */ +} + +static void register_set_value(GtkTreeIter *iter, char *value) +{ + if (*value == '{') + { + const char *parent; + GtkTreeIter child; + gboolean valid = scp_tree_store_iter_children(store, &child, iter); + gboolean next; + + scp_tree_store_set(store, iter, REGISTER_DISPLAY, NULL, REGISTER_VALUE, NULL, -1); + scp_tree_store_get(store, iter, REGISTER_NAME, &parent, -1); + + do + { + const char *name = ++value; + char *path, *end; + + if ((value = strchr(name, '=')) == NULL) + { + dc_error("= expected"); + break; + } + + value[-(isspace(value[-1]) != 0)] = '\0'; + + if (!*name) + { + dc_error("name expected"); + break; + } + + if (isspace(*++value)) + value++; + + if (*value == '{') + { + if ((end = strchr(value, '}')) != NULL) + end++; + } + else if ((end = strchr(value, ',')) == NULL) + end = strchr(value, '}'); + + if (!end) + { + dc_error(", or } expected"); + break; + } + + next = *end == ','; + *end = '\0'; + path = g_strdup_printf("%s.%s", parent, name); + + if (!valid) + scp_tree_store_append(store, &child, iter); + scp_tree_store_set(store, &child, REGISTER_PATH, path, REGISTER_NAME, name, + REGISTER_DISPLAY, value, REGISTER_VALUE, value, -1); + valid &= scp_tree_store_iter_next(store, &child); + + g_free(path); + value = end; + if (isspace(value[1])) + value++; + + } while (next); + + while (valid) + valid = scp_tree_store_remove(store, &child); + } + else + { + scp_tree_store_clear_children(store, iter, FALSE); + scp_tree_store_set(store, iter, REGISTER_DISPLAY, value, REGISTER_VALUE, value, -1); + } +} + +typedef struct _ValueAction +{ + gint format; + gboolean assign; +} ValueAction; + +static void register_node_value(const ParseNode *node, const ValueAction *va) +{ + iff (node->type == PT_ARRAY, "register-values: contains value") + { + GArray *nodes = (GArray *) node->value; + const char *number = parse_find_value(nodes, "number"); + char *value = parse_find_value(nodes, "value"); + + iff (number && value, "no number or value") + { + GtkTreeIter iter; + + if (store_find(store, &iter, REGISTER_ID, number), "%s: rid not found") + { + if (va->format < FORMAT_COUNT) + scp_tree_store_set(store, &iter, REGISTER_FORMAT, va->format, -1); + + if (va->assign) + register_set_value(&iter, value); + } + } + } +} + +void on_register_values(GArray *nodes) +{ + const char *token = parse_grab_token(nodes); + ValueAction va = { *token - '0', utils_matches_frame(token + 1) }; + + if (va.format < FORMAT_COUNT || va.assign) + { + parse_foreach(parse_lead_array(nodes), (GFunc) register_node_value, &va); + + if (va.assign) + query_all_registers = FALSE; + } +} + +static void on_register_display_edited(G_GNUC_UNUSED GtkCellRendererText *renderer, + gchar *path_str, gchar *new_text, G_GNUC_UNUSED gpointer gdata) +{ + view_display_edited(store, debug_state() & DS_DEBUG, path_str, "07-gdb-set var $%s=%s", + new_text); +} + +static const TreeCell register_cells[] = +{ + { "register_display", G_CALLBACK(on_register_display_edited) }, + { NULL, NULL } +}; + +static void register_iter_clear(GtkTreeIter *iter, G_GNUC_UNUSED gpointer gdata) +{ + if (scp_tree_store_iter_has_child(store, iter)) + scp_tree_store_clear_children(store, iter, FALSE); + else + scp_tree_store_set(store, iter, REGISTER_DISPLAY, NULL, REGISTER_VALUE, NULL, -1); +} + +void registers_clear(void) +{ + store_foreach(store, (GFunc) register_iter_clear, NULL); + query_all_registers = TRUE; +} + +gboolean registers_update(void) +{ + if (g_strcmp0(frame_id, "0") && view_stack_update()) + return FALSE; + + if (frame_id) + { + if (query_all_registers) + registers_send_update(NULL, '4'); + else + debug_send_format(F, "04%c%s%s-data-list-changed-registers", FRAME_ARGS); + } + else + registers_clear(); + + return TRUE; +} + +static char *last_gdb_executable = NULL; + +void registers_query_names(void) +{ + if (g_strcmp0(pref_gdb_executable, last_gdb_executable)) + { + g_free(last_gdb_executable); + last_gdb_executable = g_strdup(pref_gdb_executable); + debug_send_command(N, "-data-list-register-names"); + } +} + +static GtkWidget *tree; + +void registers_show(gboolean show) +{ + gtk_widget_set_visible(tree, show); +} + +static GObject *register_display; + +void registers_update_state(DebugState state) +{ + GtkTreeIter iter; + + if (gtk_tree_selection_get_selected(selection, NULL, &iter)) + { + GtkTreeIter parent; + + g_object_set(register_display, "editable", (state & DS_DEBUG) && + (scp_tree_store_iter_parent(store, &parent, &iter) || + !scp_tree_store_iter_has_child(store, &iter)), NULL); + } +} + +void registers_delete_all(void) +{ + store_clear(store); +} + +static gboolean register_load(GKeyFile *config, const char *section) +{ + char *name = utils_key_file_get_string(config, section, "name"); + gint format = utils_get_setting_integer(config, section, "format", FORMAT_NATURAL); + gboolean valid = FALSE; + GtkTreeIter iter; + + if (name && (unsigned) format < FORMAT_COUNT) + { + scp_tree_store_append_with_values(store, NULL, NULL, REGISTER_PATH, name, + REGISTER_NAME, name, REGISTER_HB_MODE, HB_DEFAULT, REGISTER_FORMAT, + format, -1); + valid = TRUE; + } + + g_free(name); + return valid; +} + +void registers_load(GKeyFile *config) +{ + registers_delete_all(); + g_free(last_gdb_executable); + last_gdb_executable = NULL; + utils_load(config, "register", register_load); +} + +static gboolean register_save(GKeyFile *config, const char *section, GtkTreeIter *iter) +{ + const char *name; + gint format; + + scp_tree_store_get(store, iter, REGISTER_NAME, &name, REGISTER_FORMAT, &format, -1); + + if (format == FORMAT_NATURAL) + return FALSE; + + g_key_file_set_string(config, section, "name", name); + g_key_file_set_integer(config, section, "format", format); + return TRUE; +} + +void registers_save(GKeyFile *config) +{ + store_save(store, config, "register", register_save); +} + +static gboolean on_register_query_tooltip(G_GNUC_UNUSED GtkWidget *widget, gint x, gint y, + gboolean keyboard_tip, GtkTooltip *tooltip, GtkTreeViewColumn *register_name_column) +{ + GtkTreeView *tree = GTK_TREE_VIEW(widget); + GtkTreeIter iter; + + if (gtk_tree_view_get_tooltip_context(tree, &x, &y, keyboard_tip, NULL, NULL, &iter)) + { + gint id; + char *text; + + gtk_tree_view_set_tooltip_cell(tree, tooltip, NULL, register_name_column, NULL); + scp_tree_store_get(store, &iter, REGISTER_ID, &id, -1); + text = g_strdup_printf("register %d", id); + gtk_tooltip_set_text(tooltip, text); + g_free(text); + return TRUE; + } + + return FALSE; +} + +static void on_register_refresh(G_GNUC_UNUSED const MenuItem *menu_item) +{ + registers_send_update(NULL, '2'); +} + +static void on_register_copy(const MenuItem *menu_item) +{ + menu_copy(selection, menu_item); +} + +static void on_register_format_display(const MenuItem *menu_item) +{ + menu_mode_display(selection, menu_item, REGISTER_FORMAT); +} + +static void on_register_format_update(const MenuItem *menu_item) +{ + GtkTreeIter iter; + gint format = GPOINTER_TO_INT(menu_item->gdata); + gint id; + + gtk_tree_selection_get_selected(selection, NULL, &iter); + scp_tree_store_get(store, &iter, REGISTER_ID, &id, -1); + + if (debug_state() & DS_DEBUG) + { + debug_send_format(N, "02%d%c%s%s-data-list-register-values %c %d", format, + FRAME_ARGS, register_formats[format], id); + } + else + scp_tree_store_set(store, &iter, REGISTER_FORMAT, format, -1); +} + +static void on_register_query(G_GNUC_UNUSED const MenuItem *menu_item) +{ + debug_send_command(N, debug_state() & DS_DEBUG ? "02-data-list-register-names" : + "-data-list-register-names"); +} + +#define DS_FRESHABLE DS_DEBUG +#define DS_COPYABLE (DS_BASICS | DS_EXTRA_1) +#define DS_FORMATABLE (DS_INACTIVE | DS_DEBUG | DS_HANGING | DS_EXTRA_2) +#define DS_QUERABLE DS_SENDABLE + +#define FORMAT_ITEM(format, FORMAT) \ + { ("register_format_"format), on_register_format_update, DS_FORMATABLE, NULL, \ + GINT_TO_POINTER(FORMAT) } + +static MenuItem register_menu_items[] = +{ + { "register_refresh", on_register_refresh, DS_FRESHABLE, NULL, NULL }, + { "register_copy", on_register_copy, DS_COPYABLE, NULL, NULL }, + { "register_format", on_register_format_display, DS_FORMATABLE, NULL, NULL }, + FORMAT_ITEM("natural", FORMAT_NATURAL), + FORMAT_ITEM("hex", FORMAT_HEX), + FORMAT_ITEM("decimal", FORMAT_DECIMAL), + FORMAT_ITEM("octal", FORMAT_OCTAL), + FORMAT_ITEM("binary", FORMAT_BINARY), + FORMAT_ITEM("raw", FORMAT_RAW), + { "register_query", on_register_query, DS_QUERABLE, NULL, NULL }, + { NULL, NULL, 0, NULL, NULL } +}; + +static guint register_menu_extra_state(void) +{ + GtkTreeIter iter; + + if (gtk_tree_selection_get_selected(selection, NULL, &iter)) + { + GtkTreeIter parent; + + return (1 << DS_INDEX_1) | + (!scp_tree_store_iter_parent(store, &parent, &iter) << DS_INDEX_2); + } + + return 0; +} + +static MenuInfo register_menu_info = { register_menu_items, register_menu_extra_state, 0 }; + +static void on_register_selection_changed(G_GNUC_UNUSED GtkTreeSelection *selection, + G_GNUC_UNUSED gpointer gdata) +{ + registers_update_state(debug_state()); +} + +void register_init(void) +{ + tree = GTK_WIDGET(view_connect("register_view", &store, &selection, register_cells, + "register_window", ®ister_display)); + gtk_widget_set_has_tooltip(tree, TRUE); + g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_register_query_tooltip), + get_column("register_name_column")); + menu_select("register_menu", ®ister_menu_info, selection); + g_signal_connect(selection, "changed", G_CALLBACK(on_register_selection_changed), NULL); +} + +void registers_finalize(void) +{ + g_free(last_gdb_executable); +}
Modified: scope/src/register.h 40 files changed, 40 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,40 @@ +/* + * register.h + * + * Copyright 2013 Dimitar Toshkov Zhekov dimitar.zhekov@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +#ifndef REGISTER_H + +void on_register_names(GArray *nodes); +void on_register_changes(GArray *nodes); +void on_register_values(GArray *nodes); + +void registers_clear(void); +gboolean registers_update(void); +void registers_query_names(void); +void registers_show(gboolean show); + +void registers_update_state(DebugState state); +void registers_delete_all(void); +void registers_load(GKeyFile *config); +void registers_save(GKeyFile *config); + +void register_init(void); +void registers_finalize(void); + +#define REGISTER_H 1 +#endif
Modified: scope/src/scope.c 4 files changed, 3 insertions(+), 1 deletions(-) =================================================================== @@ -32,7 +32,7 @@ PLUGIN_VERSION_CHECK(215)
PLUGIN_SET_TRANSLATABLE_INFO(LOCALEDIR, GETTEXT_PACKAGE, _("Scope Debugger"), - _("Relatively simple GDB front-end."), "0.88" , + _("Relatively simple GDB front-end."), "0.90" , "Dimitar Toshkov Zhekov dimitar.zhekov@gmail.com")
/* Keybinding(s) */ @@ -560,6 +560,7 @@ void plugin_init(G_GNUC_UNUSED GeanyData *gdata) gtk_notebook_set_tab_pos(GTK_NOTEBOOK(debug_panel), pref_panel_tab_pos); conterm_init(); inspect_init(); + register_init(); parse_init(); debug_init(); views_init(); @@ -613,6 +614,7 @@ void plugin_cleanup(void) tooltip_finalize(); program_finalize(); conterm_finalize(); + registers_finalize(); inspect_finalize(); thread_finalize(); break_finalize();
Modified: scope/src/stack.c 5 files changed, 2 insertions(+), 3 deletions(-) =================================================================== @@ -199,8 +199,7 @@ static void on_stack_selection_changed(GtkTreeSelection *selection, else frame_id = NULL;
- view_dirty(VIEW_LOCALS); - view_dirty(VIEW_WATCHES); + views_context_dirty(debug_state(), TRUE); }
static void stack_seek_selected(gboolean focus) @@ -341,7 +340,7 @@ void stack_init(void) view_set_sort_func(store, STACK_FILE, store_seek_compare); view_set_line_data_func("stack_line_column", "stack_line", STACK_LINE); gtk_widget_set_has_tooltip(GTK_WIDGET(tree), TRUE); - g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_tooltip), + g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_base_tooltip), get_column("stack_base_name_column"));
g_signal_connect(tree, "key-press-event", G_CALLBACK(on_view_key_press),
Modified: scope/src/thread.c 12 files changed, 7 insertions(+), 5 deletions(-) =================================================================== @@ -314,7 +314,7 @@ static void thread_iter_stopped(GtkTreeIter *iter, StopData *sd) if (!addr) thread_state = THREAD_QUERY_FRAME;
- views_data_dirty(); + views_data_dirty(DS_BUSY); } else if (!addr) view_dirty(VIEW_THREADS); @@ -328,7 +328,7 @@ static void thread_iter_stopped(GtkTreeIter *iter, StopData *sd)
static void thread_node_stopped(const ParseNode *node, StopData *sd) { - iff (node->type == PT_VALUE, "%s: found array", node->name) + iff (node->type == PT_VALUE, "stopped-threads: contains array") { GtkTreeIter iter;
@@ -429,6 +429,7 @@ void on_thread_created(GArray *nodes) { /* startup */ breaks_reset(); + registers_show(TRUE); #ifdef G_OS_UNIX terminal_clear(); if (terminal_auto_show) @@ -483,6 +484,7 @@ void on_thread_exited(GArray *nodes) if (!--thread_count) { /* shutdown */ + registers_show(FALSE); #ifdef G_OS_UNIX if (terminal_auto_hide) terminal_standalone(FALSE); @@ -673,8 +675,8 @@ static void on_thread_selection_changed(GtkTreeSelection *selection, thread_state = THREAD_BLANK; }
- views_data_dirty(); - update_state(debug_state()); + views_data_dirty(debug_state()); + update_state(debug_state()); /* may be a different state */ }
static void thread_seek_selected(gboolean focus) @@ -881,7 +883,7 @@ void thread_init(void) view_set_sort_func(store, THREAD_GROUP_ID, thread_ident_compare); view_set_sort_func(store, THREAD_TARGET_ID, thread_ident_compare); gtk_widget_set_has_tooltip(GTK_WIDGET(tree), TRUE); - g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_tooltip), + g_signal_connect(tree, "query-tooltip", G_CALLBACK(on_view_query_base_tooltip), get_column("thread_base_name_column"));
groups = SCP_TREE_STORE(get_object("thread_group_store"));
Modified: scope/src/utils.c 12 files changed, 11 insertions(+), 1 deletions(-) =================================================================== @@ -41,7 +41,9 @@ void show_errno(const char *prefix)
void show_errno(const char *prefix) { - show_error(_("%s: error %lu."), prefix, (unsigned long) GetLastError()); + gchar *error = g_win32_error_message(GetLastError()); + show_error(_("%s: %s"), prefix, error); + g_free(error); } #endif /* G_OS_UNIX */
@@ -604,6 +606,14 @@ static void on_insert_text(GtkEditable *editable, gchar *new_text, gint new_text g_signal_stop_emission_by_name(editable, "insert-text"); }
+gboolean utils_matches_frame(const char *token) +{ + size_t len = *token - '0' + 1; + + return thread_id && len == strlen(thread_id) && strlen(++token) > len && + !memcmp(token, thread_id, len) && !g_strcmp0(token + len, frame_id); +} + void validator_attach(GtkEditable *editable, gint validator) { g_signal_connect(editable, "insert-text", G_CALLBACK(on_insert_text),
Modified: scope/src/utils.h 2 files changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -25,6 +25,7 @@ gboolean utils_set_nonblock(GPollFD *fd); void utils_handle_button_press(GtkWidget *widget, GdkEventButton *event); void utils_handle_button_release(GtkWidget *widget, GdkEventButton *event); + gboolean utils_check_path(const char *pathname, gboolean file, int mode); /* "" ok */ const gchar *utils_skip_spaces(const gchar *text); void utils_strchrepl(char *text, char c, char repl); @@ -86,6 +87,7 @@ void utils_load(GKeyFile *config, const char *prefix,
gchar *utils_verify_selection(gchar *text); gchar *utils_get_default_selection(void); /* +verify */ +gboolean utils_matches_frame(const char *token);
enum {
Modified: scope/src/views.c 134 files changed, 89 insertions(+), 45 deletions(-) =================================================================== @@ -23,10 +23,17 @@
#include "common.h"
+typedef enum _ViewContext +{ + VC_NONE, + VC_DATA, + VC_FRAME +} ViewContext; + typedef struct _ViewInfo { gboolean dirty; - gboolean data; + ViewContext context; void (*clear)(void); gboolean (*update)(void); gboolean flush; @@ -35,34 +42,21 @@
static ViewInfo views[VIEW_COUNT] = { - { FALSE, FALSE, NULL, NULL, FALSE, 0 }, - { FALSE, FALSE, threads_clear, threads_update, FALSE, DS_SENDABLE }, - { FALSE, FALSE, breaks_clear, breaks_update, FALSE, DS_SENDABLE }, - { FALSE, TRUE, stack_clear, stack_update, TRUE, DS_DEBUG }, - { FALSE, TRUE, locals_clear, locals_update, TRUE, DS_DEBUG }, - { FALSE, TRUE, watches_clear, watches_update, TRUE, DS_DEBUG }, - { FALSE, TRUE, memory_clear, memory_update, TRUE, DS_SENDABLE }, - { FALSE, FALSE, NULL, dc_update, FALSE, DS_DEBUG }, - { FALSE, TRUE, inspects_clear, inspects_update, FALSE, DS_DEBUG }, - { FALSE, TRUE, tooltip_clear, tooltip_update, FALSE, DS_SENDABLE }, - { FALSE, FALSE, menu_clear, NULL, FALSE, 0 } + { FALSE, VC_NONE, NULL, NULL, FALSE, 0 }, + { FALSE, VC_NONE, threads_clear, threads_update, FALSE, DS_SENDABLE }, + { FALSE, VC_NONE, breaks_clear, breaks_update, FALSE, DS_SENDABLE }, + { FALSE, VC_DATA, stack_clear, stack_update, TRUE, DS_DEBUG }, + { FALSE, VC_FRAME, locals_clear, locals_update, TRUE, DS_DEBUG }, + { FALSE, VC_FRAME, watches_clear, watches_update, TRUE, DS_DEBUG }, + { FALSE, VC_DATA, memory_clear, memory_update, TRUE, DS_SENDABLE }, + { FALSE, VC_NONE, NULL, dc_update, FALSE, DS_DEBUG }, + { FALSE, VC_DATA, inspects_clear, inspects_update, FALSE, DS_DEBUG }, + { FALSE, VC_FRAME, registers_clear, registers_update, TRUE, DS_DEBUG }, + { FALSE, VC_DATA, tooltip_clear, tooltip_update, FALSE, DS_SENDABLE }, + { FALSE, VC_NONE, menu_clear, NULL, FALSE, 0 } };
-void view_dirty(ViewIndex index) -{ - views[index].dirty = TRUE; -} - -void views_data_dirty(void) -{ - ViewIndex i; - - for (i = 0; i < VIEW_COUNT; i++) - if (views[i].data) - view_dirty(i); -} - -static void view_update_unconditional(ViewIndex index, DebugState state) +static void view_update_dirty(ViewIndex index, DebugState state) { ViewInfo *view = views + index;
@@ -81,7 +75,44 @@ static void view_update_unconditional(ViewIndex index, DebugState state) static void view_update(ViewIndex index, DebugState state) { if (views[index].dirty) - view_update_unconditional(index, state); + view_update_dirty(index, state); +} + +static GtkNotebook *geany_sidebar; +static GtkWidget *inspect_page; +static GtkWidget *register_page; + +static void views_sidebar_update(DebugState state) +{ + gint page_num = gtk_notebook_get_current_page(geany_sidebar); + GtkWidget *page = gtk_notebook_get_nth_page(geany_sidebar, page_num); + + if (page == inspect_page) + view_update(VIEW_INSPECT, state); + else if (page == register_page) + view_update(VIEW_REGISTERS, state); +} + +void view_dirty(ViewIndex index) +{ + views[index].dirty = TRUE; +} + +void views_context_dirty(DebugState state, gboolean frame_only) +{ + ViewIndex i; + + for (i = 0; i < VIEW_COUNT; i++) + if (views[i].context >= (frame_only ? VC_FRAME : VC_DATA)) + view_dirty(i); + + if (state != DS_BUSY) + { + if (option_update_all_views) + views_update(state); + else + views_sidebar_update(state); + } }
static ViewIndex view_current = 0; @@ -105,6 +136,7 @@ void views_update(DebugState state) if (option_update_all_views) { ViewIndex i; + gboolean skip_frame = FALSE;
if (thread_state == THREAD_QUERY_FRAME) { @@ -116,12 +148,12 @@ void views_update(DebugState state)
for (i = 0; i < VIEW_COUNT; i++) { - if (views[i].dirty) + if (views[i].dirty && (!skip_frame || views[i].context != VC_FRAME)) { - view_update_unconditional(i, state); + view_update_dirty(i, state);
if (i == VIEW_STACK && thread_state >= THREAD_STOPPED) - i = VIEW_WATCHES; + skip_frame = TRUE; } } } @@ -137,9 +169,7 @@ void views_update(DebugState state)
view_update(view_current, state); view_update(VIEW_TOOLTIP, state); - - if (inspects_current()) - view_update(VIEW_INSPECT, state); + views_sidebar_update(state); } }
@@ -148,18 +178,13 @@ gboolean view_stack_update(void) if (views[VIEW_STACK].dirty) { DebugState state = thread_state >= THREAD_STOPPED ? DS_DEBUG : DS_READY; - view_update_unconditional(VIEW_STACK, state); + view_update_dirty(VIEW_STACK, state); return state == DS_DEBUG; }
return FALSE; }
-void view_inspect_update(void) -{ - view_update(VIEW_INSPECT, debug_state()); -} - void on_view_changed(G_GNUC_UNUSED GtkNotebook *notebook, G_GNUC_UNUSED gpointer page, gint page_num, G_GNUC_UNUSED gpointer gdata) { @@ -191,7 +216,7 @@ gboolean on_view_button_1_press(GtkWidget *widget, GdkEventButton *event, ViewSe return FALSE; }
-gboolean on_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, +gboolean on_view_query_base_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, GtkTreeViewColumn *base_name_column) { GtkTreeView *tree = GTK_TREE_VIEW(widget); @@ -474,12 +499,12 @@ static void on_command_send_button_clicked(G_GNUC_UNUSED GtkButton *button,
thread_synchronize(); utils_strchrepl(text, '\n', ' '); - gtk_text_buffer_set_text(command_text, text, -1); start = utils_skip_spaces(text); locale = gtk_toggle_button_get_active(command_locale) ? utils_get_locale_from_utf8(start) : g_strdup(start); debug_send_command(N, locale); g_free(locale); + gtk_text_buffer_set_text(command_text, "", -1); gtk_widget_hide(command_dialog);
if (*start) @@ -538,12 +563,15 @@ void view_command_line(const gchar *text, const gchar *title, const gchar *seek, g_utf8_strlen(text, pos ? pos + strlen(seek) * seek_after - text : -1)); gtk_text_buffer_place_cursor(command_text, &iter); } + else + { + gtk_text_buffer_get_start_iter(command_text, &start); + gtk_text_buffer_get_end_iter(command_text, &end); + gtk_text_buffer_select_range(command_text, &start, &end); + }
on_command_text_changed(command_text, NULL); command_line_update_state(debug_state()); - gtk_text_buffer_get_start_iter(command_text, &start); - gtk_text_buffer_get_end_iter(command_text, &end); - gtk_text_buffer_select_range(command_text, &start, &end); gtk_combo_box_set_active_iter(command_history, NULL); gtk_dialog_run(GTK_DIALOG(command_dialog)); } @@ -568,6 +596,12 @@ void views_update_state(DebugState state) } }
+static void on_geany_sidebar_switch_page(G_GNUC_UNUSED GtkNotebook *notebook, + G_GNUC_UNUSED gpointer page, G_GNUC_UNUSED gint page_num, G_GNUC_UNUSED gpointer gdata) +{ + views_sidebar_update(debug_state()); +} + void views_init(void) { command_dialog = dialog_connect("command_dialog"); @@ -596,9 +630,19 @@ void views_init(void) g_signal_connect(command_send, "clicked", G_CALLBACK(on_command_send_button_clicked), NULL); utils_enter_to_clicked(command_view, command_send); + + geany_sidebar = GTK_NOTEBOOK(geany->main_widgets->sidebar_notebook); + g_signal_connect(geany_sidebar, "switch-page", G_CALLBACK(on_geany_sidebar_switch_page), + NULL); + inspect_page = get_widget("inspect_page"); + gtk_notebook_append_page(geany_sidebar, inspect_page, get_widget("inspect_label")); + register_page = get_widget("register_page"); + gtk_notebook_append_page(geany_sidebar, register_page, get_widget("register_label")); }
void views_finalize(void) { gtk_widget_destroy(GTK_WIDGET(command_dialog)); + gtk_widget_destroy(inspect_page); + gtk_widget_destroy(register_page); }
Modified: scope/src/views.h 8 files changed, 5 insertions(+), 3 deletions(-) =================================================================== @@ -30,23 +30,25 @@ VIEW_MEMORY, VIEW_CONSOLE, VIEW_INSPECT, + VIEW_REGISTERS, VIEW_TOOLTIP, VIEW_POPMENU, VIEW_COUNT } ViewIndex;
void view_dirty(ViewIndex index); -void views_data_dirty(void); +void views_context_dirty(DebugState state, gboolean frame_only); +#define views_data_dirty(state) views_context_dirty((state), FALSE) void views_clear(void); void views_update(DebugState state); gboolean view_stack_update(void); -void view_inspect_update(void); +void view_local_update(void);
void on_view_changed(GtkNotebook *notebook, gpointer page, gint page_num, gpointer gdata); typedef void (*ViewSeeker)(gboolean focus); gboolean on_view_key_press(GtkWidget *widget, GdkEventKey *event, ViewSeeker seeker); gboolean on_view_button_1_press(GtkWidget *widget, GdkEventButton *event, ViewSeeker seeker); -gboolean on_view_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, +gboolean on_view_query_base_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_tip, GtkTooltip *tooltip, GtkTreeViewColumn *base_name_column);
enum
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org