cvs -z3 -d:pserver:anonymous@libmigdb.cvs.sourceforge.net:/cvsroot/libmigdb co -P...
authorJan Kratochvil <jan.kratochvil@redhat.com>
Thu, 26 Jul 2012 14:15:39 +0000 (16:15 +0200)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Thu, 26 Jul 2012 14:15:39 +0000 (16:15 +0200)
2010-05-19T21:30

44 files changed:
.cvsignore [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
DJGPP.why [new file with mode: 0644]
GPL-license [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
change.log [new file with mode: 0644]
compress.sh [new file with mode: 0755]
doc/html.frt [new file with mode: 0644]
doc/reference.html [new file with mode: 0644]
examples/.cvsignore [new file with mode: 0644]
examples/Makefile [new file with mode: 0644]
examples/cmds.txt [new file with mode: 0644]
examples/linux_test.c [new file with mode: 0644]
examples/pty_test.c [new file with mode: 0644]
examples/remote_test.c [new file with mode: 0644]
examples/target_frames.cc [new file with mode: 0644]
examples/test_target.cc [new file with mode: 0644]
examples/ticepic.c [new file with mode: 0644]
examples/x11_cpp_test.cc [new file with mode: 0644]
examples/x11_fr_test.c [new file with mode: 0644]
examples/x11_test.c [new file with mode: 0644]
examples/x11_wp_test.c [new file with mode: 0644]
files [new file with mode: 0644]
src/.cvsignore [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/alloc.c [new file with mode: 0644]
src/breakpoint.c [new file with mode: 0644]
src/connect.c [new file with mode: 0644]
src/cpp_int.cc [new file with mode: 0644]
src/data_man.c [new file with mode: 0644]
src/error.c [new file with mode: 0644]
src/get_free_pty.c [new file with mode: 0644]
src/get_free_vt.c [new file with mode: 0644]
src/mi_gdb.h [new file with mode: 0644]
src/misc.c [new file with mode: 0644]
src/parse.c [new file with mode: 0644]
src/prg_control.c [new file with mode: 0644]
src/stack_man.c [new file with mode: 0644]
src/symbol_query.c [new file with mode: 0644]
src/target_man.c [new file with mode: 0644]
src/thread.c [new file with mode: 0644]
src/var_obj.c [new file with mode: 0644]
version.c [new file with mode: 0644]

diff --git a/.cvsignore b/.cvsignore
new file mode 100644 (file)
index 0000000..a36664c
--- /dev/null
@@ -0,0 +1,3 @@
+*.dst
+.*.dst
+version
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e2fe890
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,438 @@
+2010-05-19 21:30  set
+
+       * change.log:
+
+       * Modified: [connect.c] To ignore \r characters from gdb. Markus Huebenthal
+       saw them using gdb 6.8.
+       * Modified: [prg_control.c] -readnow vs file name order. Don't remmember
+       who pointed-out it.
+
+2010-05-19 21:29  set
+
+       * src/prg_control.c:
+
+       * Modified: -readnow vs file name order. Don't remmember who pointed-out
+       it.
+
+2010-05-19 21:29  set
+
+       * src/connect.c:
+
+       * Modified: To ignore \r characters from gdb. Markus Huebenthal saw them
+       using gdb 6.8.
+
+2010-02-18 14:24  set
+
+       * files:
+
+       * Added: cmds.txt example.
+
+2010-02-18 14:18  set
+
+       * .cvsignore, change.log, examples/.cvsignore, examples/Makefile,
+         examples/cmds.txt, examples/ticepic.c, examples/x11_cpp_test.cc,
+         src/connect.c, src/mi_gdb.h, src/target_man.c:
+
+       * Added: [ticepic.c examples/Makefile] Example of how to use something
+       different than gdb.
+       * Added: [x11_cpp_test.cc cmds.txt] Example of how to specify an starting
+       commands file.
+       * Added: [connect.c mi_gdb.h] Functionality to indicate a file containing
+       commands to be executed at start-up and after connection.
+       * Modified: [mi_gdb.h] Version to 0.8.12.
+       * Fixed: [target_man.c] Return value for gmi_target_select.
+       * Added: [.cvsignore] version executable exclusion.
+       * Added: [examples/.cvsignore] ticepic binary exclusion.
+
+2007-06-13 14:26  set
+
+       * change.log, compress.sh, files, version.c, src/alloc.c,
+         src/mi_gdb.h, src/parse.c:
+
+       * Added: "from" field to the mi_frames structure. Suggested by Val Greene
+       (vgreene/SF).
+
+2007-05-11 16:16  set
+
+       * change.log, src/cpp_int.cc, src/mi_gdb.h, src/parse.c,
+         src/target_man.c:
+
+       * Added: Implementation of the -target-download command, used to download
+       a binary to the remote target.
+       * Added: An option to MIDebugger::SelectTargetRemote used to load the
+       binary to the remote target. Useful for embedded systems, tested with
+       avr-gdb.
+
+2007-05-10 18:49  set
+
+       * change.log, src/cpp_int.cc, src/mi_gdb.h, src/misc.c:
+
+       * Added: AVR architecture.
+       * Added: Workaround for bugs in -gdb-show architecture. Seen on gdb 6.4.x.
+
+2007-05-03 13:51  set
+
+       * change.log, src/cpp_int.cc, src/mi_gdb.h:
+
+       * Added: pic14 architecture. That's for an in-circuit emulator that I'm
+       developing.
+
+2007-04-30 18:43  set
+
+       * change.log, src/parse.c:
+
+       * Fixed: When parsing an address from gdb strtol isn't suitable, strtoul
+       is better.
+
+2005-09-26 20:38  set
+
+       * change.log, src/parse.c:
+
+       * Fixed: Apple seem to have changed the output type for stack frames to be
+       a tuple of tuples rather than a list of tuples. Patch from Greg.
+
+2005-06-03 15:04  set
+
+       * doc/reference.html:
+
+       * Updated: Version to 0.8.10.
+
+2005-06-03 15:03  set
+
+       * change.log, compress.sh, doc/html.frt, src/mi_gdb.h, src/parse.c:
+
+       * Fixed: Breakpoint parser filled the "type" field instead of the "disp"
+       field. Patch by Max Kovalenko (madmax/botik/ru).
+       * Modified: Version to 0.8.10.
+
+2005-05-13 21:29  set
+
+       * change.log, examples/pty_test.c:
+
+       * Fixed: pty_test.c to also exit when read returns 0 (Linux case). Patch
+       from Greg.
+
+2005-05-12 22:23  set
+
+       * change.log, doc/html.frt, doc/reference.html:
+
+       * Modified: Regenerated the docs to include the new documentation about
+       ptys. Also changed the docs to name version 0.8.9.
+
+2005-05-12 22:18  set
+
+       * change.log, compress.sh, examples/.cvsignore, examples/Makefile,
+         examples/pty_test.c, src/Makefile, src/get_free_pty.c,
+         src/get_free_vt.c, src/mi_gdb.h:
+
+       * Applied patches from Greg Watson (gwatson/lanl/gov):
+         * Removes apple code from src/get_free_vt.c
+         * Adds a new file src/get_free_pty.c This is a new functionality to
+           communicate with the debuggie using a pseudo terminal.
+         * Adds new mi_pty structure to src/mi_gdb.h
+         * Modifies src/Makefile to build get_free_pty.o
+         * Adds new file examples/pty_test.c
+         * Modifies examples/Makefile to build pty_test
+
+2005-04-29 22:11  set
+
+       * change.log, src/get_free_vt.c, src/mi_gdb.h, src/parse.c,
+         src/prg_control.c:
+
+       * Applied patches from Greg Watson (gwatson/lanl/gov):
+         * Add pty support for Darwin, including extending the mi_aux_term
+           structure to include a file descriptor for the master side of the pty.
+           This allows the code to prevent a race condition between checking for a
+           free pty and opening it.
+         * Rename mi_get_sttoped() to mi_get_stopped() and expose the interface
+           in mi_gdb.h.
+         * Added new gmi_exec_next_cnt() and gmi_exec_stop_cnt() commands.
+         * Add support for the broken Darwin version of gdb (tuples can contain
+           values as well as results).
+         * Fix the 'signal-name' and 'signal-meaning' variable names (were
+           'signal_name' and 'signal_meaning').
+         * Allow a 'count' argument to be supplied to mi_exec_step() and
+           mi_exec_next().
+
+2004-12-06 16:51  set
+
+       * change.log, compress.sh, src/connect.c, src/mi_gdb.h:
+
+       * Fixed: Compilations problems for SuSE 5.2. Reported by J.B. Lethbridge.
+
+2004-10-19 18:21  set
+
+       * change.log, src/cpp_int.cc:
+
+       * Fixed: FinishFun member must set the state to running if the command
+       succeed.
+
+2004-10-18 21:39  set
+
+       * change.log, compress.sh, src/mi_gdb.h:
+
+       * Modified: Version to 0.8.7.
+
+2004-10-18 21:35  set
+
+       * change.log, examples/x11_cpp_test.cc, examples/x11_fr_test.c,
+         examples/x11_wp_test.c, src/connect.c, src/mi_gdb.h:
+
+       * Fixed: Various examples to compile with current code.
+       * Fixed: Some missing headers. Needed to compile on BSD systems.
+
+2004-10-16 01:50  set
+
+       * change.log, src/cpp_int.cc:
+
+       * Added: [Cygwin] Some minimal support. Now when the target is selected we
+       tell gdb to use a new window. It seems to work but the new window have some
+       serious problems.
+
+2004-10-07 23:09  set
+
+       * Makefile:
+
+       * Fixed: [Makefile] .PHONY is needed to avoid problems.
+
+2004-09-17 01:18  set
+
+       * change.log, src/connect.c, src/get_free_vt.c:
+
+       * Modified: To compile with Cygwin. It doesn't mean it works, just
+       compiles.
+
+2004-09-13 22:39  set
+
+       * src/data_man.c:
+
+       * Added: Comment about which CVS version of gdb fixes the mi/1770 bug.
+
+2004-09-10 21:10  set
+
+       * Makefile, change.log, compress.sh, files, src/Makefile,
+         src/mi_gdb.h:
+
+       * Added: A top level makefile, is just a wrapper for the src/Makefile.
+       * Modified: Version to 0.8.6.
+
+2004-09-08 20:09  set
+
+       * change.log, src/cpp_int.cc, src/mi_gdb.h:
+
+       * Added: C++ member to find and cache the architecture. Currently supported
+       architectures are IA32 (x86) and SPARC. They are the only archs I have at
+       hand.
+
+2004-09-07 21:56  set
+
+       * change.log, src/connect.c, src/error.c, src/mi_gdb.h:
+
+       * Fixed: Lack of error report when we failed to create the temporal files
+       to spawn an X terminal.
+       * Fixed: Now we test if the X terminal and gdb binary are there and report
+       proper errors if they are missing.
+
+2004-09-06 19:13  set
+
+       * change.log, src/data_man.c, src/mi_gdb.h, src/parse.c:
+
+       * Added: Functions to workaround another bug in gdb. I reported it and it
+       was named "mi/1770". Affects gdb 6.x.
+
+2004-08-28 06:15  set
+
+       * src/connect.c:
+
+       * Fixed: Oops!
+
+2004-08-25 22:49  set
+
+       * change.log, src/connect.c, src/cpp_int.cc, src/mi_gdb.h,
+         src/prg_control.c:
+
+       * Modified: mi_error reset to MI_OK when connecting.
+       * Modified: MIDebugger::TargetUnselect() to detach only if remote/pid is
+       stopped.
+       * Added: execute until address is reached (we had file:line only).
+
+2004-08-24 23:10  set
+
+       * change.log, src/cpp_int.cc:
+
+       * Modified: PID targets starts stopped.
+       * Fixed: When debugging an attached process if gdb dies we failed to go to
+       disconnected.
+
+2004-08-24 01:45  set
+
+       * change.log, compress.sh, src/connect.c, src/data_man.c,
+         src/mi_gdb.h, src/prg_control.c, src/var_obj.c:
+
+       * Added: Mechanism to disable psym workarounds. The mechanism allows to
+       enable/disable workarounds in a simple and compatible way.
+       * Added: Mechanism to force MI version.
+       * Added: Enabled a couple of MI v2 things when the version is forced to 2+.
+       * Added: BreakAfter(mi_bkpt *b) C++ wrapper.
+
+2004-08-17 22:40  set
+
+       * change.log, compress.sh, src/alloc.c, src/cpp_int.cc,
+         src/data_man.c, src/mi_gdb.h, src/parse.c:
+
+       * Added: Disassembler functionality.
+
+2004-08-13 22:36  set
+
+       * change.log, src/connect.c, src/cpp_int.cc, src/error.c,
+         src/mi_gdb.h, src/parse.c:
+
+       * Modified: The mechanism to set gdb and xterm binaries. Now you can get
+       the actual default (it searches in PATH) and set a new value that's copied.
+       * Added: Functions to set the "main" function.
+       * Added: Time out callback to catch time-outs in gdb response.
+       * Added: Mechanism to detect gdb died and go to disconnected state. We
+       already found an operation that makes gdb die.
+
+2004-08-12 23:21  set
+
+       * change.log, src/mi_gdb.h, src/parse.c, src/thread.c:
+
+       * Added: Command to get info about the threads. It uses a partially
+       implemented gdb functionality.
+
+2004-08-09 14:58  set
+
+       * change.log, compress.sh, doc/reference.html:
+
+       * Updated: version and reference to release 0.8.3.
+
+2004-08-09 01:07  set
+
+       * change.log, doc/reference.html, src/connect.c, src/cpp_int.cc,
+         src/mi_gdb.h:
+
+       * Added: A function to know the endian of the target.
+       * Added: A workaround to another bug in gdb: responses like the endian and
+       architecture are sent to the console and not to the result record. So now
+       the -gdb-show command traps the console (a copy) and if the RR have no info
+       and we got something in the console that's returned.
+
+2004-08-06 22:59  set
+
+       * change.log, src/connect.c, src/cpp_int.cc, src/data_man.c,
+         src/mi_gdb.h, src/parse.c:
+
+       * Fixed: The gdb dialog was amazingly slow. It was just the fact that I
+       trusted in the non-blocking flag and sleep, but this annoys the scheduler
+       and the solution is to just use select, which is the Right Thing To Do (TM)
+       ;-)
+       * Modified: MIDebugger::EvalExpression now takes a const char * and cleans
+       the error number before executing.
+       * Added: Some very restricted function to read memory content.
+
+2004-08-04 22:07  set
+
+       * change.log, compress.sh, src/alloc.c, src/connect.c,
+         src/cpp_int.cc, src/mi_gdb.h, src/parse.c, src/var_obj.c:
+
+       * Modified: The mi_gvar structure to be able to hold a tree of variables.
+       * Fixed: mi_error_from_gdb not released at exit.
+       * Fixed: leak in Kill()
+       * Fixed/Added: Various details of the GNU vars code.
+
+2004-08-01 02:16  set
+
+       * change.log, doc/reference.html, src/alloc.c, src/breakpoint.c,
+         src/cpp_int.cc, src/mi_gdb.h, src/parse.c:
+
+       * Added: More fields to the mi_wp structure, useful for the frontend.
+       * Fixed: Watchpoint expressions must be enclosed using "" to avoid
+       problems.
+       * Fixed: wp_mode name to mi_wp_mode.
+       * Added: int MIDebugger::WatchDelete(mi_wp *w).
+       * Fixed: sr_wp_scope doesn't report a full wp, just the number.
+
+2004-07-30 23:17  set
+
+       * change.log, src/connect.c, src/cpp_int.cc:
+
+       * Added: More workarounds to gdb bugs. I fille the cli/1725, gdb/1726 and
+       gdb/1727 bug reports. I hope they get fixed :-(
+
+2004-07-28 23:09  set
+
+       * change.log, src/alloc.c, src/breakpoint.c, src/cpp_int.cc,
+         src/mi_gdb.h, src/parse.c:
+
+       * Fixed: Some mess in the bkpts structure. The "times" field is how many
+       times we hit a breakpoint, just information. The real value is "ignore".
+       * Fixed: Missing parse of the "cond" field for breakpoints.
+       * Added: A C++ function to set a breakpoint from a mi_bkpt structure. It
+       supports the four modes to specify a location.
+
+2004-07-26 00:58  set
+
+       * change.log, src/alloc.c, src/mi_gdb.h:
+
+       * Added: More fields to the mi_bkpt structure.
+
+2004-07-21 21:43  set
+
+       * change.log, src/prg_control.c, doc/html.frt, doc/reference.html,
+         examples/target_frames.cc:
+
+       * Added: A workaround to a bug in gdb: the two stages load of symtabs
+       (using partial ones) is not reliable (fails to find the symtab in some
+       cases). So now we force the load with "readnow".
+       * Fixed: Lack of string.h in examples/target_frames.cc. Reported by Thiago.
+
+2004-07-21 01:42  set
+
+       * change.log, compress.sh, files:
+
+       * Fixed: directory in compressed sources.
+
+2004-07-20 22:38  set
+
+       * .cvsignore, change.log, compress.sh, files, examples/.cvsignore,
+         src/.cvsignore, src/cpp_int.cc, src/mi_gdb.h, src/target_man.c:
+
+       * Added: C++ wrapper to attach to a running process. Also modified the low
+       level function to return the current frame.
+       * Modified: Now if we get an error while the state is running we assume the
+       previous "running" was wrong and we are in fact stopped. Until now I saw
+       two cases where gdb says we are running and then shows an error.
+
+2004-07-20 15:31  set
+
+       * DJGPP.why, GPL-license, README, compress.sh, files, doc/html.frt,
+         doc/reference.html, examples/Makefile, examples/linux_test.c,
+         examples/remote_test.c, examples/target_frames.cc,
+         examples/test_target.cc, examples/x11_cpp_test.cc,
+         examples/x11_fr_test.c, examples/x11_test.c,
+         examples/x11_wp_test.c, src/Makefile, src/alloc.c,
+         src/breakpoint.c, src/connect.c, src/cpp_int.cc, src/data_man.c,
+         src/error.c, src/get_free_vt.c, src/mi_gdb.h, src/misc.c,
+         src/parse.c, src/prg_control.c, src/stack_man.c,
+         src/symbol_query.c, src/target_man.c, src/thread.c,
+         src/var_obj.c:
+
+       Imported sources, current version is 0.8.0
+
+2004-07-20 15:31  set
+
+       * DJGPP.why, GPL-license, README, compress.sh, files, doc/html.frt,
+         doc/reference.html, examples/Makefile, examples/linux_test.c,
+         examples/remote_test.c, examples/target_frames.cc,
+         examples/test_target.cc, examples/x11_cpp_test.cc,
+         examples/x11_fr_test.c, examples/x11_test.c,
+         examples/x11_wp_test.c, src/Makefile, src/alloc.c,
+         src/breakpoint.c, src/connect.c, src/cpp_int.cc, src/data_man.c,
+         src/error.c, src/get_free_vt.c, src/mi_gdb.h, src/misc.c,
+         src/parse.c, src/prg_control.c, src/stack_man.c,
+         src/symbol_query.c, src/target_man.c, src/thread.c,
+         src/var_obj.c:
+
+       Initial revision
+
diff --git a/DJGPP.why b/DJGPP.why
new file mode 100644 (file)
index 0000000..4f3cbda
--- /dev/null
+++ b/DJGPP.why
@@ -0,0 +1,101 @@
+DJGPP Problems and why it isn't currently supported:
+
+ Traditionaly djgpp never used gdb frontends. The reason is not so obvious.
+The main problem is that DOS isn't a multitasking OS. So you can't open a
+pipe to a child a process and multitask. The pipe command exists but you are
+blocked until the child finishes.
+For this reason there is no gdb frontend for djgpp. Instead djgpp users use
+full debuggers with a frontend included. That's the case of RHIDE (in this
+particular case gdb is inside RHIDE).
+ But most people using djgpp uses a multitasking OS, at least for development.
+The most common setup is Windows. Additionally you could use two DOS boxes
+and get real-hardware-multitask ;-)
+ The two possible setups are:
+
+1) Windows (win32): The frontend communicates with gdb using some IPC
+mechanism. The frontend uses the "start" (or similar) command to call gdb and
+then sends/receives the commands/responses using the IPC mechanism.
+Here Windows does the multitasking.
+That's completly transparent in most cases because the frontend starts gdb
+indicating which file to debug and the same front end controls gdb (including
+the end of sesssion).
+
+2) Two DOS boxes: The user must run gdb in one of the boxes indicating to
+connect to the other using some networking protocol. On the other side the
+frontend is started and waits for a incoming connection.
+This is a little bit more complicated because:
+a) The user must setup a network.
+b) The user must start things manually.
+
+ But there are some problems that doesn't allow it:
+
+GDB side:
+
+ GDB remote debugging isn't like this. It was designed for remote debug
+using multitasking systems and not things like DOS. When you use the remote
+debugging you run "gdbserver" on the "target" end and "gdb" on the local side
+(host). But then you are again in the same situation, you can't control gdb
+using pipes or similar mechanisms.
+
+ The solution for this is to tell gdb "Hey! use IPC for your command loop".
+But the problem is that gdb is a mess. It have a very nice abstraction for
+I/O implemented like classes (see ui-file.c). So you have gdb_stdout and
+gdb_stdin structures. But not all the code uses it, in fact the "readline"
+part (gdb prompt and input) bypass it.
+
+ To solve this you have to redirect at low level. Something like:
+
+a) Open a socket.
+b) dup2 stdin/stdout
+
+ This is the easy part because you have to avoid this redirection in the
+child or the output of the debuggy will also go throu the IPC channel. But I
+think it isn't that hard because gdb switches the stdout/in attributes when
+running the child process, so I think it is possible to also dup2 to the old
+handles while the child is running.
+
+  In any case all of this means changes in gdb.
+
+
+
+DJGPP side:
+
+ The "open socket and dup2" above mentioned mechanism works for POSIX systems
+like Linux (I tested it and worked, I was able to control gdb using TCP/IP
+sockets). But djgpp isn't POSIX.
+
+ DJGPP have a nice mechanism to for "File System Extensions", but when I
+tried it I found that dup2 doesn't work for extensions. I'm not sure if it
+can be done with some hack or if the last version of djgpp version solves
+this problem.
+
+ It most probably means that djgpp have to be modified. May be I'm wrong.
+
+
+
+IPC what?
+
+ Inter-Process Communication is quite simple on POSIX systems but for djgpp
+... Well, you can use a networking protocol, but again isn't that simple.
+ For TCP/IP you have:
+
+a) libsocket, it looks like it doesn't work very well with VSOCK 2. I tried
+it on Windows 98 SE and it failed.
+b) Watt-32, it needs a special NDIS driver for Windows.
+
+ Another option could be using mslot library. It seems to work (at least for
+Windows). It uses the "Mail Slot" mechanism. One problem I found in this
+library is that it implements the "read" FSEXT in a "non-blocking" way and
+doesn't honor the O_NONBLOCKING flag. The changes to fix it are really
+simple. According to mslot docs they are available for plain DOS.
+
+
+Conclusion:
+
+ It looks like is possible to achieve the above mentioned setups. But changes
+have to be made to gdb, djgpp and existing IPC libraries.
+ The gdb part seems to be the most complex and harder to be introduced in
+main gdb.
+
+
+SET
diff --git a/GPL-license b/GPL-license
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..f873b16
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+#!/usr/bin/make
+
+.PHONY: libmigdb
+
+all: libmigdb
+
+libmigdb:
+       $(MAKE) -C src
+
+clean:
+       $(MAKE) -C src clean
+
+install:
+       $(MAKE) -C src install
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..0f61c6f
--- /dev/null
+++ b/README
@@ -0,0 +1,124 @@
+Introduction:
+------------
+
+This library is an attempt to support the GDB/MI interface. MI stands for
+machine interface. In this mode gdb sends responses that are "machine
+readable" instead of "human readable"
+
+Objetive:
+--------
+
+To implement a C and C++ interface to talk with gdb using it.
+
+Advantages:
+----------
+
+* The responses should be i18n independent and with less problems to be parsed.
+* New versions shouldn't break the parser.
+
+Disadvantages:
+-------------
+
+* The responses are quite complex.
+* The responses can't be easily read by a human.
+
+Motivation:
+----------
+
+To add remote debugging to SETEdit. RHIDE lacks it.
+
+Currently supported platcforms:
+------------------------------
+
+Currently we support:
+
+* Linux console
+* Linux X11
+
+The code should be usable by other systems that provides POSIX API and where
+gdb is available.
+
+How to compile and install:
+--------------------------
+
+Change to the "src" directory and run "make". Change to root and run "make
+install".
+The "Makefile" could need changes. The PREFIX is /usr you most probably will
+want to change it to /usr/local.
+
+How to run examples:
+-------------------
+
+Switch to the "examples" directory and run "make". Read the comments at the
+beggining of the examples.
+They show how to use the library for different targets.
+
+* linux_test: Linux console. Shows how to set breakpoints and watchpoints.
+* remote_test: Remote debugging using TCP/IP connection. Shows breakpoints.
+* x11_cpp_test: Shows how to use the C++ wrapper. The examples is for X11.
+* x11_fr_test: Linux X11. Shows how to use "frames" and "variable objects".
+* x11_test: Linux X11. Shows how to set breakpoints and watchpoints.
+* x11_wp_test: Linux X11. Shows how to set watchpoints.
+
+Function reference and help:
+---------------------------
+
+An incomplete reference can be found in the "doc" directory. I suggest
+looking at the examples with the reference at hand.
+
+
+Author:
+------
+
+Salvador E. Tropea
+Email: user: set, server: users.sf.net
+
+     Telephone: (+5411) 4759-0013
+     Postal Address:
+     Salvador E. Tropea
+     Curapaligue 2124
+     (1678) Caseros - 3 de Febrero
+     Prov: Buenos Aires
+     Argentina
+
+-----------------------------------------------------------------------------
+
+Random notes:
+------------
+
+Debug strategies:
+
+1) Remote using TCP/IP: This methode is quite limited. One amazing thing I
+noticed is that you can't set watchpoints. Other important differences are
+that the remote target starts "running", it means you have to use continue
+instead of run and it also means that command line arguments must be provided
+at the remote end.
+The way that's implemented you need a full gdb on the local end. That's ok
+when you want to release the remote end from some of the heavy tasks (like
+loading all the debug info), but doesn't help if what you want is just
+control gdb from a remote machine sending the commands throu TCP/IP. The last
+could allow debugging DOS applications under Windows exploting the Windows
+multitasking.
+
+2) Local under X: We start an xterm child that runs:
+
+<--- /tmp/xxxxxx.sh
+tty > /tmp/yyyyyy
+sleep 100d
+<---
+
+That's "xterm -e /bin/sh /tmp/xxxxxx.sh &"
+Then we read /tmp/yyyyyy file to know the ttyname, delete both files and
+tell gdb to use this terminal.
+This is implemented by: gmi_start_xterm()
+
+3) Local for Linux console: We can open a new terminal (as X and Allegro
+does with tty8 and higher).
+This is implemented by: gmi_look_for_free_vt()
+
+4) Local for Linux console, same terminal: We tell gdb to use the current
+terminal, but before sending an async command we so Suspend and when we get
+an async response "stopped" we Resume. This is less functional and more
+complex.
+
+
diff --git a/change.log b/change.log
new file mode 100644 (file)
index 0000000..e490f31
--- /dev/null
@@ -0,0 +1,224 @@
+$Log: change.log,v $
+Revision 1.40  2010/05/19 19:30:23  set
+* Modified: [connect.c] To ignore \r characters from gdb. Markus Huebenthal
+saw them using gdb 6.8.
+* Modified: [prg_control.c] -readnow vs file name order. Don't remmember
+who pointed-out it.
+
+Revision 1.39  2010/02/18 13:18:05  set
+* Added: [ticepic.c examples/Makefile] Example of how to use something
+different than gdb.
+* Added: [x11_cpp_test.cc cmds.txt] Example of how to specify an starting
+commands file.
+* Added: [connect.c mi_gdb.h] Functionality to indicate a file containing
+commands to be executed at start-up and after connection.
+* Modified: [mi_gdb.h] Version to 0.8.12.
+* Fixed: [target_man.c] Return value for gmi_target_select.
+* Added: [.cvsignore] version executable exclusion.
+* Added: [examples/.cvsignore] ticepic binary exclusion.
+
+Revision 1.38  2007/06/13 12:26:47  set
+* Added: "from" field to the mi_frames structure. Suggested by Val Greene
+(vgreene/SF).
+* Modified: Version to 0.8.11.
+
+Revision 1.37  2007/05/11 14:16:24  set
+* Added: Implementation of the -target-download command, used to download
+a binary to the remote target.
+* Added: An option to MIDebugger::SelectTargetRemote used to load the
+binary to the remote target. Useful for embedded systems, tested with
+avr-gdb.
+
+Revision 1.36  2007/05/10 16:49:11  set
+* Added: AVR architecture.
+* Added: Workaround for bugs in -gdb-show architecture. Seen on gdb 6.4.x.
+
+Revision 1.35  2007/05/03 11:51:09  set
+* Added: pic14 architecture. That's for an in-circuit emulator that I'm
+developing.
+
+Revision 1.34  2007/04/30 16:43:49  set
+* Fixed: When parsing an address from gdb strtol isn't suitable, strtoul
+is better.
+
+Revision 1.33  2005/09/26 18:38:35  set
+* Fixed: Apple seem to have changed the output type for stack frames to be
+a tuple of tuples rather than a list of tuples. Patch from Greg.
+
+Revision 1.32  2005/06/03 13:03:19  set
+* Fixed: Breakpoint parser filled the "type" field instead of the "disp"
+field. Patch by Max Kovalenko (madmax/botik/ru).
+* Modified: Version to 0.8.10.
+
+Revision 1.31  2005/05/13 19:29:54  set
+* Fixed: pty_test.c to also exit when read returns 0 (Linux case). Patch
+from Greg.
+
+Revision 1.30  2005/05/12 20:23:02  set
+* Modified: Regenerated the docs to include the new documentation about
+ptys. Also changed the docs to name version 0.8.9.
+
+Revision 1.29  2005/05/12 20:18:56  set
+* Applied patches from Greg Watson (gwatson/lanl/gov):
+  * Removes apple code from src/get_free_vt.c
+  * Adds a new file src/get_free_pty.c This is a new functionality to
+    communicate with the debuggie using a pseudo terminal.
+  * Adds new mi_pty structure to src/mi_gdb.h
+  * Modifies src/Makefile to build get_free_pty.o
+  * Adds new file examples/pty_test.c
+  * Modifies examples/Makefile to build pty_test
+
+Revision 1.28  2005/04/29 20:11:13  set
+* Applied patches from Greg Watson (gwatson/lanl/gov):
+  * Add pty support for Darwin, including extending the mi_aux_term
+    structure to include a file descriptor for the master side of the pty.
+    This allows the code to prevent a race condition between checking for a
+    free pty and opening it.
+  * Rename mi_get_sttoped() to mi_get_stopped() and expose the interface
+    in mi_gdb.h.
+  * Added new gmi_exec_next_cnt() and gmi_exec_stop_cnt() commands.
+  * Add support for the broken Darwin version of gdb (tuples can contain
+    values as well as results).
+  * Fix the 'signal-name' and 'signal-meaning' variable names (were
+    'signal_name' and 'signal_meaning').
+  * Allow a 'count' argument to be supplied to mi_exec_step() and
+    mi_exec_next().
+
+Revision 1.27  2004/12/06 15:51:04  set
+* Fixed: Compilations problems for SuSE 5.2. Reported by J.B. Lethbridge.
+
+Revision 1.26  2004/10/19 16:21:40  set
+* Fixed: FinishFun member must set the state to running if the command
+succeed.
+
+Revision 1.25  2004/10/18 19:39:17  set
+* Modified: Version to 0.8.7.
+
+Revision 1.24  2004/10/18 19:35:40  set
+* Fixed: Various examples to compile with current code.
+* Fixed: Some missing headers. Needed to compile on BSD systems.
+
+Revision 1.23  2004/10/15 23:50:37  set
+* Added: [Cygwin] Some minimal support. Now when the target is selected we
+tell gdb to use a new window. It seems to work but the new window have some
+serious problems.
+
+Revision 1.22  2004/09/16 23:18:26  set
+* Modified: To compile with Cygwin. It doesn't mean it works, just
+compiles.
+
+Revision 1.21  2004/09/10 19:10:20  set
+* Added: A top level makefile, is just a wrapper for the src/Makefile.
+* Modified: Version to 0.8.6.
+
+Revision 1.20  2004/09/08 18:09:46  set
+* Added: C++ member to find and cache the architecture. Currently supported
+architectures are IA32 (x86) and SPARC. They are the only archs I have at
+hand.
+
+Revision 1.19  2004/09/07 19:56:28  set
+* Fixed: Lack of error report when we failed to create the temporal files
+to spawn an X terminal.
+* Fixed: Now we test if the X terminal and gdb binary are there and report
+proper errors if they are missing.
+
+Revision 1.18  2004/09/06 17:13:11  set
+* Added: Functions to workaround another bug in gdb. I reported it and it
+was named "mi/1770". Affects gdb 6.x.
+
+Revision 1.17  2004/08/25 20:49:52  set
+* Modified: mi_error reset to MI_OK when connecting.
+* Modified: MIDebugger::TargetUnselect() to detach only if remote/pid is
+stopped.
+* Added: execute until address is reached (we had file:line only).
+
+Revision 1.16  2004/08/24 21:10:21  set
+* Modified: PID targets starts stopped.
+* Fixed: When debugging an attached process if gdb dies we failed to go to
+disconnected.
+
+Revision 1.15  2004/08/23 23:45:23  set
+* Added: Mechanism to disable psym workarounds. The mechanism allows to
+enable/disable workarounds in a simple and compatible way.
+* Added: Mechanism to force MI version.
+* Added: Enabled a couple of MI v2 things when the version is forced to 2+.
+* Added: BreakAfter(mi_bkpt *b) C++ wrapper.
+
+Revision 1.14  2004/08/17 20:40:11  set
+* Added: Disassembler functionality.
+
+Revision 1.13  2004/08/13 20:36:08  set
+* Modified: The mechanism to set gdb and xterm binaries. Now you can get
+the actual default (it searches in PATH) and set a new value that's copied.
+* Added: Functions to set the "main" function.
+* Added: Time out callback to catch time-outs in gdb response.
+* Added: Mechanism to detect gdb died and go to disconnected state. We
+already found an operation that makes gdb die.
+
+Revision 1.12  2004/08/12 21:21:43  set
+* Added: Command to get info about the threads. It uses a partially
+implemented gdb functionality.
+
+Revision 1.11  2004/08/09 12:58:23  set
+* Updated: version and reference to release 0.8.3.
+
+Revision 1.10  2004/08/08 23:07:00  set
+* Added: A function to know the endian of the target.
+* Added: A workaround to another bug in gdb: responses like the endian and
+architecture are sent to the console and not to the result record. So now
+the -gdb-show command traps the console (a copy) and if the RR have no info
+and we got something in the console that's returned.
+
+Revision 1.9  2004/08/06 20:59:44  set
+* Fixed: The gdb dialog was amazingly slow. It was just the fact that I
+trusted in the non-blocking flag and sleep, but this annoys the scheduler
+and the solution is to just use select, which is the Right Thing To Do (TM)
+;-)
+* Modified: MIDebugger::EvalExpression now takes a const char * and cleans
+the error number before executing.
+* Added: Some very restricted function to read memory content.
+
+Revision 1.8  2004/08/04 20:07:31  set
+* Modified: The mi_gvar structure to be able to hold a tree of variables.
+* Fixed: mi_error_from_gdb not released at exit.
+* Fixed: leak in Kill()
+* Fixed/Added: Various details of the GNU vars code.
+
+Revision 1.7  2004/08/01 00:16:13  set
+* Added: More fields to the mi_wp structure, useful for the frontend.
+* Fixed: Watchpoint expressions must be enclosed using "" to avoid
+problems.
+* Fixed: wp_mode name to mi_wp_mode.
+* Added: int MIDebugger::WatchDelete(mi_wp *w).
+* Fixed: sr_wp_scope doesn't report a full wp, just the number.
+
+Revision 1.6  2004/07/30 21:17:08  set
+* Added: More workarounds to gdb bugs. I fille the cli/1725, gdb/1726 and
+gdb/1727 bug reports. I hope they get fixed :-(
+
+Revision 1.5  2004/07/28 21:09:40  set
+* Fixed: Some mess in the bkpts structure. The "times" field is how many
+times we hit a breakpoint, just information. The real value is "ignore".
+* Fixed: Missing parse of the "cond" field for breakpoints.
+* Added: A C++ function to set a breakpoint from a mi_bkpt structure. It
+supports the four modes to specify a location.
+
+Revision 1.4  2004/07/25 22:58:07  set
+* Added: More fields to the mi_bkpt structure.
+
+Revision 1.3  2004/07/21 19:43:39  set
+* Added: A workaround to a bug in gdb: the two stages load of symtabs
+(using partial ones) is not reliable (fails to find the symtab in some
+cases). So now we force the load with "readnow".
+* Fixed: Lack of string.h in examples/target_frames.cc. Reported by Thiago.
+
+Revision 1.2  2004/07/20 23:42:56  set
+* Fixed: directory in compressed sources.
+
+Revision 1.1  2004/07/20 20:38:42  set
+* Added: C++ wrapper to attach to a running process. Also modified the low
+level function to return the current frame.
+* Modified: Now if we get an error while the state is running we assume the
+previous "running" was wrong and we are in fact stopped. Until now I saw
+two cases where gdb says we are running and then shows an error.
+
diff --git a/compress.sh b/compress.sh
new file mode 100755 (executable)
index 0000000..7903952
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+gcc -o version version.c
+cd ..
+tar jcvf libmigdb-`libmigdb/version`.tar.bz2 `cat libmigdb/files`
diff --git a/doc/html.frt b/doc/html.frt
new file mode 100644 (file)
index 0000000..92082d3
--- /dev/null
@@ -0,0 +1,282 @@
+#
+# This file sets the behavior of the txh generator
+#
+# Lines starting with # or spaces are skiped except in strings or in [Generate]
+# Be carefull with [ it delimits sections!
+#
+
+[Configuration]
+#
+# No external program is needed!
+# @.html means: Copy the temporal file to xxxxx.html
+#
+CommandLine=@.html
+Name="Direct HTML 3.X format"
+
+[Delimiters]
+# Up to 11 characters
+SectionStart=/**[txh]**
+# Up to 11 characters
+SectionEnd=*********/
+
+[Variables]
+#
+# Up to 16 definitions
+#
+# Codes for the behavior of the definitions:
+# 1 Normal, put the content if found.
+# 2 Repeat, use the last value found in the file, ~no is an exeption, ~clear stops
+# 3 If not found replace by the prototype.
+# 4 If not found replace by the class.
+# 5 If not found replace by the name of the function
+# 6 It disables the node generation for this comment. The variable is
+#   stored in the first variable that have associations and is in the comment.
+#
+# Additionally there are 2 special variables:
+# 90 Name of the file
+# 91 Line number of the end of the comment
+# 92 Name of the var 0 in the format: ~0 ~~Distinguish{(~Distinguish)~} (node name)
+#
+# 0 The first variable is the main index variable
+#
+AddDefinition=Function,5
+# 1
+AddDefinition=Class,4
+# 2
+AddDefinition=Include,2
+# 3
+AddDefinition=Module,2
+# 4
+AddDefinition=Prototype,3
+# 5
+AddDefinition=Description,1
+# 6
+AddDefinition=Return,1
+# 7
+AddDefinition=Example,1
+# 8
+AddDefinition=Comments,6
+# 9
+AddDefinition=Command,1
+#
+# It says what variable is added to distinguish between 2 vars 0 that are equal
+#
+Distinguish=1
+
+[Associations]
+#
+# Up to 8 associations
+#
+# The associations are between the 0 variable and another variable.
+#
+# Name in main menu, node, variable, optional to add to each node
+#
+AddAssoc=List by classes,Classes,1,(class)
+AddAssoc=List by modules,Modules,3
+AddAssoc=List by files,Files,90
+AddAssoc=List by GDB/MI command,Command,9
+
+[Replace]
+#
+# All must be delimited by ", they can be used in the GenMain section
+#
+# Title of the HTML
+Constant="GDB/MI library"
+
+# Description for the help
+Constant="This document describes the functions of libmigdb library
+@p
+This document applies to version 0.8.10 of the GDB/Machine interface
+library.
+@p
+Most of the C++ interface is fully documented. But not all the C
+interface is docummented.
+@p
+The name of the high level C functions are derived from the corresponding
+GDB/MI command. For this reason I recommend using the chapter 'GDB/MI' of
+gdb documentation as main reference. As an example: The gdb command
+'-thread-list-ids' is implemented in the gmi_thread_list_ids function. This
+function uses the lowlevel function mi_thread_list_ids.
+@p
+The mi_gdb.h header contains a lot of comments about what does each
+function. And the examples show how to them together.
+@p
+"
+
+[Commands]
+#
+# You can enclose these values between " to make more clear where
+# they start and end. Use \n,\r,\t and \" like in C. Use \ at the
+# end to concatenate like in C.
+#
+# @p = end of paragraph
+#
+EndOfPar="<p>"
+#
+# @* = break line
+#
+BreakLine="<br>"
+#
+# @{value} is the special cross ref.
+# ~0 Is the visible name of a reference
+# ~1 Is the real name of a reference
+#
+CrossRef="<a href=\"#~1\">~0</a>"
+#
+# What we must get from a @@ sequence
+#
+Double@="@"
+
+[DefinedCommands]
+#
+# The format is @<name>{parameters ...}
+#
+subtitle="<Font Size=+1><u>~0</u></Font><p>"
+pre=<pre>
+/pre=</pre>
+link="<a href=\"~0\">~1</a>"
+mailto="<a href=\"mailto:~0\">~1</a>"
+
+#
+# This section says how to translate ASCIIs
+#
+[ASCIIConvert]
+ =&aacute;
+\82=&eacute;
+¡=&iacute;
+¢=&oacute;
+£=&uacute;
+¤=&ntilde;
+Â¥=&Ntilde;
+­=&iexcl;
+¨=&iquest;
+\84=&auml;
+\89=&euml;
+\8b=&iuml;
+\94=&ouml;
+\81=&uuml;
+\9a=&Uuml;
+\85=&agrave;
+\8a=&egrave;
+\8d=&igrave;
+\95=&ograve;
+\97=&ugrave;
+<=&lt;
+>=&gt;
+
+#
+#  Use ~number to use one variable
+#  Use ~~number{} for conditional, all the code inside {} will become
+# conditional
+#  This section isn't passed for the macro expansion so here you are
+# free to use special commands for the formater.
+#
+[GenNode]
+<p><hr></p>
+<a name="~92"></a>
+<center><Font Size=+2>~0</Font> (~90 ~91)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+~~2{
+<pre>
+# This line is a comment, but the next is code
+ #include &lt;~2&gt;
+</pre>
+~}
+~~4{
+<pre>
+ ~4;
+</pre>
+~}
+~~1{
+<Font Size=+1><u>Member of the class:</u></Font>
+~1
+<p>
+~}
+
+~~5{
+<Font Size=+1><u>Description</u></Font><p>
+
+~5
+<p>
+~}
+~~6{
+<Font Size=+1><u>Return Value</u></Font><p>
+
+~6
+<p>
+~}
+~~7{
+<Font Size=+1><u>Example</u></Font><p>
+
+~7
+<p>
+~}
+
+[GenMenu]
+Start="<Menu>"
+#
+# ~1 is the visible name
+# ~2 is the name of the node
+#
+Entry="<li><a href=\"#~2\">~1</a>"
+End="</Menu>"
+
+#
+# ~1  is the name of the association
+# ~2  is the menu for it
+#
+[GenAssoMain]
+<p><hr></p>
+<a name="~1"></a>
+<H1>~1</H1>
+
+~2
+#
+# ~1  is the name of the association
+# ~2  is the name without the distinguish
+# ~3  is the comment for it
+# ~4  is the menu for it
+#
+[GenAssoRest]
+<p><hr></p>
+<a name="~1"></a>
+<H1>~2</H1>
+
+~3
+
+~4
+
+#
+# ~1 Main menu
+# ~2 Name of the function list node
+# ~3 Menu for all the functions
+# ~4 All the associations code
+# ~5 All the function nodes
+# ~50+ Values from section Replace
+#
+[GenMain]
+<html>
+<head>
+<title>~50</title>
+</head>
+<body>
+<H1>~50</H1>
+
+~51
+
+~1
+
+<p><hr></p>
+<a name="~2"></a>
+<H1>~2</H1>
+
+~3
+
+~4
+
+~5
+
+</body>
+</html>
diff --git a/doc/reference.html b/doc/reference.html
new file mode 100644 (file)
index 0000000..453f0ad
--- /dev/null
@@ -0,0 +1,5072 @@
+<html>
+<head>
+<title>GDB/MI library</title>
+</head>
+<body>
+<H1>GDB/MI library</H1>
+
+This document describes the functions of libmigdb library
+
+<p>
+
+This document applies to version 0.8.10 of the GDB/Machine interface
+library.
+
+<p>
+
+Most of the C++ interface is fully documented. But not all the C
+interface is docummented.
+
+<p>
+
+The name of the high level C functions are derived from the corresponding
+GDB/MI command. For this reason I recommend using the chapter 'GDB/MI' of
+gdb documentation as main reference. As an example: The gdb command
+'-thread-list-ids' is implemented in the gmi_thread_list_ids function. This
+function uses the lowlevel function mi_thread_list_ids.
+
+<p>
+
+The mi_gdb.h header contains a lot of comments about what does each
+function. And the examples show how to them together.
+
+<p>
+
+
+
+<Menu>
+<li><a href="#Alphabetical List">Alphabetical list of functions</a>
+<li><a href="#Classes">List by classes</a>
+<li><a href="#Modules">List by modules</a>
+<li><a href="#Files">List by files</a>
+<li><a href="#Command">List by GDB/MI command</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Alphabetical List"></a>
+<H1>Alphabetical List</H1>
+
+<Menu>
+<li><a href="#BreakDelete (MIDebugger)">BreakDelete (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger)">Breakpoint (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger) <1>">Breakpoint (MIDebugger) <1></a>
+<li><a href="#BreakpointFull (MIDebugger)">BreakpointFull (MIDebugger)</a>
+<li><a href="#CallStack (MIDebugger)">CallStack (MIDebugger)</a>
+<li><a href="#Connect (MIDebugger)">Connect (MIDebugger)</a>
+<li><a href="#Continue (MIDebugger)">Continue (MIDebugger)</a>
+<li><a href="#Disconnect (MIDebugger)">Disconnect (MIDebugger)</a>
+<li><a href="#EvalExpression (MIDebugger)">EvalExpression (MIDebugger)</a>
+<li><a href="#FillTypeVal (MIDebugger)">FillTypeVal (MIDebugger)</a>
+<li><a href="#FinishFun (MIDebugger)">FinishFun (MIDebugger)</a>
+<li><a href="#gmi_break_delete">gmi_break_delete</a>
+<li><a href="#gmi_break_insert">gmi_break_insert</a>
+<li><a href="#gmi_break_insert_full">gmi_break_insert_full</a>
+<li><a href="#gmi_break_insert_full_fl">gmi_break_insert_full_fl</a>
+<li><a href="#gmi_break_set_condition">gmi_break_set_condition</a>
+<li><a href="#gmi_break_set_times">gmi_break_set_times</a>
+<li><a href="#gmi_break_state">gmi_break_state</a>
+<li><a href="#gmi_break_watch">gmi_break_watch</a>
+<li><a href="#gmi_data_evaluate_expression">gmi_data_evaluate_expression</a>
+<li><a href="#gmi_dir">gmi_dir</a>
+<li><a href="#gmi_end_aux_term">gmi_end_aux_term</a>
+<li><a href="#gmi_end_pty">gmi_end_pty</a>
+<li><a href="#gmi_exec_continue">gmi_exec_continue</a>
+<li><a href="#gmi_exec_finish">gmi_exec_finish</a>
+<li><a href="#gmi_exec_interrupt">gmi_exec_interrupt</a>
+<li><a href="#gmi_exec_kill">gmi_exec_kill</a>
+<li><a href="#gmi_exec_next">gmi_exec_next</a>
+<li><a href="#gmi_exec_next_cnt">gmi_exec_next_cnt</a>
+<li><a href="#gmi_exec_next_instruction">gmi_exec_next_instruction</a>
+<li><a href="#gmi_exec_return">gmi_exec_return</a>
+<li><a href="#gmi_exec_run">gmi_exec_run</a>
+<li><a href="#gmi_exec_step">gmi_exec_step</a>
+<li><a href="#gmi_exec_step_cnt">gmi_exec_step_cnt</a>
+<li><a href="#gmi_exec_step_instruction">gmi_exec_step_instruction</a>
+<li><a href="#gmi_exec_until">gmi_exec_until</a>
+<li><a href="#gmi_exec_until_addr">gmi_exec_until_addr</a>
+<li><a href="#gmi_file_symbol_file">gmi_file_symbol_file</a>
+<li><a href="#gmi_full_var_create">gmi_full_var_create</a>
+<li><a href="#gmi_gdb_exit">gmi_gdb_exit</a>
+<li><a href="#gmi_gdb_set">gmi_gdb_set</a>
+<li><a href="#gmi_gdb_show">gmi_gdb_show</a>
+<li><a href="#gmi_gdb_version">gmi_gdb_version</a>
+<li><a href="#gmi_look_for_free_pty">gmi_look_for_free_pty</a>
+<li><a href="#gmi_look_for_free_vt">gmi_look_for_free_vt</a>
+<li><a href="#gmi_set_exec">gmi_set_exec</a>
+<li><a href="#gmi_stack_info_depth">gmi_stack_info_depth</a>
+<li><a href="#gmi_stack_info_depth_get">gmi_stack_info_depth_get</a>
+<li><a href="#gmi_stack_info_frame">gmi_stack_info_frame</a>
+<li><a href="#gmi_stack_list_arguments">gmi_stack_list_arguments</a>
+<li><a href="#gmi_stack_list_arguments_r">gmi_stack_list_arguments_r</a>
+<li><a href="#gmi_stack_list_frames">gmi_stack_list_frames</a>
+<li><a href="#gmi_stack_list_frames_r">gmi_stack_list_frames_r</a>
+<li><a href="#gmi_stack_list_locals">gmi_stack_list_locals</a>
+<li><a href="#gmi_stack_select_frame">gmi_stack_select_frame</a>
+<li><a href="#gmi_start_xterm">gmi_start_xterm</a>
+<li><a href="#gmi_target_attach">gmi_target_attach</a>
+<li><a href="#gmi_target_detach">gmi_target_detach</a>
+<li><a href="#gmi_target_select">gmi_target_select</a>
+<li><a href="#gmi_target_terminal">gmi_target_terminal</a>
+<li><a href="#gmi_thread_list_all_threads">gmi_thread_list_all_threads</a>
+<li><a href="#gmi_thread_list_ids">gmi_thread_list_ids</a>
+<li><a href="#gmi_thread_select">gmi_thread_select</a>
+<li><a href="#gmi_var_assign">gmi_var_assign</a>
+<li><a href="#gmi_var_create">gmi_var_create</a>
+<li><a href="#gmi_var_create_nm">gmi_var_create_nm</a>
+<li><a href="#gmi_var_delete">gmi_var_delete</a>
+<li><a href="#gmi_var_evaluate_expression">gmi_var_evaluate_expression</a>
+<li><a href="#gmi_var_info_expression">gmi_var_info_expression</a>
+<li><a href="#gmi_var_info_num_children">gmi_var_info_num_children</a>
+<li><a href="#gmi_var_info_type">gmi_var_info_type</a>
+<li><a href="#gmi_var_list_children">gmi_var_list_children</a>
+<li><a href="#gmi_var_set_format">gmi_var_set_format</a>
+<li><a href="#gmi_var_show_attributes">gmi_var_show_attributes</a>
+<li><a href="#gmi_var_show_format">gmi_var_show_format</a>
+<li><a href="#gmi_var_update">gmi_var_update</a>
+<li><a href="#GoTo (MIDebugger)">GoTo (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger) <1>">GoTo (MIDebugger) <1></a>
+<li><a href="#Kill (MIDebugger)">Kill (MIDebugger)</a>
+<li><a href="#mi_connect_local">mi_connect_local</a>
+<li><a href="#mi_disconnect">mi_disconnect</a>
+<li><a href="#mi_force_version">mi_force_version</a>
+<li><a href="#mi_get_error_str">mi_get_error_str</a>
+<li><a href="#mi_get_workaround">mi_get_workaround</a>
+<li><a href="#mi_look_for_free_pty">mi_look_for_free_pty</a>
+<li><a href="#mi_look_for_free_vt">mi_look_for_free_vt</a>
+<li><a href="#mi_set_workaround">mi_set_workaround</a>
+<li><a href="#MIDebugger (MIDebugger)">MIDebugger (MIDebugger)</a>
+<li><a href="#ModifyExpression (MIDebugger)">ModifyExpression (MIDebugger)</a>
+<li><a href="#Poll (MIDebugger)">Poll (MIDebugger)</a>
+<li><a href="#ReturnNow (MIDebugger)">ReturnNow (MIDebugger)</a>
+<li><a href="#Run (MIDebugger)">Run (MIDebugger)</a>
+<li><a href="#RunOrContinue (MIDebugger)">RunOrContinue (MIDebugger)</a>
+<li><a href="#RunToMain (MIDebugger)">RunToMain (MIDebugger)</a>
+<li><a href="#SelectTargetLinux (MIDebugger)">SelectTargetLinux (MIDebugger)</a>
+<li><a href="#SelectTargetPID (MIDebugger)">SelectTargetPID (MIDebugger)</a>
+<li><a href="#SelectTargetRemote (MIDebugger)">SelectTargetRemote (MIDebugger)</a>
+<li><a href="#SelectTargetTTY (MIDebugger)">SelectTargetTTY (MIDebugger)</a>
+<li><a href="#SelectTargetX11 (MIDebugger)">SelectTargetX11 (MIDebugger)</a>
+<li><a href="#Send (MIDebugger)">Send (MIDebugger)</a>
+<li><a href="#StepOver (MIDebugger)">StepOver (MIDebugger)</a>
+<li><a href="#Stop (MIDebugger)">Stop (MIDebugger)</a>
+<li><a href="#TargetUnselect (MIDebugger)">TargetUnselect (MIDebugger)</a>
+<li><a href="#TraceInto (MIDebugger)">TraceInto (MIDebugger)</a>
+<li><a href="#WatchDelete (MIDebugger)">WatchDelete (MIDebugger)</a>
+<li><a href="#Watchpoint (MIDebugger)">Watchpoint (MIDebugger)</a>
+<li><a href="#~MIDebugger (MIDebugger)">~MIDebugger (MIDebugger)</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Classes"></a>
+<H1>Classes</H1>
+
+<Menu>
+<li><a href="#MIDebugger (class)">MIDebugger</a>
+</Menu>
+
+
+<p><hr></p>
+<a name="MIDebugger (class)"></a>
+<H1>MIDebugger</H1>
+
+
+
+<Menu>
+<li><a href="#BreakDelete (MIDebugger)">BreakDelete (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger)">Breakpoint (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger) <1>">Breakpoint (MIDebugger) <1></a>
+<li><a href="#BreakpointFull (MIDebugger)">BreakpointFull (MIDebugger)</a>
+<li><a href="#CallStack (MIDebugger)">CallStack (MIDebugger)</a>
+<li><a href="#Connect (MIDebugger)">Connect (MIDebugger)</a>
+<li><a href="#Continue (MIDebugger)">Continue (MIDebugger)</a>
+<li><a href="#Disconnect (MIDebugger)">Disconnect (MIDebugger)</a>
+<li><a href="#EvalExpression (MIDebugger)">EvalExpression (MIDebugger)</a>
+<li><a href="#FillTypeVal (MIDebugger)">FillTypeVal (MIDebugger)</a>
+<li><a href="#FinishFun (MIDebugger)">FinishFun (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger)">GoTo (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger) <1>">GoTo (MIDebugger) <1></a>
+<li><a href="#Kill (MIDebugger)">Kill (MIDebugger)</a>
+<li><a href="#MIDebugger (MIDebugger)">MIDebugger (MIDebugger)</a>
+<li><a href="#ModifyExpression (MIDebugger)">ModifyExpression (MIDebugger)</a>
+<li><a href="#Poll (MIDebugger)">Poll (MIDebugger)</a>
+<li><a href="#ReturnNow (MIDebugger)">ReturnNow (MIDebugger)</a>
+<li><a href="#Run (MIDebugger)">Run (MIDebugger)</a>
+<li><a href="#RunOrContinue (MIDebugger)">RunOrContinue (MIDebugger)</a>
+<li><a href="#RunToMain (MIDebugger)">RunToMain (MIDebugger)</a>
+<li><a href="#SelectTargetLinux (MIDebugger)">SelectTargetLinux (MIDebugger)</a>
+<li><a href="#SelectTargetPID (MIDebugger)">SelectTargetPID (MIDebugger)</a>
+<li><a href="#SelectTargetRemote (MIDebugger)">SelectTargetRemote (MIDebugger)</a>
+<li><a href="#SelectTargetTTY (MIDebugger)">SelectTargetTTY (MIDebugger)</a>
+<li><a href="#SelectTargetX11 (MIDebugger)">SelectTargetX11 (MIDebugger)</a>
+<li><a href="#Send (MIDebugger)">Send (MIDebugger)</a>
+<li><a href="#StepOver (MIDebugger)">StepOver (MIDebugger)</a>
+<li><a href="#Stop (MIDebugger)">Stop (MIDebugger)</a>
+<li><a href="#TargetUnselect (MIDebugger)">TargetUnselect (MIDebugger)</a>
+<li><a href="#TraceInto (MIDebugger)">TraceInto (MIDebugger)</a>
+<li><a href="#WatchDelete (MIDebugger)">WatchDelete (MIDebugger)</a>
+<li><a href="#Watchpoint (MIDebugger)">Watchpoint (MIDebugger)</a>
+<li><a href="#~MIDebugger (MIDebugger)">~MIDebugger (MIDebugger)</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Modules"></a>
+<H1>Modules</H1>
+
+<Menu>
+<li><a href="#Allocator.">Allocator.</a>
+<li><a href="#Breakpoint table commands.">Breakpoint table commands.</a>
+<li><a href="#C++ Interface.">C++ Interface.</a>
+<li><a href="#Connect.">Connect.</a>
+<li><a href="#Data manipulation.">Data manipulation.</a>
+<li><a href="#Error.
+  Comment:
+  Translates error numbers into messages.">Error.
+  Comment:
+  Translates error numbers into messages.</a>
+<li><a href="#Linux VT.">Linux VT.</a>
+<li><a href="#Miscellaneous commands.">Miscellaneous commands.</a>
+<li><a href="#Parser.">Parser.</a>
+<li><a href="#Program control.">Program control.</a>
+<li><a href="#pseudo terminal">pseudo terminal</a>
+<li><a href="#Stack manipulation.">Stack manipulation.</a>
+<li><a href="#Symbol query.">Symbol query.</a>
+<li><a href="#Target manipulation.">Target manipulation.</a>
+<li><a href="#Thread commands.">Thread commands.</a>
+<li><a href="#Variable objects.">Variable objects.</a>
+</Menu>
+
+
+<p><hr></p>
+<a name="Allocator."></a>
+<H1>Allocator.</H1>
+
+Most alloc/free routines are here. Free routines must accept NULL
+pointers. Alloc functions must set mi_error.
+<p>
+
+
+<Menu>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Breakpoint table commands."></a>
+<H1>Breakpoint table commands.</H1>
+
+GDB/MI commands for the "Breakpoint Table Commands" section.
+<p>
+
+
+<pre>
+gdb command:          Implemented?
+
+-break-after          Yes
+-break-condition      Yes
+-break-delete         Yes
+-break-disable        Yes
+-break-enable         Yes
+-break-info           N.A. (info break NUMBER) (*)
+-break-insert         Yes
+-break-list           No (*)
+-break-watch          Yes
+</pre>
+
+(*) I think the program should keep track of the breakpoints, so it will
+be implemented when I have more time.
+<p>
+
+
+<Menu>
+<li><a href="#gmi_break_delete">gmi_break_delete</a>
+<li><a href="#gmi_break_insert">gmi_break_insert</a>
+<li><a href="#gmi_break_insert_full">gmi_break_insert_full</a>
+<li><a href="#gmi_break_insert_full_fl">gmi_break_insert_full_fl</a>
+<li><a href="#gmi_break_set_condition">gmi_break_set_condition</a>
+<li><a href="#gmi_break_set_times">gmi_break_set_times</a>
+<li><a href="#gmi_break_state">gmi_break_state</a>
+<li><a href="#gmi_break_watch">gmi_break_watch</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="C++ Interface."></a>
+<H1>C++ Interface.</H1>
+
+Implements a very simple (naive ;-) C++ wrapper.
+<p>
+
+
+<Menu>
+<li><a href="#BreakDelete (MIDebugger)">BreakDelete (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger)">Breakpoint (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger) <1>">Breakpoint (MIDebugger) <1></a>
+<li><a href="#BreakpointFull (MIDebugger)">BreakpointFull (MIDebugger)</a>
+<li><a href="#CallStack (MIDebugger)">CallStack (MIDebugger)</a>
+<li><a href="#Connect (MIDebugger)">Connect (MIDebugger)</a>
+<li><a href="#Continue (MIDebugger)">Continue (MIDebugger)</a>
+<li><a href="#Disconnect (MIDebugger)">Disconnect (MIDebugger)</a>
+<li><a href="#EvalExpression (MIDebugger)">EvalExpression (MIDebugger)</a>
+<li><a href="#FillTypeVal (MIDebugger)">FillTypeVal (MIDebugger)</a>
+<li><a href="#FinishFun (MIDebugger)">FinishFun (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger)">GoTo (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger) <1>">GoTo (MIDebugger) <1></a>
+<li><a href="#Kill (MIDebugger)">Kill (MIDebugger)</a>
+<li><a href="#MIDebugger (MIDebugger)">MIDebugger (MIDebugger)</a>
+<li><a href="#ModifyExpression (MIDebugger)">ModifyExpression (MIDebugger)</a>
+<li><a href="#Poll (MIDebugger)">Poll (MIDebugger)</a>
+<li><a href="#ReturnNow (MIDebugger)">ReturnNow (MIDebugger)</a>
+<li><a href="#Run (MIDebugger)">Run (MIDebugger)</a>
+<li><a href="#RunOrContinue (MIDebugger)">RunOrContinue (MIDebugger)</a>
+<li><a href="#RunToMain (MIDebugger)">RunToMain (MIDebugger)</a>
+<li><a href="#SelectTargetLinux (MIDebugger)">SelectTargetLinux (MIDebugger)</a>
+<li><a href="#SelectTargetPID (MIDebugger)">SelectTargetPID (MIDebugger)</a>
+<li><a href="#SelectTargetRemote (MIDebugger)">SelectTargetRemote (MIDebugger)</a>
+<li><a href="#SelectTargetTTY (MIDebugger)">SelectTargetTTY (MIDebugger)</a>
+<li><a href="#SelectTargetX11 (MIDebugger)">SelectTargetX11 (MIDebugger)</a>
+<li><a href="#Send (MIDebugger)">Send (MIDebugger)</a>
+<li><a href="#StepOver (MIDebugger)">StepOver (MIDebugger)</a>
+<li><a href="#Stop (MIDebugger)">Stop (MIDebugger)</a>
+<li><a href="#TargetUnselect (MIDebugger)">TargetUnselect (MIDebugger)</a>
+<li><a href="#TraceInto (MIDebugger)">TraceInto (MIDebugger)</a>
+<li><a href="#WatchDelete (MIDebugger)">WatchDelete (MIDebugger)</a>
+<li><a href="#Watchpoint (MIDebugger)">Watchpoint (MIDebugger)</a>
+<li><a href="#~MIDebugger (MIDebugger)">~MIDebugger (MIDebugger)</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Connect."></a>
+<H1>Connect.</H1>
+
+This module handles the dialog with gdb, including starting and stopping
+gdb.
+<p>
+
+
+GDB Bug workaround for "file -readnow": I tried to workaround a bug using
+it but looks like this option also have bugs!!!! so I have to use the
+command line option --readnow.
+It also have a bug!!!! when the binary is changed and gdb must reload it
+this option is ignored. So it looks like we have no solution but 3 gdb bugs
+in a row.
+
+<Menu>
+<li><a href="#gmi_end_aux_term">gmi_end_aux_term</a>
+<li><a href="#gmi_start_xterm">gmi_start_xterm</a>
+<li><a href="#mi_connect_local">mi_connect_local</a>
+<li><a href="#mi_disconnect">mi_disconnect</a>
+<li><a href="#mi_force_version">mi_force_version</a>
+<li><a href="#mi_get_workaround">mi_get_workaround</a>
+<li><a href="#mi_set_workaround">mi_set_workaround</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Data manipulation."></a>
+<H1>Data manipulation.</H1>
+
+GDB/MI commands for the "Data manipulation" section.
+<p>
+
+
+<pre>
+gdb command:                       Implemented?
+
+-data-disassemble                  Yes
+-data-evaluate-expression          Yes
+-data-list-changed-registers       No
+-data-list-register-names          Yes
+-data-list-register-values         No
+-data-read-memory                  No
+-display-delete                    N.A. (delete display)
+-display-disable                   N.A. (disable display)
+-display-enable                    N.A. (enable display)
+-display-insert                    N.A. (display)
+-display-list                      N.A. (info display)
+-environment-cd                    No
+-environment-directory             Yes, MI v1 implementation
+-environment-path                  No
+</pre>
+
+Notes:
+<p>
+
+
+1) -display* aren't implemented. You can use CLI command display, but the
+results are sent to the console. So it looks like the best is to manually
+use -data-evaluate-expression to emulate it.
+<p>
+
+
+2) GDB bug mi/1770: Affects gdb&lt;=6.2, when you ask for the names of the
+registers you get it plus the name of the "pseudo-registers", but if you
+try to get the value of a pseudo-register you get an error saying the
+register number is invalid. I reported to gdb-patches@sources.redhat.com
+on 2004/08/25 and as I didn't get any answer I filled a bug report on
+2004/09/02. The patch to fix this annoying bug is:
+
+Index: gdb/mi/mi-main.c
+===================================================================
+RCS file: /cvs/src/src/gdb/mi/mi-main.c,v
+retrieving revision 1.64
+diff -u -r1.64 mi-main.c
+--- gdb/mi/mi-main.c    3 Aug 2004 00:57:27 -0000       1.64
++++ gdb/mi/mi-main.c    25 Aug 2004 14:12:50 -0000
+@ -423,7 +423,7 @
+      case, some entries of REGISTER_NAME will change depending upon
+      the particular processor being debugged.
+
+-  numregs = NUM_REGS;
++  numregs = NUM_REGS + NUM_PSEUDO_REGS;
+
+   if (argc == 0)
+     {
+----
+
+Note I had to remove an end of comment in the patch to include it here.
+This bug forced me to create another set of functions. The only way is to
+first get the values and then the names.
+Fixed by Changelog entry:
+
+2004-09-12  Salvador E. Tropea  &lt;set@users.sf.net&gt;
+            Andrew Cagney  &lt;cagney@gnu.org&gt;
+
+        * mi/mi-main.c (mi_cmd_data_list_changed_registers)
+        (mi_cmd_data_list_register_values)
+        (mi_cmd_data_write_register_values): Include the PSEUDO_REGS in
+        the register number computation.
+
+<Menu>
+<li><a href="#gmi_data_evaluate_expression">gmi_data_evaluate_expression</a>
+<li><a href="#gmi_dir">gmi_dir</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Error.
+  Comment:
+  Translates error numbers into messages."></a>
+<H1>Error.
+  Comment:
+  Translates error numbers into messages.</H1>
+
+
+
+<Menu>
+<li><a href="#mi_get_error_str">mi_get_error_str</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Linux VT."></a>
+<H1>Linux VT.</H1>
+
+Helper to find a free VT. That's 100% Linux specific.
+<p>
+
+  The code comes from "lconsole.c" from Allegro project and was originally
+created by Marek Habersack and then modified by George Foot. I addapted it
+to my needs and changed license from giftware to GPL.
+<p>
+
+
+<Menu>
+<li><a href="#gmi_look_for_free_vt">gmi_look_for_free_vt</a>
+<li><a href="#mi_look_for_free_vt">mi_look_for_free_vt</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Miscellaneous commands."></a>
+<H1>Miscellaneous commands.</H1>
+
+GDB/MI commands for the "Miscellaneous Commands" section.
+<p>
+
+
+<pre>
+gdb command:       Implemented?
+
+-gdb-exit          Yes
+-gdb-set           Yes
+-gdb-show          Yes
+-gdb-version       Yes
+</pre>
+
+<Menu>
+<li><a href="#gmi_gdb_exit">gmi_gdb_exit</a>
+<li><a href="#gmi_gdb_set">gmi_gdb_set</a>
+<li><a href="#gmi_gdb_show">gmi_gdb_show</a>
+<li><a href="#gmi_gdb_version">gmi_gdb_version</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Parser."></a>
+<H1>Parser.</H1>
+
+Parses the output of gdb. It basically converts the text from gdb into a
+tree (could be a complex one) that we can easily interpret using C code.
+
+<Menu>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Program control."></a>
+<H1>Program control.</H1>
+
+GDB/MI commands for the "Program Control" section.
+<p>
+
+
+<pre>
+gdb command:                   Implemented?
+
+-exec-abort                    N.A. (*) (kill, but with non-interactive options)
+-exec-arguments                Yes
+-exec-continue                 Yes  ASYNC
+-exec-finish                   Yes  ASYNC
+-exec-interrupt                Yes  ASYNC
+-exec-next                     Yes  ASYNC
+-exec-next-instruction         Yes  ASYNC
+-exec-return                   Yes
+-exec-run                      Yes  ASYNC
+-exec-show-arguments           N.A. (show args) see gmi_stack_info_frame
+-exec-step                     Yes  ASYNC
+-exec-step-instruction         Yes  ASYNC
+-exec-until                    Yes  ASYNC
+-file-exec-and-symbols         Yes
+-file-exec-file                No
+-file-list-exec-sections       N.A. (info file)
+-file-list-exec-source-files   N.A.
+-file-list-shared-libraries    N.A.
+-file-list-symbol-files        N.A.
+-file-symbol-file              Yes
+</pre>
+
+(*)  gmi_exec_kill implements it, but you should ensure that
+gmi_gdb_set("confirm","off") was called.
+<p>
+
+
+GDB Bug workaround for -file-exec-and-symbols and -file-symbol-file: This
+is complex, but a real bug. When you set a breakpoint you never know the
+name of the file as it appears in the debug info. So you can be specifying
+an absolute file name or a relative file name. The reference point could be
+different than the one used in the debug info. To solve all the combinations
+gdb does a search trying various combinations. GDB isn't very smart so you
+must at least specify the working directory and the directory where the
+binary is located to get a good chance (+ user options to solve the rest).
+Once you did it gdb can find the file by doing transformations to the
+"canonical" filename. This search works OK for already loaded symtabs
+(symbol tables), but it have a bug when the search is done for psymtabs
+(partial symtabs). The bug is in the use of source_full_path_of (source.c).
+This function calls openp indicating try_cwd_first. It makes the search file
+if the psymtab file name have at least one dirseparator. It means that
+psymtabs for files compiled with relative paths will fail. The search for
+symtabs uses symtab_to_filename, it calls open_source_file which finally
+calls openp without try_cwd_first.<br>
+To workaround this bug we must ensure gdb loads *all* the symtabs to memory.
+And here comes another problem -file-exec-and-symbols doesn't support it
+according to docs. In real life that's a wrapper for "file", but as nobody
+can say it won't change we must use the CLI command.
+
+<Menu>
+<li><a href="#gmi_exec_continue">gmi_exec_continue</a>
+<li><a href="#gmi_exec_finish">gmi_exec_finish</a>
+<li><a href="#gmi_exec_interrupt">gmi_exec_interrupt</a>
+<li><a href="#gmi_exec_kill">gmi_exec_kill</a>
+<li><a href="#gmi_exec_next">gmi_exec_next</a>
+<li><a href="#gmi_exec_next_cnt">gmi_exec_next_cnt</a>
+<li><a href="#gmi_exec_next_instruction">gmi_exec_next_instruction</a>
+<li><a href="#gmi_exec_return">gmi_exec_return</a>
+<li><a href="#gmi_exec_run">gmi_exec_run</a>
+<li><a href="#gmi_exec_step">gmi_exec_step</a>
+<li><a href="#gmi_exec_step_cnt">gmi_exec_step_cnt</a>
+<li><a href="#gmi_exec_step_instruction">gmi_exec_step_instruction</a>
+<li><a href="#gmi_exec_until">gmi_exec_until</a>
+<li><a href="#gmi_exec_until_addr">gmi_exec_until_addr</a>
+<li><a href="#gmi_file_symbol_file">gmi_file_symbol_file</a>
+<li><a href="#gmi_set_exec">gmi_set_exec</a>
+<li><a href="#gmi_target_terminal">gmi_target_terminal</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="pseudo terminal"></a>
+<H1>pseudo terminal</H1>
+
+Helper to find a free pseudo terminal. Use this if you need to manage
+  input *and* output to the target process. If you just need output then
+  define a handler for target output stream records (assuming that this
+  is working for your particular version of gdb).
+  Usage:
+
+        mi_pty *pty = gmi_look_for_free_pty();
+        if (pty) gmi_target_terminal(mih, pty-&gt;slave);
+        ...
+        * reading from pty-&gt;master will get stdout from target *
+        * writing to pty-&gt;master will send to target stdin *
+        
+  Note: Contributed by Greg Watson (gwatson lanl gov)
+
+<Menu>
+<li><a href="#gmi_end_pty">gmi_end_pty</a>
+<li><a href="#gmi_look_for_free_pty">gmi_look_for_free_pty</a>
+<li><a href="#mi_look_for_free_pty">mi_look_for_free_pty</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Stack manipulation."></a>
+<H1>Stack manipulation.</H1>
+
+GDB/MI commands for the "Stack Manipulation" section.
+<p>
+
+
+<pre>
+gdb command:              Implemented?
+
+-stack-info-frame         Yes, implemented as "frame"
+-stack-info-depth         Yes
+-stack-list-arguments     Yes
+-stack-list-frames        Yes
+-stack-list-locals        Yes
+-stack-select-frame       Yes
+</pre>
+
+<Menu>
+<li><a href="#gmi_stack_info_depth">gmi_stack_info_depth</a>
+<li><a href="#gmi_stack_info_depth_get">gmi_stack_info_depth_get</a>
+<li><a href="#gmi_stack_info_frame">gmi_stack_info_frame</a>
+<li><a href="#gmi_stack_list_arguments">gmi_stack_list_arguments</a>
+<li><a href="#gmi_stack_list_arguments_r">gmi_stack_list_arguments_r</a>
+<li><a href="#gmi_stack_list_frames">gmi_stack_list_frames</a>
+<li><a href="#gmi_stack_list_frames_r">gmi_stack_list_frames_r</a>
+<li><a href="#gmi_stack_list_locals">gmi_stack_list_locals</a>
+<li><a href="#gmi_stack_select_frame">gmi_stack_select_frame</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Symbol query."></a>
+<H1>Symbol query.</H1>
+
+GDB/MI commands for the "Symbol Query" section.
+<p>
+
+
+<pre>
+gdb command:              Implemented?
+-symbol-info-address      N.A. (info address, human readable)
+-symbol-info-file         N.A.
+-symbol-info-function     N.A.
+-symbol-info-line         N.A. (info line, human readable)
+-symbol-info-symbol       N.A. (info symbol, human readable)
+-symbol-list-functions    N.A. (info functions, human readable)
+-symbol-list-types        N.A. (info types, human readable)
+-symbol-list-variables    N.A. (info variables, human readable)
+-symbol-list-lines        No (gdb 6.x)
+-symbol-locate            N.A.
+-symbol-type              N.A. (ptype, human readable)
+</pre>
+
+Note:
+<p>
+
+
+Only one is implemented and not in gdb 5.x.
+<p>
+
+
+<Menu>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Target manipulation."></a>
+<H1>Target manipulation.</H1>
+
+GDB/MI commands for the "Target Manipulation" section.
+<p>
+
+
+<pre>
+-target-attach                  Yes (implemented using attach)
+-target-compare-sections        N.A. (compare-sections)
+-target-detach                  Yes
+-target-download                No
+-target-exec-status             N.A.
+-target-list-available-targets  N.A. (help target)
+-target-list-current-targets    N.A. (info file among other things)
+-target-list-parameters         N.A.
+-target-select                  Yes
+</pre>
+
+<Menu>
+<li><a href="#gmi_target_attach">gmi_target_attach</a>
+<li><a href="#gmi_target_detach">gmi_target_detach</a>
+<li><a href="#gmi_target_select">gmi_target_select</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Thread commands."></a>
+<H1>Thread commands.</H1>
+
+GDB/MI commands for the "Thread Commands" section.
+<p>
+
+
+<pre>
+gdb command:              Implemented?
+-thread-info              N.A.
+-thread-list-all-threads  Yes, implemented as "info threads"
+-thread-list-ids          Yes
+-thread-select            Yes
+</pre>
+
+<Menu>
+<li><a href="#gmi_thread_list_all_threads">gmi_thread_list_all_threads</a>
+<li><a href="#gmi_thread_list_ids">gmi_thread_list_ids</a>
+<li><a href="#gmi_thread_select">gmi_thread_select</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Variable objects."></a>
+<H1>Variable objects.</H1>
+
+GDB/MI commands for the "Variable Objects" section.
+<p>
+
+
+<pre>
+gdb command:              Imp? Description:
+-var-create               Yes  create a variable object
+-var-delete               Yes  delete the variable object and its children
+-var-set-format           Yes  set the display format of this variable
+-var-show-format          Yes  show the display format of this variable
+-var-info-num-children    Yes  tells how many children this object has
+-var-list-children        Yes* return a list of the object's children
+-var-info-type            Yes  show the type of this variable object
+-var-info-expression      Yes  print what this variable object represents
+-var-show-attributes      Yes  is this variable editable?
+-var-evaluate-expression  Yes  get the value of this variable
+-var-assign               Yes  set the value of this variable
+-var-update               Yes* update the variable and its children
+</pre>
+
+Notes:
+<p>
+
+1) I suggest letting gdb to choose the names for the variables.<br>
+2) -var-list-children supports an optional "show values" argument in MI v2.
+It isn't implemented.<br>
+
+<p>
+
+
+* MI v1 and v2 result formats supported.
+<p>
+
+
+<Menu>
+<li><a href="#gmi_full_var_create">gmi_full_var_create</a>
+<li><a href="#gmi_var_assign">gmi_var_assign</a>
+<li><a href="#gmi_var_create">gmi_var_create</a>
+<li><a href="#gmi_var_create_nm">gmi_var_create_nm</a>
+<li><a href="#gmi_var_delete">gmi_var_delete</a>
+<li><a href="#gmi_var_evaluate_expression">gmi_var_evaluate_expression</a>
+<li><a href="#gmi_var_info_expression">gmi_var_info_expression</a>
+<li><a href="#gmi_var_info_num_children">gmi_var_info_num_children</a>
+<li><a href="#gmi_var_info_type">gmi_var_info_type</a>
+<li><a href="#gmi_var_list_children">gmi_var_list_children</a>
+<li><a href="#gmi_var_set_format">gmi_var_set_format</a>
+<li><a href="#gmi_var_show_attributes">gmi_var_show_attributes</a>
+<li><a href="#gmi_var_show_format">gmi_var_show_format</a>
+<li><a href="#gmi_var_update">gmi_var_update</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Files"></a>
+<H1>Files</H1>
+
+<Menu>
+<li><a href="#breakpoint.c">breakpoint.c</a>
+<li><a href="#connect.c">connect.c</a>
+<li><a href="#cpp_int.cc">cpp_int.cc</a>
+<li><a href="#data_man.c">data_man.c</a>
+<li><a href="#error.c">error.c</a>
+<li><a href="#get_free_pty.c">get_free_pty.c</a>
+<li><a href="#get_free_vt.c">get_free_vt.c</a>
+<li><a href="#misc.c">misc.c</a>
+<li><a href="#prg_control.c">prg_control.c</a>
+<li><a href="#stack_man.c">stack_man.c</a>
+<li><a href="#target_man.c">target_man.c</a>
+<li><a href="#thread.c">thread.c</a>
+<li><a href="#var_obj.c">var_obj.c</a>
+</Menu>
+
+
+<p><hr></p>
+<a name="breakpoint.c"></a>
+<H1>breakpoint.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_delete">gmi_break_delete</a>
+<li><a href="#gmi_break_insert">gmi_break_insert</a>
+<li><a href="#gmi_break_insert_full">gmi_break_insert_full</a>
+<li><a href="#gmi_break_insert_full_fl">gmi_break_insert_full_fl</a>
+<li><a href="#gmi_break_set_condition">gmi_break_set_condition</a>
+<li><a href="#gmi_break_set_times">gmi_break_set_times</a>
+<li><a href="#gmi_break_state">gmi_break_state</a>
+<li><a href="#gmi_break_watch">gmi_break_watch</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="connect.c"></a>
+<H1>connect.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_end_aux_term">gmi_end_aux_term</a>
+<li><a href="#gmi_start_xterm">gmi_start_xterm</a>
+<li><a href="#mi_connect_local">mi_connect_local</a>
+<li><a href="#mi_disconnect">mi_disconnect</a>
+<li><a href="#mi_force_version">mi_force_version</a>
+<li><a href="#mi_get_workaround">mi_get_workaround</a>
+<li><a href="#mi_set_workaround">mi_set_workaround</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="cpp_int.cc"></a>
+<H1>cpp_int.cc</H1>
+
+
+
+<Menu>
+<li><a href="#BreakDelete (MIDebugger)">BreakDelete (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger)">Breakpoint (MIDebugger)</a>
+<li><a href="#Breakpoint (MIDebugger) <1>">Breakpoint (MIDebugger) <1></a>
+<li><a href="#BreakpointFull (MIDebugger)">BreakpointFull (MIDebugger)</a>
+<li><a href="#CallStack (MIDebugger)">CallStack (MIDebugger)</a>
+<li><a href="#Connect (MIDebugger)">Connect (MIDebugger)</a>
+<li><a href="#Continue (MIDebugger)">Continue (MIDebugger)</a>
+<li><a href="#Disconnect (MIDebugger)">Disconnect (MIDebugger)</a>
+<li><a href="#EvalExpression (MIDebugger)">EvalExpression (MIDebugger)</a>
+<li><a href="#FillTypeVal (MIDebugger)">FillTypeVal (MIDebugger)</a>
+<li><a href="#FinishFun (MIDebugger)">FinishFun (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger)">GoTo (MIDebugger)</a>
+<li><a href="#GoTo (MIDebugger) <1>">GoTo (MIDebugger) <1></a>
+<li><a href="#Kill (MIDebugger)">Kill (MIDebugger)</a>
+<li><a href="#MIDebugger (MIDebugger)">MIDebugger (MIDebugger)</a>
+<li><a href="#ModifyExpression (MIDebugger)">ModifyExpression (MIDebugger)</a>
+<li><a href="#Poll (MIDebugger)">Poll (MIDebugger)</a>
+<li><a href="#ReturnNow (MIDebugger)">ReturnNow (MIDebugger)</a>
+<li><a href="#Run (MIDebugger)">Run (MIDebugger)</a>
+<li><a href="#RunOrContinue (MIDebugger)">RunOrContinue (MIDebugger)</a>
+<li><a href="#RunToMain (MIDebugger)">RunToMain (MIDebugger)</a>
+<li><a href="#SelectTargetLinux (MIDebugger)">SelectTargetLinux (MIDebugger)</a>
+<li><a href="#SelectTargetPID (MIDebugger)">SelectTargetPID (MIDebugger)</a>
+<li><a href="#SelectTargetRemote (MIDebugger)">SelectTargetRemote (MIDebugger)</a>
+<li><a href="#SelectTargetTTY (MIDebugger)">SelectTargetTTY (MIDebugger)</a>
+<li><a href="#SelectTargetX11 (MIDebugger)">SelectTargetX11 (MIDebugger)</a>
+<li><a href="#Send (MIDebugger)">Send (MIDebugger)</a>
+<li><a href="#StepOver (MIDebugger)">StepOver (MIDebugger)</a>
+<li><a href="#Stop (MIDebugger)">Stop (MIDebugger)</a>
+<li><a href="#TargetUnselect (MIDebugger)">TargetUnselect (MIDebugger)</a>
+<li><a href="#TraceInto (MIDebugger)">TraceInto (MIDebugger)</a>
+<li><a href="#WatchDelete (MIDebugger)">WatchDelete (MIDebugger)</a>
+<li><a href="#Watchpoint (MIDebugger)">Watchpoint (MIDebugger)</a>
+<li><a href="#~MIDebugger (MIDebugger)">~MIDebugger (MIDebugger)</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="data_man.c"></a>
+<H1>data_man.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_data_evaluate_expression">gmi_data_evaluate_expression</a>
+<li><a href="#gmi_dir">gmi_dir</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="error.c"></a>
+<H1>error.c</H1>
+
+
+
+<Menu>
+<li><a href="#mi_get_error_str">mi_get_error_str</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="get_free_pty.c"></a>
+<H1>get_free_pty.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_end_pty">gmi_end_pty</a>
+<li><a href="#gmi_look_for_free_pty">gmi_look_for_free_pty</a>
+<li><a href="#mi_look_for_free_pty">mi_look_for_free_pty</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="get_free_vt.c"></a>
+<H1>get_free_vt.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_look_for_free_vt">gmi_look_for_free_vt</a>
+<li><a href="#mi_look_for_free_vt">mi_look_for_free_vt</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="misc.c"></a>
+<H1>misc.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_gdb_exit">gmi_gdb_exit</a>
+<li><a href="#gmi_gdb_set">gmi_gdb_set</a>
+<li><a href="#gmi_gdb_show">gmi_gdb_show</a>
+<li><a href="#gmi_gdb_version">gmi_gdb_version</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="prg_control.c"></a>
+<H1>prg_control.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_continue">gmi_exec_continue</a>
+<li><a href="#gmi_exec_finish">gmi_exec_finish</a>
+<li><a href="#gmi_exec_interrupt">gmi_exec_interrupt</a>
+<li><a href="#gmi_exec_kill">gmi_exec_kill</a>
+<li><a href="#gmi_exec_next">gmi_exec_next</a>
+<li><a href="#gmi_exec_next_cnt">gmi_exec_next_cnt</a>
+<li><a href="#gmi_exec_next_instruction">gmi_exec_next_instruction</a>
+<li><a href="#gmi_exec_return">gmi_exec_return</a>
+<li><a href="#gmi_exec_run">gmi_exec_run</a>
+<li><a href="#gmi_exec_step">gmi_exec_step</a>
+<li><a href="#gmi_exec_step_cnt">gmi_exec_step_cnt</a>
+<li><a href="#gmi_exec_step_instruction">gmi_exec_step_instruction</a>
+<li><a href="#gmi_exec_until">gmi_exec_until</a>
+<li><a href="#gmi_exec_until_addr">gmi_exec_until_addr</a>
+<li><a href="#gmi_file_symbol_file">gmi_file_symbol_file</a>
+<li><a href="#gmi_set_exec">gmi_set_exec</a>
+<li><a href="#gmi_target_terminal">gmi_target_terminal</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="stack_man.c"></a>
+<H1>stack_man.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_info_depth">gmi_stack_info_depth</a>
+<li><a href="#gmi_stack_info_depth_get">gmi_stack_info_depth_get</a>
+<li><a href="#gmi_stack_info_frame">gmi_stack_info_frame</a>
+<li><a href="#gmi_stack_list_arguments">gmi_stack_list_arguments</a>
+<li><a href="#gmi_stack_list_arguments_r">gmi_stack_list_arguments_r</a>
+<li><a href="#gmi_stack_list_frames">gmi_stack_list_frames</a>
+<li><a href="#gmi_stack_list_frames_r">gmi_stack_list_frames_r</a>
+<li><a href="#gmi_stack_list_locals">gmi_stack_list_locals</a>
+<li><a href="#gmi_stack_select_frame">gmi_stack_select_frame</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="target_man.c"></a>
+<H1>target_man.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_target_attach">gmi_target_attach</a>
+<li><a href="#gmi_target_detach">gmi_target_detach</a>
+<li><a href="#gmi_target_select">gmi_target_select</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="thread.c"></a>
+<H1>thread.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_thread_list_all_threads">gmi_thread_list_all_threads</a>
+<li><a href="#gmi_thread_list_ids">gmi_thread_list_ids</a>
+<li><a href="#gmi_thread_select">gmi_thread_select</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="var_obj.c"></a>
+<H1>var_obj.c</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_full_var_create">gmi_full_var_create</a>
+<li><a href="#gmi_var_assign">gmi_var_assign</a>
+<li><a href="#gmi_var_create">gmi_var_create</a>
+<li><a href="#gmi_var_create_nm">gmi_var_create_nm</a>
+<li><a href="#gmi_var_delete">gmi_var_delete</a>
+<li><a href="#gmi_var_evaluate_expression">gmi_var_evaluate_expression</a>
+<li><a href="#gmi_var_info_expression">gmi_var_info_expression</a>
+<li><a href="#gmi_var_info_num_children">gmi_var_info_num_children</a>
+<li><a href="#gmi_var_info_type">gmi_var_info_type</a>
+<li><a href="#gmi_var_list_children">gmi_var_list_children</a>
+<li><a href="#gmi_var_set_format">gmi_var_set_format</a>
+<li><a href="#gmi_var_show_attributes">gmi_var_show_attributes</a>
+<li><a href="#gmi_var_show_format">gmi_var_show_format</a>
+<li><a href="#gmi_var_update">gmi_var_update</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="Command"></a>
+<H1>Command</H1>
+
+<Menu>
+<li><a href="#-break-after">-break-after</a>
+<li><a href="#-break-condition">-break-condition</a>
+<li><a href="#-break-delete">-break-delete</a>
+<li><a href="#-break-enable + -break-disable">-break-enable + -break-disable</a>
+<li><a href="#-break-insert">-break-insert</a>
+<li><a href="#-break-insert [ops] file:line">-break-insert [ops] file:line</a>
+<li><a href="#-break-insert file:line">-break-insert file:line</a>
+<li><a href="#-break-watch">-break-watch</a>
+<li><a href="#-data-evaluate-expression">-data-evaluate-expression</a>
+<li><a href="#-environment-directory">-environment-directory</a>
+<li><a href="#-exec-abort [using kill]">-exec-abort [using kill]</a>
+<li><a href="#-exec-continue">-exec-continue</a>
+<li><a href="#-exec-finish">-exec-finish</a>
+<li><a href="#-exec-interrupt [replacement]">-exec-interrupt [replacement]</a>
+<li><a href="#-exec-next">-exec-next</a>
+<li><a href="#-exec-next count">-exec-next count</a>
+<li><a href="#-exec-next-instruction">-exec-next-instruction</a>
+<li><a href="#-exec-return">-exec-return</a>
+<li><a href="#-exec-run">-exec-run</a>
+<li><a href="#-exec-step">-exec-step</a>
+<li><a href="#-exec-step count">-exec-step count</a>
+<li><a href="#-exec-step-instruction">-exec-step-instruction</a>
+<li><a href="#-exec-until">-exec-until</a>
+<li><a href="#-exec-until (using *address)">-exec-until (using *address)</a>
+<li><a href="#-file-exec-and-symbols + -exec-arguments">-file-exec-and-symbols + -exec-arguments</a>
+<li><a href="#-file-symbol-file">-file-symbol-file</a>
+<li><a href="#-gdb-exit">-gdb-exit</a>
+<li><a href="#-gdb-set">-gdb-set</a>
+<li><a href="#-gdb-show">-gdb-show</a>
+<li><a href="#-gdb-version">-gdb-version</a>
+<li><a href="#-stack-info-depth">-stack-info-depth</a>
+<li><a href="#-stack-info-depth [no args]">-stack-info-depth [no args]</a>
+<li><a href="#-stack-info-frame [using frame]">-stack-info-frame [using frame]</a>
+<li><a href="#-stack-list-arguments">-stack-list-arguments</a>
+<li><a href="#-stack-list-frames">-stack-list-frames</a>
+<li><a href="#-stack-list-locals">-stack-list-locals</a>
+<li><a href="#-stack-select-frame">-stack-select-frame</a>
+<li><a href="#-target-attach [using attach]">-target-attach [using attach]</a>
+<li><a href="#-target-detach">-target-detach</a>
+<li><a href="#-target-select">-target-select</a>
+<li><a href="#-thread-list-all-threads">-thread-list-all-threads</a>
+<li><a href="#-thread-list-ids">-thread-list-ids</a>
+<li><a href="#-thread-select">-thread-select</a>
+<li><a href="#-var-assign">-var-assign</a>
+<li><a href="#-var-create">-var-create</a>
+<li><a href="#-var-create + -var-info-expression + -var-show-attributes">-var-create + -var-info-expression + -var-show-attributes</a>
+<li><a href="#-var-create [auto name]">-var-create [auto name]</a>
+<li><a href="#-var-delete">-var-delete</a>
+<li><a href="#-var-evaluate-expression">-var-evaluate-expression</a>
+<li><a href="#-var-info-expression">-var-info-expression</a>
+<li><a href="#-var-info-num-children">-var-info-num-children</a>
+<li><a href="#-var-info-type">-var-info-type</a>
+<li><a href="#-var-list-children">-var-list-children</a>
+<li><a href="#-var-set-format">-var-set-format</a>
+<li><a href="#-var-show-attributes">-var-show-attributes</a>
+<li><a href="#-var-show-format">-var-show-format</a>
+<li><a href="#-var-update">-var-update</a>
+<li><a href="#tty">tty</a>
+</Menu>
+
+
+<p><hr></p>
+<a name="-break-after"></a>
+<H1>-break-after</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_set_times">gmi_break_set_times</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-condition"></a>
+<H1>-break-condition</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_set_condition">gmi_break_set_condition</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-delete"></a>
+<H1>-break-delete</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_delete">gmi_break_delete</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-enable + -break-disable"></a>
+<H1>-break-enable + -break-disable</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_state">gmi_break_state</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-insert"></a>
+<H1>-break-insert</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_insert_full">gmi_break_insert_full</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-insert [ops] file:line"></a>
+<H1>-break-insert [ops] file:line</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_insert_full_fl">gmi_break_insert_full_fl</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-insert file:line"></a>
+<H1>-break-insert file:line</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_insert">gmi_break_insert</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-break-watch"></a>
+<H1>-break-watch</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_break_watch">gmi_break_watch</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-data-evaluate-expression"></a>
+<H1>-data-evaluate-expression</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_data_evaluate_expression">gmi_data_evaluate_expression</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-environment-directory"></a>
+<H1>-environment-directory</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_dir">gmi_dir</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-abort [using kill]"></a>
+<H1>-exec-abort [using kill]</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_kill">gmi_exec_kill</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-continue"></a>
+<H1>-exec-continue</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_continue">gmi_exec_continue</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-finish"></a>
+<H1>-exec-finish</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_finish">gmi_exec_finish</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-interrupt [replacement]"></a>
+<H1>-exec-interrupt [replacement]</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_interrupt">gmi_exec_interrupt</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-next"></a>
+<H1>-exec-next</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_next">gmi_exec_next</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-next count"></a>
+<H1>-exec-next count</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_next_cnt">gmi_exec_next_cnt</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-next-instruction"></a>
+<H1>-exec-next-instruction</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_next_instruction">gmi_exec_next_instruction</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-return"></a>
+<H1>-exec-return</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_return">gmi_exec_return</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-run"></a>
+<H1>-exec-run</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_run">gmi_exec_run</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-step"></a>
+<H1>-exec-step</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_step">gmi_exec_step</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-step count"></a>
+<H1>-exec-step count</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_step_cnt">gmi_exec_step_cnt</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-step-instruction"></a>
+<H1>-exec-step-instruction</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_step_instruction">gmi_exec_step_instruction</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-until"></a>
+<H1>-exec-until</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_until">gmi_exec_until</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-exec-until (using *address)"></a>
+<H1>-exec-until (using *address)</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_exec_until_addr">gmi_exec_until_addr</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-file-exec-and-symbols + -exec-arguments"></a>
+<H1>-file-exec-and-symbols + -exec-arguments</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_set_exec">gmi_set_exec</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-file-symbol-file"></a>
+<H1>-file-symbol-file</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_file_symbol_file">gmi_file_symbol_file</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-gdb-exit"></a>
+<H1>-gdb-exit</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_gdb_exit">gmi_gdb_exit</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-gdb-set"></a>
+<H1>-gdb-set</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_gdb_set">gmi_gdb_set</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-gdb-show"></a>
+<H1>-gdb-show</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_gdb_show">gmi_gdb_show</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-gdb-version"></a>
+<H1>-gdb-version</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_gdb_version">gmi_gdb_version</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-info-depth"></a>
+<H1>-stack-info-depth</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_info_depth">gmi_stack_info_depth</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-info-depth [no args]"></a>
+<H1>-stack-info-depth [no args]</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_info_depth_get">gmi_stack_info_depth_get</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-info-frame [using frame]"></a>
+<H1>-stack-info-frame [using frame]</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_info_frame">gmi_stack_info_frame</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-list-arguments"></a>
+<H1>-stack-list-arguments</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_list_arguments">gmi_stack_list_arguments</a>
+<li><a href="#gmi_stack_list_arguments_r">gmi_stack_list_arguments_r</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-list-frames"></a>
+<H1>-stack-list-frames</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_list_frames">gmi_stack_list_frames</a>
+<li><a href="#gmi_stack_list_frames_r">gmi_stack_list_frames_r</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-list-locals"></a>
+<H1>-stack-list-locals</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_list_locals">gmi_stack_list_locals</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-stack-select-frame"></a>
+<H1>-stack-select-frame</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_stack_select_frame">gmi_stack_select_frame</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-target-attach [using attach]"></a>
+<H1>-target-attach [using attach]</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_target_attach">gmi_target_attach</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-target-detach"></a>
+<H1>-target-detach</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_target_detach">gmi_target_detach</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-target-select"></a>
+<H1>-target-select</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_target_select">gmi_target_select</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-thread-list-all-threads"></a>
+<H1>-thread-list-all-threads</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_thread_list_all_threads">gmi_thread_list_all_threads</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-thread-list-ids"></a>
+<H1>-thread-list-ids</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_thread_list_ids">gmi_thread_list_ids</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-thread-select"></a>
+<H1>-thread-select</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_thread_select">gmi_thread_select</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-assign"></a>
+<H1>-var-assign</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_assign">gmi_var_assign</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-create"></a>
+<H1>-var-create</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_create_nm">gmi_var_create_nm</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-create + -var-info-expression + -var-show-attributes"></a>
+<H1>-var-create + -var-info-expression + -var-show-attributes</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_full_var_create">gmi_full_var_create</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-create [auto name]"></a>
+<H1>-var-create [auto name]</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_create">gmi_var_create</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-delete"></a>
+<H1>-var-delete</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_delete">gmi_var_delete</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-evaluate-expression"></a>
+<H1>-var-evaluate-expression</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_evaluate_expression">gmi_var_evaluate_expression</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-info-expression"></a>
+<H1>-var-info-expression</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_info_expression">gmi_var_info_expression</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-info-num-children"></a>
+<H1>-var-info-num-children</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_info_num_children">gmi_var_info_num_children</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-info-type"></a>
+<H1>-var-info-type</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_info_type">gmi_var_info_type</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-list-children"></a>
+<H1>-var-list-children</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_list_children">gmi_var_list_children</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-set-format"></a>
+<H1>-var-set-format</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_set_format">gmi_var_set_format</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-show-attributes"></a>
+<H1>-var-show-attributes</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_show_attributes">gmi_var_show_attributes</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-show-format"></a>
+<H1>-var-show-format</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_show_format">gmi_var_show_format</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="-var-update"></a>
+<H1>-var-update</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_var_update">gmi_var_update</a>
+</Menu>
+
+
+
+<p><hr></p>
+<a name="tty"></a>
+<H1>tty</H1>
+
+
+
+<Menu>
+<li><a href="#gmi_target_terminal">gmi_target_terminal</a>
+</Menu>
+
+
+
+
+
+<p><hr></p>
+<a name="gmi_break_insert"></a>
+<center><Font Size=+2>gmi_break_insert</Font> (breakpoint.c 133)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_insert(mi_h *h, const char *file, int line);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Insert a breakpoint at file:line.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_bkpt structure with info about the breakpoint. NULL on
+error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_insert_full"></a>
+<center><Font Size=+2>gmi_break_insert_full</Font> (breakpoint.c 150)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_insert_full(mi_h *h, int temporary, int hard_assist, const char *cond, int count, int thread, const char *where);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Insert a breakpoint, all available options.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_bkpt structure with info about the breakpoint. NULL on
+error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_insert_full_fl"></a>
+<center><Font Size=+2>gmi_break_insert_full_fl</Font> (breakpoint.c 169)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_insert_full_fl(mi_h *h, const char *file, int line, int temporary, int hard_assist, const char *cond, int count, int thread);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Insert a breakpoint, all available options.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_bkpt structure with info about the breakpoint. NULL on
+error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_delete"></a>
+<center><Font Size=+2>gmi_break_delete</Font> (breakpoint.c 188)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_delete(mi_h *h, int number);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Remove a breakpoint.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK. Note that gdb always says OK, but errors can be sent to the
+console.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_set_times"></a>
+<center><Font Size=+2>gmi_break_set_times</Font> (breakpoint.c 205)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_set_times(mi_h *h, int number, int count);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Modify the "ignore" count for a breakpoint.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK. Note that gdb always says OK, but errors can be sent to the
+console.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_set_condition"></a>
+<center><Font Size=+2>gmi_break_set_condition</Font> (breakpoint.c 221)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_set_condition(mi_h *h, int number, const char *condition);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Associate a condition with the breakpoint.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_state"></a>
+<center><Font Size=+2>gmi_break_state</Font> (breakpoint.c 238)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_state(mi_h *h, int number, int enable);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Enable or disable a breakpoint.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK. Note that gdb always says OK, but errors can be sent to the
+console.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_break_watch"></a>
+<center><Font Size=+2>gmi_break_watch</Font> (breakpoint.c 258)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Set a watchpoint. It doesn't work for remote targets!
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_wp structure with info about the watchpoint. NULL on
+error.
+<p>
+
+
+
+<p><hr></p>
+<a name="mi_connect_local"></a>
+<center><Font Size=+2>mi_connect_local</Font> (connect.c 330)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_connect_local();
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Connect to a local copy of gdb. Note that the mi_h structure is something
+similar to a "FILE *" for stdio.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_h structure or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="mi_disconnect"></a>
+<center><Font Size=+2>mi_disconnect</Font> (connect.c 410)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_disconnect(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Close connection. You should ask gdb to quit first <a href="#gmi_gdb_exit">gmi_gdb_exit</a>.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="gmi_start_xterm"></a>
+<center><Font Size=+2>gmi_start_xterm</Font> (connect.c 647)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_start_xterm();
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Opens a new xterm to be used by the child process to debug.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_aux_term structure, you can use <a href="#gmi_end_aux_term">gmi_end_aux_term</a> to
+release it.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_end_aux_term"></a>
+<center><Font Size=+2>gmi_end_aux_term</Font> (connect.c 764)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_end_aux_term(mi_aux_term *t);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Closes the auxiliar terminal and releases the allocated memory.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="mi_force_version"></a>
+<center><Font Size=+2>mi_force_version</Font> (connect.c 781)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle, unsigned vMinor);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Forces the MI version. Currently the library can't detect it so you must
+force it manually. GDB 5.x implemented MI v1 and 6.x v2.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="mi_set_workaround"></a>
+<center><Font Size=+2>mi_set_workaround</Font> (connect.c 794)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_set_workaround(unsigned wa, int enable);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Dis/Enables the @var{wa} workaround for a bug in gdb.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="mi_get_workaround"></a>
+<center><Font Size=+2>mi_get_workaround</Font> (connect.c 813)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_get_workaround(unsigned wa);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Finds if the @var{wa} workaround for a bug in gdb is enabled.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 if enabled.
+<p>
+
+
+
+<p><hr></p>
+<a name="MIDebugger (MIDebugger)"></a>
+<center><Font Size=+2>MIDebugger</Font> (cpp_int.cc 22)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::MIDebugger();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Initializes a debugger object. It starts in the "disconnected" state.
+Use <a href="#Connect (MIDebugger)">Connect</a> after it.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="~MIDebugger (MIDebugger)"></a>
+<center><Font Size=+2>~MIDebugger</Font> (cpp_int.cc 40)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::~MIDebugger();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+This is the destructor for the class. It tries to change the state to
+"disconnected" doing the needed actions.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="Connect (MIDebugger)"></a>
+<center><Font Size=+2>Connect</Font> (cpp_int.cc 79)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Connect(bool);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Connects to gdb. Currently only local connections are supported, that's
+a gdb limitation. Call it when in "unconnected" state, on success it will
+change to the "connected" state.  After it you should call one of the
+SelectTarget members. <a href="#SelectTargetX11 (MIDebugger)">SelectTargetX11</a>, <a href="#SelectTargetLinux (MIDebugger)">SelectTargetLinux</a> or
+<a href="#SelectTargetRemote (MIDebugger)">SelectTargetRemote</a>. To finish the connection use <a href="#Disconnect (MIDebugger)">Disconnect</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="Disconnect (MIDebugger)"></a>
+<center><Font Size=+2>Disconnect</Font> (cpp_int.cc 105)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Disconnect();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Finishes the connection to gdb. Call when in "connected" state, on success
+it will change to "disconnected" state. This function first tries to exit
+from gdb and then close the connection. But if gdb fails to exit it will be
+killed.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="SelectTargetTTY (MIDebugger)"></a>
+<center><Font Size=+2>SelectTargetTTY</Font> (cpp_int.cc 127)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::SelectTargetTTY(const char *exec, const char *args, const char *auxtty, dMode m);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Protected member that implements <a href="#SelectTargetX11 (MIDebugger)">SelectTargetX11</a> and
+<a href="#SelectTargetLinux (MIDebugger)">SelectTargetLinux</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="SelectTargetX11 (MIDebugger)"></a>
+<center><Font Size=+2>SelectTargetX11</Font> (cpp_int.cc 180)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::SelectTargetX11(const char *exec, const char *args, const char *auxtty);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Starts a debug session for X11. It opens an xterm console for the program
+to debug and tells gdb which executable to debug and the command line
+options to pass. You can specify an already existing tty console to be used.
+Can be called when the state is "connected". On success will change to the
+"target_specified" state. After it you can use <a href="#Run (MIDebugger)">Run</a> or use the members
+to define breakpoints and similar stuff. To finish it use
+<a href="#TargetUnselect (MIDebugger)">TargetUnselect</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="SelectTargetLinux (MIDebugger)"></a>
+<center><Font Size=+2>SelectTargetLinux</Font> (cpp_int.cc 202)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::SelectTargetLinux(const char *exec, const char *args, const char *auxtty);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Starts a debug session for Linux console. It selects an empty VT for the
+program to debug and tells gdb which executable to debug and the command line
+options to pass. You can specify an already existing tty console to be used.
+Can be called when the state is "connected". On success will change to the
+"target_specified" state. After it you can use <a href="#Run (MIDebugger)">Run</a> or use the members
+to define breakpoints and similar stuff. To finish it use
+<a href="#TargetUnselect (MIDebugger)">TargetUnselect</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="SelectTargetRemote (MIDebugger)"></a>
+<center><Font Size=+2>SelectTargetRemote</Font> (cpp_int.cc 228)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::SelectTargetRemote(const char *exec, const char *rparams, const char *rtype);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Starts a remote session. The other end should be running gdbserver. You
+must specify a local copy of the program to debug with debug info. The remote
+copy can be stripped. The @var{rtype} and @var{rparams} selects the protocol
+and the remote machine. Read gdb docs to know more about the available
+options. If @var{rtype} is omitted "extended-remote" protocol is used.
+Can be called when the state is "connected". On success will change to the
+"target_specified" state. After it you can use <a href="#Run (MIDebugger)">Run</a> or use the members
+to define breakpoints and similar stuff. To finish it use
+<a href="#TargetUnselect (MIDebugger)">TargetUnselect</a>. Note that when gdb uses remote debugging the remote
+program starts running. The <a href="#Run (MIDebugger)">Run</a> member knows about it.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+<Font Size=+1><u>Example</u></Font><p>
+
+o-&gt;SelectTargetRemote("./exec_file","192.168.1.65:5000");
+<p>
+
+
+<p><hr></p>
+<a name="SelectTargetPID (MIDebugger)"></a>
+<center><Font Size=+2>SelectTargetPID</Font> (cpp_int.cc 258)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::SelectTargetPID(const char *exec, int pid);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Starts a local session using an already running process.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="TargetUnselect (MIDebugger)"></a>
+<center><Font Size=+2>TargetUnselect</Font> (cpp_int.cc 295)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::TargetUnselect();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Used to unselect the current target. When X11 mode it closes the auxiliar
+terminal. For remote debugging it uses "detach". Can be called when in
+"target_specified" state. On success it changes to "connected" state.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="Run (MIDebugger)"></a>
+<center><Font Size=+2>Run</Font> (cpp_int.cc 335)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Run();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Starts running the program. You should set breakpoint before it. Can be
+called when state is "target_specified". On success will change to "running"
+state. After it you should poll for async responses using <a href="#Poll (MIDebugger)">Poll</a>. The
+program can stop for many reasons asynchronously and also exit. This
+information is known using Poll. You can stop the program using <a href="#Stop (MIDebugger)">Stop</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="Stop (MIDebugger)"></a>
+<center><Font Size=+2>Stop</Font> (cpp_int.cc 365)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Stop();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Stops the program execution. GDB sends an interrupt signal to the program.
+Can be called when the state is "running". It won't switch to "stopped"
+state automatically. Instead you must poll for async events and wait for a
+stopped notification. After it you can call <a href="#Continue (MIDebugger)">Continue</a> to resume
+execution.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+
+<p>
+
+
+<Font Size=+1><u>Example</u></Font><p>
+
+!=0 OK
+<p>
+
+
+<p><hr></p>
+<a name="Poll (MIDebugger)"></a>
+<center><Font Size=+2>Poll</Font> (cpp_int.cc 386)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Poll(mi_stop *&rs);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Polls gdb looking for async responses. Currently it just looks for
+"stopped" messages. You must call it when the state is "running". But the
+function will poll gdb even if the state isn't "running". When a stopped
+message is received the state changes to stopped or target_specified (the
+last is when we get some exit).
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 if we got a response. The @var{rs} pointer will point to an
+mi_stop structure if we got it or will be NULL if we didn't.
+<p>
+
+
+
+<p><hr></p>
+<a name="Continue (MIDebugger)"></a>
+<center><Font Size=+2>Continue</Font> (cpp_int.cc 432)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Continue();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Resumes execution after the program "stopped". Can be called when the state
+is stopped. On success will change to "running" state.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="RunOrContinue (MIDebugger)"></a>
+<center><Font Size=+2>RunOrContinue</Font> (cpp_int.cc 454)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::RunOrContinue();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Starts program execution or resumes it. When the state is target_specified
+it calls <a href="#Run (MIDebugger)">Run</a> otherwise it uses <a href="#Continue (MIDebugger)">Continue</a>. Can be called when the
+state is "target_specified" or "stopped". On success will change to
+"running" state.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="Kill (MIDebugger)"></a>
+<center><Font Size=+2>Kill</Font> (cpp_int.cc 473)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Kill();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Kills the program you are debugging. Can be called when the state is
+"stopped" or "running". On success changes the state to "target_specified".
+Note that if you want to restart the program you can just call <a href="#Run (MIDebugger)">Run</a> and
+if you want to just stop the program call <a href="#Stop (MIDebugger)">Stop</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="Breakpoint (MIDebugger)"></a>
+<center><Font Size=+2>Breakpoint</Font> (cpp_int.cc 520)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Breakpoint(const char *file, int line);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Inserts a breakpoint at @var{file} and @var{line}. Can be called when the
+state is "stopped" or "target_specified".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+An mi_bkpt structure or NULL if error.
+<p>
+
+
+
+<p><hr></p>
+<a name="Breakpoint (MIDebugger) <1>"></a>
+<center><Font Size=+2>Breakpoint</Font> (cpp_int.cc 537)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Breakpoint(const char *where, bool temporary, const char *cond, int count, int thread, bool hard_assist);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Inserts a breakpoint at @var{where}, all options available. Can be called
+when the state is "stopped" or "target_specified".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+An mi_bkpt structure or NULL if error.
+<p>
+
+
+
+<p><hr></p>
+<a name="BreakpointFull (MIDebugger)"></a>
+<center><Font Size=+2>BreakpointFull</Font> (cpp_int.cc 585)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::BreakpointFull(const char *file, int line, bool temporary, const char *cond, int count, int thread, bool hard_assist);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Inserts a breakpoint at @var{file} and @var{line} all options available.
+Can be called when the state is "stopped" or "target_specified".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+An mi_bkpt structure or NULL if error.
+<p>
+
+
+
+<p><hr></p>
+<a name="BreakDelete (MIDebugger)"></a>
+<center><Font Size=+2>BreakDelete</Font> (cpp_int.cc 605)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::BreakDelete(mi_bkpt *b);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Removes the specified breakpoint. It doesn't free the structure. Can be
+called when the state is "stopped" or "target_specified".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="Watchpoint (MIDebugger)"></a>
+<center><Font Size=+2>Watchpoint</Font> (cpp_int.cc 622)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Watchpoint(enum mi_wp_mode mode, const char *exp);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Inserts a watchpoint for the specified expression. Can be called when the
+state is "stopped" or "target_specified".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+An mi_wp structure or NULL if error.
+<p>
+
+
+
+<p><hr></p>
+<a name="WatchDelete (MIDebugger)"></a>
+<center><Font Size=+2>WatchDelete</Font> (cpp_int.cc 639)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::WatchDelete(mi_wp *w);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Removes the specified watchpoint. It doesn't free the structure. Can be
+called when the state is "stopped" or "target_specified".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="RunToMain (MIDebugger)"></a>
+<center><Font Size=+2>RunToMain</Font> (cpp_int.cc 657)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::RunToMain();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Puts a temporal breakpoint in main function and starts running. Can be
+called when the state is "target_specified". If successful the state will
+change to "running".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="StepOver (MIDebugger)"></a>
+<center><Font Size=+2>StepOver</Font> (cpp_int.cc 681)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::StepOver(bool inst);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Executes upto the next line, doesn't follow function calls. The @var{inst}
+argument is for assembler. If the state is "target_specified" it will go to
+the first line in the main function. If the state is "stopped" will use the
+next command. If successfully the state will change to "running".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="GoTo (MIDebugger)"></a>
+<center><Font Size=+2>GoTo</Font> (cpp_int.cc 713)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::GoTo(const char *file, int line);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Executes until the specified point. If the state is "target_specified" it
+uses a temporal breakpoint. If the state is "stopped" it uses -exec-until.
+Fails for any other state.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="GoTo (MIDebugger) <1>"></a>
+<center><Font Size=+2>GoTo</Font> (cpp_int.cc 751)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::GoTo(void *addr);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Executes until the specified point. If the state is "target_specified" it
+uses a temporal breakpoint. If the state is "stopped" it uses -exec-until.
+Fails for any other state.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="FinishFun (MIDebugger)"></a>
+<center><Font Size=+2>FinishFun</Font> (cpp_int.cc 788)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::FinishFun();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Resumes execution until the end of the current funtion is reached. Only
+usable when we are in the "stopped" state.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="ReturnNow (MIDebugger)"></a>
+<center><Font Size=+2>ReturnNow</Font> (cpp_int.cc 808)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::ReturnNow();
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=NULL OK, the returned frame is the current location. That's a
+synchronous function.
+<p>
+
+
+
+<p><hr></p>
+<a name="CallStack (MIDebugger)"></a>
+<center><Font Size=+2>CallStack</Font> (cpp_int.cc 824)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::CallStack(bool args);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=NULL OK, the list of frames is returned.
+<p>
+
+
+
+<p><hr></p>
+<a name="TraceInto (MIDebugger)"></a>
+<center><Font Size=+2>TraceInto</Font> (cpp_int.cc 860)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::TraceInto(bool inst);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Executes upto the next line, it follows function calls. The @var{inst}
+argument is for assembler. If the state is "target_specified" it will go to
+the first line in the main function. If the state is "stopped" will use the
+next command. If successfully the state will change to "running".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="EvalExpression (MIDebugger)"></a>
+<center><Font Size=+2>EvalExpression</Font> (cpp_int.cc 892)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::EvalExpression(const char *exp);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Evaluates the provided expression. If we get an error the error
+description is returned instead. Can't be called if "disconnected" or
+"running".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The result of the expression (use free) or NULL.
+<p>
+
+
+
+<p><hr></p>
+<a name="ModifyExpression (MIDebugger)"></a>
+<center><Font Size=+2>ModifyExpression</Font> (cpp_int.cc 918)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::ModifyExpression(char *exp, char *newVal);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Modifies the provided expression. If we get an error the error
+description is returned instead. Can't be called if "disconnected" or
+"running".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The result of the expression (use free) or NULL.
+<p>
+
+
+
+<p><hr></p>
+<a name="Send (MIDebugger)"></a>
+<center><Font Size=+2>Send</Font> (cpp_int.cc 950)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::Send(const char *command);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Sends a command to gdb.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="FillTypeVal (MIDebugger)"></a>
+<center><Font Size=+2>FillTypeVal</Font> (cpp_int.cc 970)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ MIDebugger::FillTypeVal(mi_gvar *var);
+</pre>
+
+
+<Font Size=+1><u>Member of the class:</u></Font>
+MIDebugger
+<p>
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fills the type and value fields of the mi_gvar provided list.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_data_evaluate_expression"></a>
+<center><Font Size=+2>gmi_data_evaluate_expression</Font> (data_man.c 163)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_data_evaluate_expression(mi_h *h, const char *expression);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Evaluate an expression. Returns a parsed tree.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The resulting value (as plain text) or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_dir"></a>
+<center><Font Size=+2>gmi_dir</Font> (data_man.c 180)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_dir(mi_h *h, const char *path);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Path for sources. You must use it to indicate where are the sources for
+the program to debug. Only the MI v1 implementation is available.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="mi_get_error_str"></a>
+<center><Font Size=+2>mi_get_error_str</Font> (error.c 10)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_get_error_str();
+</pre>
+
+
+
+
+
+
+
+<p><hr></p>
+<a name="mi_look_for_free_pty"></a>
+<center><Font Size=+2>mi_look_for_free_pty</Font> (get_free_pty.c 41)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_look_for_free_pty(int *master, char **slave);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Look for a free and usable pseudo terminal. Low level, use
+<a href="#gmi_look_for_free_pty">gmi_look_for_free_pty</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A file descriptor connected to the master pty and the name of the slave device, or &lt;0 on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_look_for_free_pty"></a>
+<center><Font Size=+2>gmi_look_for_free_pty</Font> (get_free_pty.c 92)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_look_for_free_pty();
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Look for a free and usable pseudo terminal to be used by the child.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_pty structure, you can use <a href="#gmi_end_pty">gmi_end_pty</a> to
+release it.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_end_pty"></a>
+<center><Font Size=+2>gmi_end_pty</Font> (get_free_pty.c 124)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_end_pty(mi_pty *p);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Closes the pseudo termial master and releases the allocated memory.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="mi_look_for_free_vt"></a>
+<center><Font Size=+2>mi_look_for_free_vt</Font> (get_free_vt.c 51)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ mi_look_for_free_vt() 53;
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Look for a free and usable Linux VT. Low level, use
+<a href="#gmi_look_for_free_vt">gmi_look_for_free_vt</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The VT number or &lt;0 on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_look_for_free_vt"></a>
+<center><Font Size=+2>gmi_look_for_free_vt</Font> (get_free_vt.c 135)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_look_for_free_vt() 137;
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Look for a free and usable Linux VT to be used by the child.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_aux_term structure, you can use <a href="#gmi_end_aux_term">gmi_end_aux_term</a> to
+release it.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_gdb_exit"></a>
+<center><Font Size=+2>gmi_gdb_exit</Font> (misc.c 54)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_gdb_exit(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Exit gdb killing the child is it is running.
+<p>
+
+
+
+
+<p><hr></p>
+<a name="gmi_gdb_version"></a>
+<center><Font Size=+2>gmi_gdb_version</Font> (misc.c 70)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_gdb_version(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Send the version to the console.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_gdb_set"></a>
+<center><Font Size=+2>gmi_gdb_set</Font> (misc.c 86)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_gdb_set(mi_h *h, const char *var, const char *val);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Set a gdb variable.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_gdb_show"></a>
+<center><Font Size=+2>gmi_gdb_show</Font> (misc.c 102)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_gdb_show(mi_h *h, const char *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Get a gdb variable.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The current value of the variable or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_set_exec"></a>
+<center><Font Size=+2>gmi_set_exec</Font> (prg_control.c 172)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_set_exec(mi_h *h, const char *file, const char *args);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Specify the executable and arguments for local debug.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_run"></a>
+<center><Font Size=+2>gmi_exec_run</Font> (prg_control.c 193)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_run(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Start running the executable. Remote sessions starts running.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_continue"></a>
+<center><Font Size=+2>gmi_exec_continue</Font> (prg_control.c 209)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_continue(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Continue the execution after a "stop".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_target_terminal"></a>
+<center><Font Size=+2>gmi_target_terminal</Font> (prg_control.c 226)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_target_terminal(mi_h *h, const char *tty_name);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Indicate which terminal will use the target program. For local sessions.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+<Font Size=+1><u>Example</u></Font><p>
+
+
+<p>
+
+
+<p><hr></p>
+<a name="gmi_file_symbol_file"></a>
+<center><Font Size=+2>gmi_file_symbol_file</Font> (prg_control.c 242)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_file_symbol_file(mi_h *h, const char *file);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Specify what's the local copy that have debug info. For remote sessions.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_finish"></a>
+<center><Font Size=+2>gmi_exec_finish</Font> (prg_control.c 259)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_finish(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Continue until function return, the return value is included in the async
+response.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_interrupt"></a>
+<center><Font Size=+2>gmi_exec_interrupt</Font> (prg_control.c 278)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_interrupt(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Stop the program using SIGINT. The corresponding command should be
+-exec-interrupt but not even gdb 6.1.1 can do it because the "async" mode
+isn't really working.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+Always 1
+<p>
+
+
+<Font Size=+1><u>Example</u></Font><p>
+
+
+<p>
+
+
+<p><hr></p>
+<a name="gmi_exec_next"></a>
+<center><Font Size=+2>gmi_exec_next</Font> (prg_control.c 299)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_next(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Next line of code.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_next_cnt"></a>
+<center><Font Size=+2>gmi_exec_next_cnt</Font> (prg_control.c 315)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_next_cnt(mi_h *h, int count);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Skip count lines of code.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_next_instruction"></a>
+<center><Font Size=+2>gmi_exec_next_instruction</Font> (prg_control.c 331)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_next_instruction(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Next line of assembler code.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_step"></a>
+<center><Font Size=+2>gmi_exec_step</Font> (prg_control.c 347)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_step(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Next line of code. Get inside functions.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_step_cnt"></a>
+<center><Font Size=+2>gmi_exec_step_cnt</Font> (prg_control.c 363)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_step_cnt(mi_h *h, int count);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Next count lines of code. Get inside functions.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_step_instruction"></a>
+<center><Font Size=+2>gmi_exec_step_instruction</Font> (prg_control.c 379)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_step_instruction(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Next line of assembler code. Get inside calls.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_until"></a>
+<center><Font Size=+2>gmi_exec_until</Font> (prg_control.c 396)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_until(mi_h *h, const char *file, int line);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Execute until location is reached. If file is NULL then is until next
+line.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_until_addr"></a>
+<center><Font Size=+2>gmi_exec_until_addr</Font> (prg_control.c 412)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_until_addr(mi_h *h, void *addr);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Execute until location is reached.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_return"></a>
+<center><Font Size=+2>gmi_exec_return</Font> (prg_control.c 429)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_return(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A pointer to a new mi_frames structure indicating the current
+location. NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_exec_kill"></a>
+<center><Font Size=+2>gmi_exec_kill</Font> (prg_control.c 447)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_exec_kill(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Just kill the program. That's what -exec-abort should do, but it isn't
+implemented by gdb. This implementation only works if the interactive mode
+is disabled (gmi_gdb_set("confirm","off")).
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_list_frames"></a>
+<center><Font Size=+2>gmi_stack_list_frames</Font> (stack_man.c 76)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_list_frames(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List of frames. Arguments aren't filled.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new list of mi_frames or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_list_frames_r"></a>
+<center><Font Size=+2>gmi_stack_list_frames_r</Font> (stack_man.c 93)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_list_frames_r(mi_h *h, int from, int to);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List of frames. Arguments aren't filled. Only the frames in the @var{from}
+ - @var{to} range are returned.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new list of mi_frames or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_list_arguments"></a>
+<center><Font Size=+2>gmi_stack_list_arguments</Font> (stack_man.c 109)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_list_arguments(mi_h *h, int show);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List arguments. Only @var{level} and @var{args} filled.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new list of mi_frames or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_list_arguments_r"></a>
+<center><Font Size=+2>gmi_stack_list_arguments_r</Font> (stack_man.c 126)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List arguments. Only @var{level} and @var{args} filled. Only for the
+frames in the @var{from} - @var{to} range.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new list of mi_frames or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_info_frame"></a>
+<center><Font Size=+2>gmi_stack_info_frame</Font> (stack_man.c 142)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_info_frame(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Information about the current frame, including args.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_frames or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_info_depth"></a>
+<center><Font Size=+2>gmi_stack_info_depth</Font> (stack_man.c 158)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_info_depth(mi_h *h, int max_depth);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Stack info depth.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The depth or -1 on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_info_depth_get"></a>
+<center><Font Size=+2>gmi_stack_info_depth_get</Font> (stack_man.c 184)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_info_depth_get(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Set stack info depth.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The depth or -1 on error.
+<p>
+
+
+<Font Size=+1><u>Example</u></Font><p>
+
+
+<p>
+
+
+<p><hr></p>
+<a name="gmi_stack_select_frame"></a>
+<center><Font Size=+2>gmi_stack_select_frame</Font> (stack_man.c 199)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_select_frame(mi_h *h, int framenum);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Change current frame.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_stack_list_locals"></a>
+<center><Font Size=+2>gmi_stack_list_locals</Font> (stack_man.c 215)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_stack_list_locals(mi_h *h, int show);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List of local vars.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_results tree containing the variables or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_target_select"></a>
+<center><Font Size=+2>gmi_target_select</Font> (target_man.c 54)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_target_select(mi_h *h, const char *type, const char *params);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Connect to a remote gdbserver using the specified methode.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_target_attach"></a>
+<center><Font Size=+2>gmi_target_attach</Font> (target_man.c 70)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_target_attach(mi_h *h, pid_t pid);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Attach to an already running process.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+The frame of the current location, NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_target_detach"></a>
+<center><Font Size=+2>gmi_target_detach</Font> (target_man.c 87)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_target_detach(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Detach from an attached process.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_thread_list_ids"></a>
+<center><Font Size=+2>gmi_thread_list_ids</Font> (thread.c 49)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_thread_list_ids(mi_h *h, int **list);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List available thread ids.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_thread_select"></a>
+<center><Font Size=+2>gmi_thread_select</Font> (thread.c 65)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_thread_select(mi_h *h, int id);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Select a thread.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_frames or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_thread_list_all_threads"></a>
+<center><Font Size=+2>gmi_thread_list_all_threads</Font> (thread.c 82)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_thread_list_all_threads(mi_h *h);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Get a list of frames for each available thread. Implemented using "info
+thread".
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A kist of frames, NULL on error
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_create_nm"></a>
+<center><Font Size=+2>gmi_var_create_nm</Font> (var_obj.c 122)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Create a variable object. I recommend using <a href="#gmi_var_create">gmi_var_create</a> and letting
+gdb choose the names.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_gvar strcture or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_create"></a>
+<center><Font Size=+2>gmi_var_create</Font> (var_obj.c 139)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_create(mi_h *h, int frame, const char *exp);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Create a variable object. The name is selected by gdb. Alternative:
+<a href="#gmi_full_var_create">gmi_full_var_create</a>.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_gvar strcture or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_delete"></a>
+<center><Font Size=+2>gmi_var_delete</Font> (var_obj.c 154)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_delete(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Delete a variable object. Doesn't free the mi_gvar data.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_set_format"></a>
+<center><Font Size=+2>gmi_var_set_format</Font> (var_obj.c 170)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Set the format used to represent the result.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_show_format"></a>
+<center><Font Size=+2>gmi_var_show_format</Font> (var_obj.c 191)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_show_format(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fill the format field with info from gdb.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_info_num_children"></a>
+<center><Font Size=+2>gmi_var_info_num_children</Font> (var_obj.c 207)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_info_num_children(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fill the numchild field with info from gdb.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_info_type"></a>
+<center><Font Size=+2>gmi_var_info_type</Font> (var_obj.c 223)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_info_type(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fill the type field with info from gdb.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_info_expression"></a>
+<center><Font Size=+2>gmi_var_info_expression</Font> (var_obj.c 240)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_info_expression(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fill the expression and lang fields with info from gdb. Note that lang
+isn't filled during creation.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_show_attributes"></a>
+<center><Font Size=+2>gmi_var_show_attributes</Font> (var_obj.c 258)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_show_attributes(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fill the attr field with info from gdb. Note that attr isn't filled
+during creation.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_full_var_create"></a>
+<center><Font Size=+2>gmi_full_var_create</Font> (var_obj.c 275)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_full_var_create(mi_h *h, int frame, const char *exp);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Create the variable and also fill the lang and attr fields. The name is
+selected by gdb.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+A new mi_gvar strcture or NULL on error.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_update"></a>
+<center><Font Size=+2>gmi_var_update</Font> (var_obj.c 297)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Update variable. Use NULL for all. Note that *changed can be NULL if none
+updated.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK. The @var{changed} list contains the list of changed vars.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_assign"></a>
+<center><Font Size=+2>gmi_var_assign</Font> (var_obj.c 313)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Change variable. The new value replaces the @var{value} field.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_evaluate_expression"></a>
+<center><Font Size=+2>gmi_var_evaluate_expression</Font> (var_obj.c 337)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_evaluate_expression(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+Fill the value field getting the current value for a variable.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK, value contains the result.
+<p>
+
+
+
+<p><hr></p>
+<a name="gmi_var_list_children"></a>
+<center><Font Size=+2>gmi_var_list_children</Font> (var_obj.c 362)</center>
+
+<Font Size=+1><u>Syntax</u></Font><p>
+
+
+
+<pre>
+ gmi_var_list_children(mi_h *h, mi_gvar *var);
+</pre>
+
+
+
+
+<Font Size=+1><u>Description</u></Font><p>
+
+List children. It ONLY returns the first level information. :-(<br>
+  On success the child field contains the list of children.
+<p>
+
+
+<Font Size=+1><u>Return Value</u></Font><p>
+
+!=0 OK
+<p>
+
+
+
+
+
+</body>
+</html>
diff --git a/examples/.cvsignore b/examples/.cvsignore
new file mode 100644 (file)
index 0000000..ad49ccf
--- /dev/null
@@ -0,0 +1,15 @@
+*.dst
+.*.dst
+*.epr*
+test_target
+x11_test
+remote_test
+linux_test
+x11_wp_test
+x11_cpp_test
+target_frames
+x11_fr_test
+pty_test
+ticepic
+*.cod
+*.lst
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644 (file)
index 0000000..0e6060c
--- /dev/null
@@ -0,0 +1,31 @@
+#!/usr/bin/make
+
+all: test_target x11_test remote_test linux_test target_frames x11_fr_test \
+       x11_wp_test x11_cpp_test pty_test
+
+CFLAGS=-O0 -Wall -gstabs+3 -I../src
+CXXFLAGS=-O0 -Wall -gstabs+3 -I../src
+LDLIBS=
+
+ticepic: ticepic.c ../src/libmigdb.a
+
+x11_test: x11_test.c ../src/libmigdb.a
+
+x11_cpp_test: x11_cpp_test.cc ../src/libmigdb.a
+
+x11_fr_test: x11_fr_test.c ../src/libmigdb.a
+
+x11_wp_test: x11_wp_test.c ../src/libmigdb.a
+
+remote_test: remote_test.c ../src/libmigdb.a
+
+linux_test: linux_test.c ../src/libmigdb.a
+
+pty_test: pty_test.c ../src/libmigdb.a
+
+clean:
+       -@rm *.o *.a test_target x11_test remote_test linux_test 2> /dev/null
+       -@rm x11_wp_test x11_cpp_test target_frames x11_fr_test 2> /dev/null
+       -@rm pty_test 2> /dev/null
+
+
diff --git a/examples/cmds.txt b/examples/cmds.txt
new file mode 100644 (file)
index 0000000..66cd5ca
--- /dev/null
@@ -0,0 +1,3 @@
+help
+help break
+
diff --git a/examples/linux_test.c b/examples/linux_test.c
new file mode 100644 (file)
index 0000000..3c610dd
--- /dev/null
@@ -0,0 +1,195 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  Linux console example/test of the libmigdb.
+  Run it from a Linux console.
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+int wait_for_stop(mi_h *h)
+{
+ int res=1;
+ mi_stop *sr;
+
+ while (!mi_get_response(h))
+    usleep(1000);
+ /* The end of the async. */
+ sr=mi_res_stop(h);
+ if (sr)
+   {
+    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
+    mi_free_stop(sr);
+   }
+ else
+   {
+    printf("Error while waiting\n");
+    res=0;
+   }
+ return res;
+}
+
+int main(int argc, char *argv[])
+{
+ mi_aux_term *child_vt=NULL;
+ mi_bkpt *bk;
+ mi_wp *wp;
+ /* This is like a file-handle for fopen.
+    Here we have all the state of gdb "connection". */
+ mi_h *h;
+
+ /* You can use any gdb you want: */
+ /*mi_set_gdb_exe("/usr/src/gdb-6.1.1/gdb/gdb");*/
+ /* You can use a terminal different than xterm: */
+ /*mi_set_xterm_exe("/usr/bin/Eterm");*/
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Look for a free VT where we can run the child. */
+ child_vt=gmi_look_for_free_vt();
+ if (!child_vt)
+    printf("Error opening auxiliar terminal, we'll use current one.\n");
+ else
+   {
+    printf("Free VT @ %s\n",child_vt->tty);
+    printf("\n\n***************************************\n");
+    printf("Switch to the above mentioned terminal!\n");
+    printf("***************************************\n\n\n");
+   }
+
+ /* Tell gdb to attach the child to a terminal. */
+ if (!gmi_target_terminal(h,child_vt ? child_vt->tty : ttyname(STDIN_FILENO)))
+   {
+    printf("Error selecting target terminal\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set the name of the child and the command line aguments. */
+ if (!gmi_set_exec(h,"./test_target","prb1 2 prb3"))
+   {
+    printf("Error setting exec y args\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set a breakpoint. */
+ bk=gmi_break_insert(h,"test_target.cc",12);
+ if (!bk)
+   {
+    printf("Error setting breakpoint\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
+
+ /* You can do things like:
+ gmi_break_delete(h,bk->number);
+ gmi_break_set_times(h,bk->number,2);
+ gmi_break_set_condition(h,bk->number,"1");
+ gmi_break_state(h,bk->number,0);*/
+ /* If we no longer need this data we can release it. */
+ mi_free_bkpt(bk);
+
+ /* Set a watchpoint, that's a data breakpoint. */
+ wp=gmi_break_watch(h,wm_write,"v");
+ if (!wp)
+   {
+    printf("Error al setting watchpoint\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ printf("Watchpoint %d for expression: %s\n",wp->number,wp->exp);
+ mi_free_wp(wp);
+
+ /* Run the program. */
+ if (!gmi_exec_run(h))
+   {
+    printf("Error in run!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be stopped at the breakpoint. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Continue execution. */
+ if (!gmi_exec_continue(h))
+   {
+    printf("Error in continue!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be terminated. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+ gmi_end_aux_term(child_vt);
+
+ return 0;
+}
diff --git a/examples/pty_test.c b/examples/pty_test.c
new file mode 100644 (file)
index 0000000..070a3b5
--- /dev/null
@@ -0,0 +1,141 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  Example/test of pseudo terminals.
+  Note: Contributed by Greg Watson (gwatson lanl gov)
+
+***************************************************************************/
+
+#include <stdio.h>
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+}
+
+int main(int argc, char *argv[])
+{
+ mi_pty *pty=NULL;
+ mi_h *h;
+ fd_set rfds;
+ char buf[BUFSIZ];
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Look for a free pseudo terminal. */
+ pty=gmi_look_for_free_pty();
+ if (!pty) 
+   {
+    printf("Error opening pseudo terminal.\n");
+    return 1;
+   }
+
+ printf("Free pty slave = %s, master on %d\n",pty->slave,pty->master);
+
+ /* Tell gdb to attach the terminal. */
+ if (!gmi_target_terminal(h,pty->slave))
+   {
+    printf("Error selecting target terminal\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set the name of the child and the command line aguments. */
+ if (!gmi_set_exec(h,"./test_target","prb1 2 prb3"))
+   {
+    printf("Error setting exec y args\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Run the program. */
+ if (!gmi_exec_run(h))
+   {
+    printf("Error in run!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ for (;;)
+   {
+    FD_ZERO(&rfds);
+    FD_SET(pty->master,&rfds);
+    FD_SET(0,&rfds);
+    
+    if (select(pty->master+1,&rfds,NULL,NULL,NULL)<0)
+      {
+       perror("select");
+       mi_disconnect(h);
+       return 1;
+      }
+
+    if (FD_ISSET(pty->master,&rfds))
+      {
+       int n=read(pty->master,buf,BUFSIZ);
+       if (n<=0)
+          break;
+       write(1,buf,n);
+      }
+
+    if (FD_ISSET(0,&rfds))
+      {
+       int n=read(0,buf,BUFSIZ);
+       if (n<=0)
+          break;
+       write(pty->master,buf,n);
+      }
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+ gmi_end_pty(pty);
+
+ return 0;
+}
diff --git a/examples/remote_test.c b/examples/remote_test.c
new file mode 100644 (file)
index 0000000..9e76969
--- /dev/null
@@ -0,0 +1,179 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  Remote example/test of the libmigdb.
+  To run it you must:
+
+1) Copy "test_target" to the "remote" host (it could be the same machine if
+you want).
+2) In the "remote" end run "gdbserver :6000 ./test_target 1 2 3"
+3) Run this example in the "local" end.
+
+You should edit the remote IP and port before compiling.
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+// Example: "192.168.1.3:5500"
+#define REMOTE_MACHINE ":6000"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+int wait_for_stop(mi_h *h)
+{
+ mi_output *o;
+ int res=1;
+ char *aux;
+
+ while (!mi_get_response(h))
+    usleep(1000);
+ /* The end of the async. */
+ o=mi_retire_response(h);
+ if (mi_get_async_stop_reason(o,&aux))
+    printf("Stopped, reason: %s\n",aux);
+ else
+   {
+    printf("Error while waiting: %s\n",aux);
+    res=0;
+   }
+ mi_free_output(o);
+ return res;
+}
+
+int main(int argc, char *argv[])
+{
+ mi_bkpt *bk;
+ /* This is like a file-handle for fopen.
+    Here we have all the state of gdb "connection". */
+ mi_h *h;
+
+ /* You can use any gdb you want: */
+ /*mi_set_gdb_exe("/usr/src/gdb-6.1.1/gdb/gdb");*/
+ /* You can use a terminal different than xterm: */
+ /*mi_set_xterm_exe("/usr/bin/Eterm");*/
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Tell gdb to load symbols from the local copy. */
+ if (!gmi_file_symbol_file(h,"./test_target"))
+   {
+    printf("Error loading symbols\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Connect to remote machine using TCP/IP. */
+ if (!gmi_target_select(h,"extended-remote",REMOTE_MACHINE))
+   {
+    printf("Error connecting to gdb server\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set a breakpoint. */
+ bk=gmi_break_insert(h,"test_target.cc",12);
+ if (!bk)
+   {
+    printf("Error setting breakpoint\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
+
+ /* You can do things like:
+ gmi_break_delete(h,bk->number);
+ gmi_break_set_times(h,bk->number,2);
+ gmi_break_set_condition(h,bk->number,"1");
+ gmi_break_state(h,bk->number,0);*/
+ /* If we no longer need this data we can release it. */
+ mi_free_bkpt(bk);
+
+ /* Run the program. */
+ /* Note that remote targets starts running and we must use continue! */
+ if (!gmi_exec_continue(h))
+   {
+    printf("Error in continue!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be stopped at the breakpoint. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Continue execution. */
+ if (!gmi_exec_continue(h))
+   {
+    printf("Error in continue!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be terminated. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+
+ return 0;
+}
diff --git a/examples/target_frames.cc b/examples/target_frames.cc
new file mode 100644 (file)
index 0000000..e58bbab
--- /dev/null
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <string.h>
+
+int v=2; struct { char *a; int q; } sup;
+
+int FuncLev2(char *str)
+{
+ v=5;
+ return strlen(str);
+}
+
+int FuncLev1(char *s, int i)
+{
+ i+=FuncLev2(s);
+ return i;
+}
+
+int main(int argc, char *argv[])
+{
+ FuncLev1("Hi!",2500);
+ printf("v=%d\n",v);
+ return 0;
+}
diff --git a/examples/test_target.cc b/examples/test_target.cc
new file mode 100644 (file)
index 0000000..83deeb6
--- /dev/null
@@ -0,0 +1,22 @@
+#include <stdio.h>
+
+int v=3;
+
+void PrintHi(int val)
+{
+ int x=val*3;
+
+ printf("Hi! x=%d\n",x); v++;
+}
+
+int main(int argc, char *argv[])
+{
+ printf("arguments: %d\n",argc);
+ for (int i=0; i<argc; i++)
+     printf("%d: %s\n",i,argv[i]);
+ printf("*stopped,reason=\"You fool! that isn't gdb ;-)\"\n"); v=5;
+ printf("Press ENTER\n");
+ getchar();
+ PrintHi(argc);
+ return 0;
+}
diff --git a/examples/ticepic.c b/examples/ticepic.c
new file mode 100644 (file)
index 0000000..68982ab
--- /dev/null
@@ -0,0 +1,200 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004-2009 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  This is an example of how to use libmigdb with something different than
+gdb. In this particular case we use a program called icepic and we load
+test_bcd.cod on it. Note that these files aren't distributed and are very
+specific, this is just an example.
+  X11 example/test of the libmigdb.
+  Run it from an X11 terminal (xterm, Eterm, etc.).
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+void print_frames(mi_frames *f, int free_f)
+{
+ mi_frames *ff=f;
+
+ if (!f)
+   {
+    printf("Error! empty frames info\n");
+    return;
+   }
+ while (f)
+   {
+    printf("Level %d, addr %p, func %s, where: %s:%d args? %c\n",f->level,f->addr,
+           f->func,f->file,f->line,f->args ? 'y' : 'n');
+    f=f->next;
+   }
+ if (free_f)
+    mi_free_frames(ff);
+}
+
+int wait_for_stop(mi_h *h)
+{
+ int res=1;
+ mi_stop *sr;
+
+ while (!mi_get_response(h))
+    usleep(1000);
+ /* The end of the async. */
+ sr=mi_res_stop(h);
+ if (sr)
+   {
+    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
+    print_frames(sr->frame,0);
+    mi_free_stop(sr);
+   }
+ else
+   {
+    printf("Error while waiting\n");
+    res=0;
+   }
+ return res;
+}
+
+void print_gvar(mi_gvar *v)
+{
+ if (!v)
+   {
+    printf("Error! failed to define variable\n");
+    return;
+   }
+ printf("Variable name: '%s', type: '%s', number of children: %d format: %s expression: %s lang: %s editable: %c\n",
+        v->name,v->type,v->numchild,mi_format_enum_to_str(v->format),
+        v->exp,mi_lang_enum_to_str(v->lang),v->attr & MI_ATTR_EDITABLE ? 'y' : 'n');
+}
+
+void print_update(mi_gvar_chg *changed)
+{
+ printf("List of changed variables:\n");
+ while (changed)
+   {
+    printf("Name: %s\nIn scope: %c\n",changed->name,changed->in_scope ? 'y' : 'n');
+    if (changed->in_scope && changed->new_type)
+      {
+       printf("New type: %s\nNew num children: %d\n",changed->new_type,changed->new_num_children);
+      }
+    changed=changed->next;
+    printf("\n");
+   }
+}
+
+void print_children(mi_gvar *ch)
+{
+ int i;
+ mi_gvar *s;
+
+ if (!ch->child)
+   {
+    printf("Error! getting children list\n");
+    return;
+   }
+ printf("\nChildren List (%d):\n",ch->numchild);
+ for (i=0, s=ch->child; i<ch->numchild; s++, i++)
+    {
+     printf("Name: %s Exp: %s Children: %d",s->name,s->exp,s->numchild);
+     if (s->type)
+        printf(" Type: %s",s->type);
+     if (s->value)
+        printf(" Value: %s",s->value);
+     printf("\n");
+    }
+ printf("\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+ mi_aux_term *xterm_tty=NULL;
+ mi_bkpt *bk;
+ mi_frames *fr;
+ /* This is like a file-handle for fopen.
+    Here we have all the state of gdb "connection". */
+ mi_h *h;
+ mi_gvar *gv, *gv2;
+ mi_gvar_chg *changed;
+ char *value;
+ int r_assign;
+
+ /* You can use any gdb you want: */
+ mi_set_gdb_exe("./icepic");
+ /* You can use a terminal different than xterm: */
+ /*mi_set_xterm_exe("/usr/bin/Eterm");*/
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Set the name of the child and the command line aguments. */
+ if (!gmi_set_exec(h,"./test_bcd.cod",""))
+   {
+    printf("Error setting exec y args\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+ /* Wait 5 seconds and close the auxiliar terminal. */
+ printf("Waiting 5 seconds\n");
+ sleep(5);
+ gmi_end_aux_term(xterm_tty);
+
+ return 0;
+}
diff --git a/examples/x11_cpp_test.cc b/examples/x11_cpp_test.cc
new file mode 100644 (file)
index 0000000..7d524cc
--- /dev/null
@@ -0,0 +1,166 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  X11 example/test of the libmigdb.
+  Run it from an X11 terminal (xterm, Eterm, etc.).
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+int wait_for_stop(MIDebugger &d)
+{
+ int res=1;
+ mi_stop *sr;
+
+ while (!d.Poll(sr))
+    usleep(1000);
+ /* The end of the async. */
+ if (sr)
+   {
+    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
+    mi_free_stop(sr);
+   }
+ else
+   {
+    printf("Error while waiting\n");
+    printf("mi_error: %d\nmi_error_from_gdb: %s\n",mi_error,mi_error_from_gdb);
+    res=0;
+   }
+ return res;
+}
+
+int DoTryRun(int res, MIDebugger &d)
+{
+ if (!res)
+   {
+    printf("Error in executing!\n");
+    return 0;
+   }
+ if (!wait_for_stop(d))
+    return 0;
+ return 1;
+}
+
+#define TryRun(a,b) if (!DoTryRun(a,b)) return 1
+
+int main(int argc, char *argv[])
+{
+ mi_bkpt *bk;
+ mi_wp *wp;
+
+ // Debugging object, used as an auto var.
+ MIDebugger d;
+
+ // You can use any gdb you want:
+ //MIDebugger::SetGDBExe("/usr/src/gdb-6.1.1/gdb/gdb");
+ // You can use a terminal different than xterm:
+ //MIDebugger::SetXTerm("/usr/bin/Eterm");
+ // You can specify commands for gdb
+ MIDebugger::SetGDBStartFile("cmds.txt");
+
+ // Connect to gdb child.
+ if (!d.Connect())
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ d.SetConsoleCB(cb_console);
+ d.SetTargetCB(cb_target);
+ d.SetLogCB(cb_log);
+ d.SetAsyncCB(cb_async);
+ d.SetToGDBCB(cb_to);
+ d.SetFromGDBCB(cb_from);
+
+ // Set the name of the child and the command line aguments.
+ // It also opens the xterm.
+ if (!d.SelectTargetX11("./test_target","prb1 2 prb3"))
+   {
+    printf("Error setting exec y args\n");
+    return 1;
+   }
+
+ /* Set a breakpoint. */
+ bk=d.Breakpoint("test_target.cc",15);
+ if (!bk)
+   {
+    printf("Error setting breakpoint\n");
+    return 1;
+   }
+ printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
+
+ /* You can do things like:
+ gmi_break_delete(h,bk->number);
+ gmi_break_set_times(h,bk->number,2);
+ gmi_break_set_condition(h,bk->number,"1");
+ gmi_break_state(h,bk->number,0);*/
+ /* If we no longer need this data we can release it. */
+ mi_free_bkpt(bk);
+
+ /* Set a watchpoint, that's a data breakpoint. */
+ wp=d.Watchpoint(wm_write,"v");
+ if (!wp)
+   {
+    printf("Error al setting watchpoint\n");
+    return 1;
+   }
+ printf("Watchpoint %d for expression: %s\n",wp->number,wp->exp);
+ mi_free_wp(wp);
+
+ TryRun(d.StepOver(),d);
+ /* Run the program. */
+ TryRun(d.RunOrContinue(),d);
+ /* Here we should be stopped at the breakpoint. */
+
+ /* Continue execution. */
+ TryRun(d.RunOrContinue(),d);
+ /* Here we should be terminated. */
+
+ /* Wait 5 seconds and close the auxiliar terminal. */
+ printf("Waiting 5 seconds\n");
+ sleep(5);
+
+ return 0;
+}
diff --git a/examples/x11_fr_test.c b/examples/x11_fr_test.c
new file mode 100644 (file)
index 0000000..dd0f4f7
--- /dev/null
@@ -0,0 +1,329 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  X11 example/test of the libmigdb.
+  Run it from an X11 terminal (xterm, Eterm, etc.).
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+void print_frames(mi_frames *f, int free_f)
+{
+ mi_frames *ff=f;
+
+ if (!f)
+   {
+    printf("Error! empty frames info\n");
+    return;
+   }
+ while (f)
+   {
+    printf("Level %d, addr %p, func %s, where: %s:%d args? %c\n",f->level,f->addr,
+           f->func,f->file,f->line,f->args ? 'y' : 'n');
+    f=f->next;
+   }
+ if (free_f)
+    mi_free_frames(ff);
+}
+
+int wait_for_stop(mi_h *h)
+{
+ int res=1;
+ mi_stop *sr;
+
+ while (!mi_get_response(h))
+    usleep(1000);
+ /* The end of the async. */
+ sr=mi_res_stop(h);
+ if (sr)
+   {
+    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
+    print_frames(sr->frame,0);
+    mi_free_stop(sr);
+   }
+ else
+   {
+    printf("Error while waiting\n");
+    res=0;
+   }
+ return res;
+}
+
+void print_gvar(mi_gvar *v)
+{
+ if (!v)
+   {
+    printf("Error! failed to define variable\n");
+    return;
+   }
+ printf("Variable name: '%s', type: '%s', number of children: %d format: %s expression: %s lang: %s editable: %c\n",
+        v->name,v->type,v->numchild,mi_format_enum_to_str(v->format),
+        v->exp,mi_lang_enum_to_str(v->lang),v->attr & MI_ATTR_EDITABLE ? 'y' : 'n');
+}
+
+void print_update(mi_gvar_chg *changed)
+{
+ printf("List of changed variables:\n");
+ while (changed)
+   {
+    printf("Name: %s\nIn scope: %c\n",changed->name,changed->in_scope ? 'y' : 'n');
+    if (changed->in_scope && changed->new_type)
+      {
+       printf("New type: %s\nNew num children: %d\n",changed->new_type,changed->new_num_children);
+      }
+    changed=changed->next;
+    printf("\n");
+   }
+}
+
+void print_children(mi_gvar *ch)
+{
+ int i;
+ mi_gvar *s;
+
+ if (!ch->child)
+   {
+    printf("Error! getting children list\n");
+    return;
+   }
+ printf("\nChildren List (%d):\n",ch->numchild);
+ for (i=0, s=ch->child; i<ch->numchild; s++, i++)
+    {
+     printf("Name: %s Exp: %s Children: %d",s->name,s->exp,s->numchild);
+     if (s->type)
+        printf(" Type: %s",s->type);
+     if (s->value)
+        printf(" Value: %s",s->value);
+     printf("\n");
+    }
+ printf("\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+ mi_aux_term *xterm_tty=NULL;
+ mi_bkpt *bk;
+ mi_frames *fr;
+ /* This is like a file-handle for fopen.
+    Here we have all the state of gdb "connection". */
+ mi_h *h;
+ mi_gvar *gv, *gv2;
+ mi_gvar_chg *changed;
+ char *value;
+ int r_assign;
+
+ /* You can use any gdb you want: */
+ /*mi_set_gdb_exe("/usr/src/gdb-6.1.1/gdb/gdb");*/
+ /* You can use a terminal different than xterm: */
+ /*mi_set_xterm_exe("/usr/bin/Eterm");*/
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Set the name of the child and the command line aguments. */
+ if (!gmi_set_exec(h,"./target_frames",""))
+   {
+    printf("Error setting exec y args\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Open an xterm to be used as terminal for the debuggy. */
+ xterm_tty=gmi_start_xterm();
+ if (!xterm_tty)
+    printf("Error opening auxiliar terminal, we'll use current one.\n");
+ else
+    printf("XTerm opened @ %s\n",xterm_tty->tty);
+
+ /* Tell gdb to attach the child to a terminal. */
+ if (!gmi_target_terminal(h,xterm_tty ? xterm_tty->tty : ttyname(STDIN_FILENO)))
+   {
+    printf("Error selecting target terminal\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set a breakpoint. */
+ bk=gmi_break_insert(h,"target_frames.cc",7);
+ if (!bk)
+   {
+    printf("Error setting breakpoint\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
+
+ /* If we no longer need this data we can release it. */
+ mi_free_bkpt(bk);
+
+ /* Run the program. */
+ if (!gmi_exec_run(h))
+   {
+    printf("Error in run!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be stopped at the breakpoint. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Get information about the calling stack. */
+ fr=gmi_stack_list_frames(h);
+ printf("\nCalling stack:\n\n");
+ print_frames(fr,1);
+ printf("\n");
+ fr=gmi_stack_info_frame(h);
+ printf("\nCurrent frame:\n\n");
+ print_frames(fr,1);
+ printf("\n");
+ printf("Stack depth: %d\n",gmi_stack_info_depth_get(h));
+ gmi_stack_select_frame(h,1);
+ fr=gmi_stack_info_frame(h);
+ printf("\nFrame 1:\n\n");
+ print_frames(fr,1);
+ printf("\n");
+
+ if (0)
+   {
+    gv=gmi_var_create(h,-1,"v");
+    print_gvar(gv);
+    gmi_var_show_format(h,gv);
+    print_gvar(gv);
+    gmi_var_info_num_children(h,gv);
+    print_gvar(gv);
+    gmi_var_info_type(h,gv);
+    print_gvar(gv);
+    gmi_var_info_expression(h,gv);
+    print_gvar(gv);
+    gmi_var_show_attributes(h,gv);
+    print_gvar(gv);
+   }
+ else
+   {
+    gv=gmi_full_var_create(h,-1,"v");
+    print_gvar(gv);
+   }
+ gv2=gmi_full_var_create(h,-1,"sup");
+ print_gvar(gv2);
+ gmi_var_set_format(h,gv,fm_hexadecimal);
+ print_gvar(gv);
+
+ /* Continue execution. */
+ if (!gmi_exec_until(h,"target_frames.cc",21))
+   {
+    printf("Error in exec until!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ gmi_var_update(h,NULL,&changed);
+ print_update(changed);
+ mi_free_gvar_chg(changed);
+
+ r_assign=gmi_var_assign(h,gv,"i+5");
+ if (r_assign && gv->value)
+    printf("\nAssigned v=%s\n\n",gv->value);
+
+ gmi_var_list_children(h,gv2);
+ print_children(gv2);
+
+ gmi_var_evaluate_expression(h,gv2);
+ printf("\n%s = %s\n\n",gv2->exp,gv2->value);
+
+ value=gmi_data_evaluate_expression(h,gv2->exp);
+ printf("\n%s = %s\n\n",gv2->exp,value);
+ free(value);
+
+ gmi_var_delete(h,gv);
+ mi_free_gvar(gv);
+ gmi_var_delete(h,gv2);
+ mi_free_gvar(gv2);
+
+ /* Continue execution. */
+ if (!gmi_exec_continue(h))
+   {
+    printf("Error in continue!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be terminated. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+ /* Wait 5 seconds and close the auxiliar terminal. */
+ printf("Waiting 5 seconds\n");
+ sleep(5);
+ gmi_end_aux_term(xterm_tty);
+
+ return 0;
+}
diff --git a/examples/x11_test.c b/examples/x11_test.c
new file mode 100644 (file)
index 0000000..4f2be25
--- /dev/null
@@ -0,0 +1,192 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  X11 example/test of the libmigdb.
+  Run it from an X11 terminal (xterm, Eterm, etc.).
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+int wait_for_stop(mi_h *h)
+{
+ int res=1;
+ mi_stop *sr;
+
+ while (!mi_get_response(h))
+    usleep(1000);
+ /* The end of the async. */
+ sr=mi_res_stop(h);
+ if (sr)
+   {
+    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
+    mi_free_stop(sr);
+   }
+ else
+   {
+    printf("Error while waiting\n");
+    printf("mi_error: %d\nmi_error_from_gdb: %s\n",mi_error,mi_error_from_gdb);
+    res=0;
+   }
+ return res;
+}
+
+int main(int argc, char *argv[])
+{
+ mi_aux_term *xterm_tty=NULL;
+ mi_bkpt *bk;
+ mi_wp *wp;
+ /* This is like a file-handle for fopen.
+    Here we have all the state of gdb "connection". */
+ mi_h *h;
+
+ /* You can use any gdb you want: */
+ /*mi_set_gdb_exe("/usr/src/gdb-6.1.1/gdb/gdb");*/
+ /* You can use a terminal different than xterm: */
+ /*mi_set_xterm_exe("/usr/bin/Eterm");*/
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Set the name of the child and the command line aguments. */
+ if (!gmi_set_exec(h,"./test_target","prb1 2 prb3"))
+   {
+    printf("Error setting exec y args\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Open an xterm to be used as terminal for the debuggy. */
+ xterm_tty=gmi_start_xterm();
+ if (!xterm_tty)
+    printf("Error opening auxiliar terminal, we'll use current one.\n");
+ else
+    printf("XTerm opened @ %s\n",xterm_tty->tty);
+
+ /* Tell gdb to attach the child to a terminal. */
+ if (!gmi_target_terminal(h,xterm_tty ? xterm_tty->tty : ttyname(STDIN_FILENO)))
+   {
+    printf("Error selecting target terminal\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set a breakpoint. */
+ bk=gmi_break_insert(h,"test_target.cc",12);
+ if (!bk)
+   {
+    printf("Error setting breakpoint\n");
+    return 1;
+   }
+ printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
+
+ /* You can do things like:
+ gmi_break_delete(h,bk->number);
+ gmi_break_set_times(h,bk->number,2);
+ gmi_break_set_condition(h,bk->number,"1");
+ gmi_break_state(h,bk->number,0);*/
+ /* If we no longer need this data we can release it. */
+ mi_free_bkpt(bk);
+
+ /* Set a watchpoint, that's a data breakpoint. */
+ wp=gmi_break_watch(h,wm_write,"v");
+ if (!wp)
+   {
+    printf("Error al setting watchpoint\n");
+    return 1;
+   }
+ printf("Watchpoint %d for expression: %s\n",wp->number,wp->exp);
+ mi_free_wp(wp);
+
+ /* Run the program. */
+ if (!gmi_exec_run(h))
+   {
+    printf("Error in run!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be stopped at the breakpoint. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Continue execution. */
+ if (!gmi_exec_continue(h))
+   {
+    printf("Error in continue!\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ /* Here we should be terminated. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+ /* Wait 5 seconds and close the auxiliar terminal. */
+ printf("Waiting 5 seconds\n");
+ sleep(5);
+ gmi_end_aux_term(xterm_tty);
+
+ return 0;
+}
diff --git a/examples/x11_wp_test.c b/examples/x11_wp_test.c
new file mode 100644 (file)
index 0000000..39bdebf
--- /dev/null
@@ -0,0 +1,292 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comment:
+  X11 example/test of the libmigdb.
+  Run it from an X11 terminal (xterm, Eterm, etc.).
+  
+***************************************************************************/
+
+#include <stdio.h>
+#include <unistd.h> //usleep
+#include "mi_gdb.h"
+
+void cb_console(const char *str, void *data)
+{
+ printf("CONSOLE> %s\n",str);
+}
+
+/* Note that unlike what's documented in gdb docs it isn't usable. */
+void cb_target(const char *str, void *data)
+{
+ printf("TARGET> %s\n",str);
+}
+
+void cb_log(const char *str, void *data)
+{
+ printf("LOG> %s\n",str);
+}
+
+void cb_to(const char *str, void *data)
+{
+ printf(">> %s",str);
+}
+
+void cb_from(const char *str, void *data)
+{
+ printf("<< %s\n",str);
+}
+
+volatile int async_c=0;
+
+void cb_async(mi_output *o, void *data)
+{
+ printf("ASYNC\n");
+ async_c++;
+}
+
+void print_frames(mi_frames *f)
+{
+ if (!f)
+   {
+    printf("Error! empty frames info\n");
+    return;
+   }
+ while (f)
+   {
+    printf("Level %d, addr %p, func %s, where: %s:%d args? %c\n",f->level,f->addr,
+           f->func,f->file,f->line,f->args ? 'y' : 'n');
+    f=f->next;
+   }
+ mi_free_frames(f);
+}
+
+int wait_for_stop(mi_h *h)
+{
+ int res=1;
+ mi_stop *sr;
+
+ while (!mi_get_response(h))
+    usleep(1000);
+ /* The end of the async. */
+ sr=mi_res_stop(h);
+ if (sr)
+   {
+    printf("Stopped, reason: %s\n",mi_reason_enum_to_str(sr->reason));
+    print_frames(sr->frame);
+    mi_free_stop(sr);
+   }
+ else
+   {
+    printf("Error while waiting\n");
+    printf("mi_error: %s (%d)\nmi_error_from_gdb: %s\n",mi_get_error_str(),
+           mi_error,mi_error_from_gdb);
+    res=0;
+   }
+ return res;
+}
+
+
+void print_gvar(mi_gvar *v)
+{
+ if (!v)
+   {
+    printf("Error! failed to define variable\n");
+    return;
+   }
+ printf("Variable name: '%s', type: '%s', number of children: %d format: %s expression: %s lang: %s editable: %c\n",
+        v->name,v->type,v->numchild,mi_format_enum_to_str(v->format),
+        v->exp,mi_lang_enum_to_str(v->lang),v->attr & MI_ATTR_EDITABLE ? 'y' : 'n');
+}
+
+void print_update(mi_gvar_chg *changed)
+{
+ printf("List of changed variables:\n");
+ while (changed)
+   {
+    printf("Name: %s\nIn scope: %c\n",changed->name,changed->in_scope ? 'y' : 'n');
+    if (changed->in_scope && changed->new_type)
+      {
+       printf("New type: %s\nNew num children: %d\n",changed->new_type,changed->new_num_children);
+      }
+    changed=changed->next;
+    printf("\n");
+   }
+}
+
+void print_children(mi_gvar *ch)
+{
+ int i;
+ mi_gvar *s;
+
+ if (!ch->child)
+   {
+    printf("Error! getting children list\n");
+    return;
+   }
+ printf("\nChildren List (%d):\n",ch->numchild);
+ for (i=0, s=ch->child; i<ch->numchild; s++, i++)
+    {
+     printf("Name: %s Exp: %s Children: %d",s->name,s->exp,s->numchild);
+     if (s->type)
+        printf(" Type: %s",s->type);
+     if (s->value)
+        printf(" Value: %s",s->value);
+     printf("\n");
+    }
+ printf("\n");
+}
+
+enum cont_mode { cm_run, cm_continue, cm_finish, cm_step };
+
+void do_continue(mi_h *h, enum cont_mode mode)
+{
+ int res;
+ switch (mode)
+   {
+    case cm_run:
+         res=gmi_exec_run(h);
+         break;
+    case cm_continue:
+         res=gmi_exec_continue(h);
+         break;
+    case cm_finish:
+         res=gmi_exec_finish(h);
+         break;
+    case cm_step:
+         res=gmi_exec_step(h);
+         break;
+   }
+ /* Continue the program. */
+ if (!res)
+   {
+    printf("Error in run!\n");
+    mi_disconnect(h);
+    exit(1);
+   }
+ /* Here we should be stopped at the breakpoint. */
+ if (!wait_for_stop(h))
+   {
+    mi_disconnect(h);
+    exit(1);
+   }
+}
+
+
+int main(int argc, char *argv[])
+{
+ mi_aux_term *xterm_tty=NULL;
+ /* This is like a file-handle for fopen.
+    Here we have all the state of gdb "connection". */
+ mi_h *h;
+ mi_bkpt *bk;
+ mi_wp *wp, *wp2;
+
+ /* You can use any gdb you want: */
+ /*mi_set_gdb_exe("/usr/src/gdb-6.1.1/gdb/gdb");*/
+ /* You can use a terminal different than xterm: */
+ /*mi_set_xterm_exe("/usr/bin/Eterm");*/
+
+ /* Connect to gdb child. */
+ h=mi_connect_local();
+ if (!h)
+   {
+    printf("Connect failed\n");
+    return 1;
+   }
+ printf("Connected to gdb!\n");
+
+ /* Set all callbacks. */
+ mi_set_console_cb(h,cb_console,NULL);
+ mi_set_target_cb(h,cb_target,NULL);
+ mi_set_log_cb(h,cb_log,NULL);
+ mi_set_async_cb(h,cb_async,NULL);
+ mi_set_to_gdb_cb(h,cb_to,NULL);
+ mi_set_from_gdb_cb(h,cb_from,NULL);
+
+ /* Open an xterm to be used as terminal for the debuggy. */
+ xterm_tty=gmi_start_xterm();
+ if (!xterm_tty)
+    printf("Error opening auxiliar terminal, we'll use current one.\n");
+ else
+    printf("XTerm opened @ %s\n",xterm_tty->tty);
+
+ /* Tell gdb to attach the child to a terminal. */
+ if (!gmi_target_terminal(h,xterm_tty ? xterm_tty->tty : ttyname(STDIN_FILENO)))
+   {
+    printf("Error selecting target terminal\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Set the name of the child and the command line aguments. */
+ if (!gmi_set_exec(h,"./target_frames",""))
+   {
+    printf("Error setting exec y args\n");
+    mi_disconnect(h);
+    return 1;
+   }
+
+ /* Break on FuncLev1. */
+ bk=gmi_break_insert_full(h,1,0,NULL,-1,-1,"FuncLev1");
+ if (!bk)
+   {
+    printf("Error setting breakpoint\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ printf("Breakpoint %d @ function: %s\n",bk->number,bk->func);
+ mi_free_bkpt(bk);
+
+ /* Set a watchpoint, that's a data breakpoint. */
+ wp=gmi_break_watch(h,wm_write,"v");
+ if (!wp)
+   {
+    printf("Error al setting watchpoint\n");
+    mi_disconnect(h);
+    return 1;
+   }
+ printf("Watchpoint %d for expression: %s\n",wp->number,wp->exp);
+ mi_free_wp(wp);
+
+ /* Run the program. */
+ do_continue(h,cm_run);
+
+ wp2=gmi_break_watch(h,wm_write,"i");
+ mi_free_wp(wp2);
+
+ if (1)
+   {
+    do_continue(h,cm_finish);
+    do_continue(h,cm_finish);
+    do_continue(h,cm_finish);
+    do_continue(h,cm_continue);
+    do_continue(h,cm_continue);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+   }
+ else
+   {
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+    do_continue(h,cm_step);
+   }
+
+ /* Exit from gdb. */
+ gmi_gdb_exit(h);
+ /* Close the connection. */
+ mi_disconnect(h);
+ /* Wait 5 seconds and close the auxiliar terminal. */
+ printf("Waiting 5 seconds\n");
+ //sleep(5);
+ gmi_end_aux_term(xterm_tty);
+
+ return 0;
+}
diff --git a/files b/files
new file mode 100644 (file)
index 0000000..fd8cf34
--- /dev/null
+++ b/files
@@ -0,0 +1,16 @@
+libmigdb/doc/*.frt
+libmigdb/doc/*.html
+libmigdb/examples/Makefile
+libmigdb/examples/*.c*
+libmigdb/examples/cmds.txt
+libmigdb/src/Makefile
+libmigdb/src/*.c*
+libmigdb/src/*.h
+libmigdb/files
+libmigdb/DJGPP.why
+libmigdb/GPL-license
+libmigdb/Makefile
+libmigdb/README
+libmigdb/compress.sh
+libmigdb/version.c
+libmigdb/change.log
diff --git a/src/.cvsignore b/src/.cvsignore
new file mode 100644 (file)
index 0000000..a2bee77
--- /dev/null
@@ -0,0 +1,3 @@
+*.dst
+.*.dst
+*.epr*
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..b94d7de
--- /dev/null
@@ -0,0 +1,55 @@
+#!/usr/bin/make
+PREFIX=/usr
+
+all: libmigdb.a
+
+CFLAGS=-O2 -Wall -gstabs+3 -I.
+CXXFLAGS=-O2 -Wall -gstabs+3
+LDLIBS=
+
+connect.o: mi_gdb.h
+
+parse.o: mi_gdb.h
+
+cpp_int.o: mi_gdb.h
+
+prg_control.o: mi_gdb.h
+
+misc.o: mi_gdb.h
+
+breakpoint.o: mi_gdb.h
+
+target_man.o: mi_gdb.h
+
+get_free_vt.o: mi_gdb.h
+
+get_free_pty.o: mi_gdb.h
+
+data_man.o: mi_gdb.h
+
+stack_man.o: mi_gdb.h
+
+symbol_query.o: mi_gdb.h
+
+thread.o: mi_gdb.h
+
+var_obj.o: mi_gdb.h
+
+alloc.o: mi_gdb.h
+
+error.o: mi_gdb.h
+
+libmigdb.a: connect.o parse.o prg_control.o misc.o breakpoint.o target_man.o \
+       get_free_vt.o get_free_pty.o data_man.o stack_man.o symbol_query.o \
+       thread.o var_obj.o alloc.o error.o cpp_int.o
+       ar rcs $@ $^
+
+clean:
+       -@rm *.o *.a 2> /dev/null
+
+install:
+       install -d -m 755 $(PREFIX)/lib
+       install -m 644 libmigdb.a $(PREFIX)/lib
+       install -d -m 755 $(PREFIX)/include
+       install -m 644 mi_gdb.h $(PREFIX)/include
+
diff --git a/src/alloc.c b/src/alloc.c
new file mode 100644 (file)
index 0000000..9e1ffa7
--- /dev/null
@@ -0,0 +1,308 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Allocator.
+  Comments:
+  Most alloc/free routines are here. Free routines must accept NULL
+pointers. Alloc functions must set mi_error.@p
+  
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+void *mi_calloc(size_t count, size_t sz)
+{
+ void *res=calloc(count,sz);
+ if (!res)
+    mi_error=MI_OUT_OF_MEMORY;
+ return res;
+}
+
+void *mi_calloc1(size_t sz)
+{
+ return mi_calloc(1,sz);
+}
+
+char *mi_malloc(size_t sz)
+{
+ char *res=malloc(sz);
+ if (!res)
+    mi_error=MI_OUT_OF_MEMORY;
+ return res;
+}
+
+mi_results *mi_alloc_results(void)
+{
+ return (mi_results *)mi_calloc1(sizeof(mi_results));
+}
+
+mi_output *mi_alloc_output(void)
+{
+ return (mi_output *)mi_calloc1(sizeof(mi_output));
+}
+
+mi_frames *mi_alloc_frames(void)
+{
+ return (mi_frames *)mi_calloc1(sizeof(mi_frames));
+}
+
+mi_gvar *mi_alloc_gvar(void)
+{
+ return (mi_gvar *)mi_calloc1(sizeof(mi_gvar));
+}
+
+mi_gvar_chg *mi_alloc_gvar_chg(void)
+{
+ return (mi_gvar_chg *)mi_calloc1(sizeof(mi_gvar_chg));
+}
+
+mi_bkpt *mi_alloc_bkpt(void)
+{
+ mi_bkpt *b=(mi_bkpt *)mi_calloc1(sizeof(mi_bkpt));
+ if (b)
+   {
+    b->thread=-1;
+    b->ignore=-1;
+   }
+ return b;
+}
+
+mi_wp *mi_alloc_wp(void)
+{
+ return (mi_wp *)mi_calloc1(sizeof(mi_wp));
+}
+
+mi_stop *mi_alloc_stop(void)
+{
+ return (mi_stop *)mi_calloc1(sizeof(mi_stop));
+}
+
+mi_asm_insns *mi_alloc_asm_insns(void)
+{
+ return (mi_asm_insns *)mi_calloc1(sizeof(mi_asm_insns));
+}
+
+mi_asm_insn *mi_alloc_asm_insn(void)
+{
+ return (mi_asm_insn *)mi_calloc1(sizeof(mi_asm_insn));
+}
+
+mi_chg_reg *mi_alloc_chg_reg(void)
+{
+ return (mi_chg_reg *)mi_calloc1(sizeof(mi_chg_reg));
+}
+
+/*****************************************************************************
+  Free functions
+*****************************************************************************/
+
+void mi_free_frames(mi_frames *f)
+{
+ mi_frames *aux;
+
+ while (f)
+   {
+    free(f->func);
+    free(f->file);
+    free(f->from);
+    mi_free_results(f->args);
+    aux=f->next;
+    free(f);
+    f=aux;
+   }
+}
+
+void mi_free_bkpt(mi_bkpt *b)
+{
+ mi_bkpt *aux;
+
+ while (b)
+   {
+    free(b->func);
+    free(b->file);
+    free(b->file_abs);
+    free(b->cond);
+    aux=b->next;
+    free(b);
+    b=aux;
+   }
+}
+
+void mi_free_gvar(mi_gvar *v)
+{
+ mi_gvar *aux;
+
+ while (v)
+   {
+    free(v->name);
+    free(v->type);
+    free(v->exp);
+    free(v->value);
+    if (v->numchild && v->child)
+       mi_free_gvar(v->child);
+    aux=v->next;
+    free(v);
+    v=aux;
+   }
+}
+
+void mi_free_gvar_chg(mi_gvar_chg *p)
+{
+ mi_gvar_chg *aux;
+
+ while (p)
+   {
+    free(p->name);
+    free(p->new_type);
+    aux=p->next;
+    free(p);
+    p=aux;
+   }
+}
+
+void mi_free_results_but(mi_results *r, mi_results *no)
+{
+ mi_results *aux;
+
+ while (r)
+   {
+    if (r==no)
+      {
+       aux=r->next;
+       r->next=NULL;
+       r=aux;
+      }
+    else
+      {
+       free(r->var);
+       switch (r->type)
+         {
+          case t_const:
+               free(r->v.cstr);
+               break;
+          case t_tuple:
+          case t_list:
+               mi_free_results_but(r->v.rs,no);
+               break;
+         }
+       aux=r->next;
+       free(r);
+       r=aux;
+      }
+   }
+}
+
+void mi_free_results(mi_results *r)
+{
+ mi_free_results_but(r,NULL);
+}
+
+void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r)
+{
+ mi_output *aux;
+
+ while (r)
+   {
+    if (r==no)
+      {
+       aux=r->next;
+       r->next=NULL;
+       r=aux;
+      }
+    else
+      {
+       if (r->c)
+          mi_free_results_but(r->c,no_r);
+       aux=r->next;
+       free(r);
+       r=aux;
+      }
+   }
+}
+
+void mi_free_output(mi_output *r)
+{
+ mi_free_output_but(r,NULL,NULL);
+}
+
+void mi_free_stop(mi_stop *s)
+{
+ if (!s)
+    return;
+ mi_free_frames(s->frame);
+ mi_free_wp(s->wp);
+ free(s->wp_old);
+ free(s->wp_val);
+ free(s->gdb_result_var);
+ free(s->return_value);
+ free(s->signal_name);
+ free(s->signal_meaning);
+ free(s);
+}
+
+void mi_free_wp(mi_wp *wp)
+{
+ mi_wp *aux;
+ while (wp)
+   {
+    free(wp->exp);
+    aux=wp->next;
+    free(wp);
+    wp=aux;
+   }
+}
+
+void mi_free_asm_insns(mi_asm_insns *i)
+{
+ mi_asm_insns *aux;
+
+ while (i)
+   {
+    free(i->file);
+    mi_free_asm_insn(i->ins);
+    aux=i->next;
+    free(i);
+    i=aux;
+   }
+}
+
+void mi_free_asm_insn(mi_asm_insn *i)
+{
+ mi_asm_insn *aux;
+
+ while (i)
+   {
+    free(i->func);
+    free(i->inst);
+    aux=i->next;
+    free(i);
+    i=aux;
+   }
+}
+
+/*void mi_free_charp_list(char **l)
+{
+ char **c=l;
+ while (c)
+   {
+    free(*c);
+    c++;
+   }
+ free(l);
+}*/
+
+void mi_free_chg_reg(mi_chg_reg *r)
+{
+ mi_chg_reg *aux;
+ while (r)
+   {
+    free(r->val);
+    free(r->name);
+    aux=r->next;
+    free(r);
+    r=aux;
+   }
+}
+
diff --git a/src/breakpoint.c b/src/breakpoint.c
new file mode 100644 (file)
index 0000000..645c274
--- /dev/null
@@ -0,0 +1,265 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Breakpoint table commands.
+  Comments:
+  GDB/MI commands for the "Breakpoint Table Commands" section.@p
+
+@<pre>
+gdb command:          Implemented?
+
+-break-after          Yes
+-break-condition      Yes
+-break-delete         Yes
+-break-disable        Yes
+-break-enable         Yes
+-break-info           N.A. (info break NUMBER) (*)
+-break-insert         Yes
+-break-list           No (*)
+-break-watch          Yes
+@</pre>
+
+(*) I think the program should keep track of the breakpoints, so it will
+be implemented when I have more time.@p
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_break_insert_fl(mi_h *h, const char *file, int line)
+{
+ mi_send(h,"-break-insert %s:%d\n",file,line);
+}
+
+void mi_break_insert(mi_h *h, int temporary, int hard_assist,
+                     const char *cond, int count, int thread,
+                     const char *where)
+{
+ char s_count[32];
+ char s_thread[32];
+
+ if (count>=0)
+    snprintf(s_count,32,"%d",count);
+ if (thread>=0)
+    snprintf(s_thread,32,"%d",thread);
+ if (cond)
+    // Conditions may contain spaces, in fact, if they don't gdb will add
+    // them after parsing. Enclosing the expression with "" solves the
+    // problem.
+    mi_send(h,"-break-insert %s %s -c \"%s\" %s %s %s %s %s\n",
+            temporary   ? "-t" : "",
+            hard_assist ? "-h" : "",
+            cond,
+            count>=0    ? "-i" : "", count>=0  ? s_count  : "",
+            thread>=0   ? "-p" : "", thread>=0 ? s_thread : "",
+            where);
+ else
+    mi_send(h,"-break-insert %s %s %s %s %s %s %s\n",
+            temporary   ? "-t" : "",
+            hard_assist ? "-h" : "",
+            count>=0    ? "-i" : "", count>=0  ? s_count  : "",
+            thread>=0   ? "-p" : "", thread>=0 ? s_thread : "",
+            where);
+}
+
+void mi_break_insert_flf(mi_h *h, const char *file, int line, int temporary,
+                         int hard_assist, const char *cond, int count,
+                         int thread)
+{
+ char s_count[32];
+ char s_thread[32];
+
+ if (count>=0)
+    snprintf(s_count,32,"%d",count);
+ if (thread>=0)
+    snprintf(s_thread,32,"%d",thread);
+ mi_send(h,"-break-insert %s %s %s %s %s %s %s %s %s:%d\n",
+         temporary   ? "-t" : "",
+         hard_assist ? "-h" : "",
+         cond        ? "-c" : "", cond      ? cond     : "",
+         count>=0    ? "-i" : "", count>=0  ? s_count  : "",
+         thread>=0   ? "-p" : "", thread>=0 ? s_thread : "",
+         file,line);
+}
+
+void mi_break_delete(mi_h *h, int number)
+{
+ mi_send(h,"-break-delete %d\n",number);
+}
+
+void mi_break_after(mi_h *h, int number, int count)
+{
+ mi_send(h,"-break-after %d %d\n",number,count);
+}
+
+void mi_break_condition(mi_h *h, int number, const char *condition)
+{
+ mi_send(h,"-break-condition %d %s\n",number,condition);
+}
+
+void mi_break_enable(mi_h *h, int number)
+{
+ mi_send(h,"-break-enable %d\n",number);
+}
+
+void mi_break_disable(mi_h *h, int number)
+{
+ mi_send(h,"-break-disable %d\n",number);
+}
+
+void mi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp)
+{
+ if (mode==wm_write)
+    mi_send(h,"-break-watch \"%s\"\n",exp);
+ else
+    mi_send(h,"-break-watch -%c \"%s\"\n",mode==wm_rw ? 'a' : 'r',exp);
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  Insert a breakpoint at file:line.
+
+  Command: -break-insert file:line
+  Return: A new mi_bkpt structure with info about the breakpoint. NULL on
+error.
+  
+***************************************************************************/
+
+mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line)
+{
+ mi_break_insert_fl(h,file,line);
+ return mi_res_bkpt(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Insert a breakpoint, all available options.
+  
+  Command: -break-insert
+  Return: A new mi_bkpt structure with info about the breakpoint. NULL on
+error.
+  
+***************************************************************************/
+
+mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
+                               const char *cond, int count, int thread,
+                               const char *where)
+{
+ mi_break_insert(h,temporary,hard_assist,cond,count,thread,where);
+ return mi_res_bkpt(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Insert a breakpoint, all available options.
+  
+  Command: -break-insert [ops] file:line
+  Return: A new mi_bkpt structure with info about the breakpoint. NULL on
+error.
+  
+***************************************************************************/
+
+mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
+                                  int temporary, int hard_assist,
+                                  const char *cond, int count, int thread)
+{
+ mi_break_insert_flf(h,file,line,temporary,hard_assist,cond,count,thread);
+ return mi_res_bkpt(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Remove a breakpoint.
+
+  Command: -break-delete
+  Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
+console.
+  
+***************************************************************************/
+
+int gmi_break_delete(mi_h *h, int number)
+{
+ mi_break_delete(h,number);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Modify the "ignore" count for a breakpoint.
+
+  Command: -break-after
+  Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
+console.
+  
+***************************************************************************/
+
+int gmi_break_set_times(mi_h *h, int number, int count)
+{
+ mi_break_after(h,number,count);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Associate a condition with the breakpoint.
+
+  Command: -break-condition
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_break_set_condition(mi_h *h, int number, const char *condition)
+{
+ mi_break_condition(h,number,condition);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Enable or disable a breakpoint.
+
+  Command: -break-enable + -break-disable
+  Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
+console.
+  
+***************************************************************************/
+
+int gmi_break_state(mi_h *h, int number, int enable)
+{
+ if (enable)
+    mi_break_enable(h,number);
+ else
+    mi_break_disable(h,number);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Set a watchpoint. It doesn't work for remote targets!
+
+  Command: -break-watch
+  Return: A new mi_wp structure with info about the watchpoint. NULL on
+error.
+  
+***************************************************************************/
+
+mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp)
+{
+ mi_break_watch(h,mode,exp);
+ return mi_res_wp(h);
+}
+
diff --git a/src/connect.c b/src/connect.c
new file mode 100644 (file)
index 0000000..319be6f
--- /dev/null
@@ -0,0 +1,887 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004-2009 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Connect.
+  Comments:
+  This module handles the dialog with gdb, including starting and stopping
+gdb.@p
+
+GDB Bug workaround for "file -readnow": I tried to workaround a bug using
+it but looks like this option also have bugs!!!! so I have to use the
+command line option --readnow.
+It also have a bug!!!! when the binary is changed and gdb must reload it
+this option is ignored. So it looks like we have no solution but 3 gdb bugs
+in a row.
+
+***************************************************************************/
+
+#define _GNU_SOURCE
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include "mi_gdb.h"
+
+#ifndef TEMP_FAILURE_RETRY
+ #define TEMP_FAILURE_RETRY(a) (a)
+#endif
+
+int mi_error=MI_OK;
+char *mi_error_from_gdb=NULL;
+static char *gdb_exe=NULL;
+static char *xterm_exe=NULL;
+static char *gdb_start=NULL;
+static char *gdb_conn=NULL;
+static char *main_func=NULL;
+static char  disable_psym_search_workaround=0;
+
+mi_h *mi_alloc_h()
+{
+ mi_h *h=(mi_h *)calloc(1,sizeof(mi_h));
+ if (!h)
+   {
+    mi_error=MI_OUT_OF_MEMORY;
+    return NULL;
+   }
+ h->to_gdb[0]=h->to_gdb[1]=h->from_gdb[0]=h->from_gdb[1]=-1;
+ h->pid=-1;
+ return h;
+}
+
+int mi_check_running_pid(pid_t pid)
+{
+ int status;
+
+ if (pid<=0)
+    return 0;
+ /* If waitpid returns the number of our child means it communicated
+    to as a termination status. */
+ if (waitpid(pid,&status,WNOHANG)==pid)
+   {
+    pid=0;
+    return 0;
+   }
+ return 1;
+}
+
+int mi_check_running(mi_h *h)
+{
+ return !h->died && mi_check_running_pid(h->pid);
+}
+
+void mi_kill_child(pid_t pid)
+{
+ kill(pid,SIGTERM);
+ usleep(100000);
+ if (mi_check_running_pid(pid))
+   {
+    int status;
+    kill(pid,SIGKILL);
+    waitpid(pid,&status,0);
+   }
+}
+
+void mi_free_h(mi_h **handle)
+{
+ mi_h *h=*handle;
+ if (h->to_gdb[0]>=0)
+    close(h->to_gdb[0]);
+ if (h->to)
+    fclose(h->to);
+ else if (h->to_gdb[1]>=0)
+    close(h->to_gdb[1]);
+ if (h->from)
+    fclose(h->from);
+ else if (h->from_gdb[0]>=0)
+    close(h->from_gdb[0]);
+ if (h->from_gdb[1]>=0)
+    close(h->from_gdb[1]);
+ if (mi_check_running(h))
+   {/* GDB is running! */
+    mi_kill_child(h->pid);
+   }
+ if (h->line)
+    free(h->line);
+ mi_free_output(h->po);
+ free(h->catched_console);
+ free(h);
+ *handle=NULL;
+}
+
+void mi_set_nonblk(int h)
+{
+ int flf;
+ flf=fcntl(h,F_GETFL,0);
+ flf=flf | O_NONBLOCK;
+ fcntl(h,F_SETFL,flf);
+}
+
+int mi_getline(mi_h *h)
+{
+ char c;
+
+ while (read(h->from_gdb[0],&c,1)==1)
+   {
+    if (h->lread>=h->llen)
+      {
+       h->llen=h->lread+128;
+       h->line=(char *)realloc(h->line,h->llen);
+       if (!h->line)
+         {
+          h->llen=0;
+          h->lread=0;
+          return -1;
+         }
+      }
+    if (c=='\n')
+      {
+       int ret=h->lread;
+       h->line[ret]=0;
+       h->lread=0;
+       return ret;
+      }
+    if (c!='\r')
+      {
+       h->line[h->lread]=c;
+       h->lread++;
+      }
+   }
+ return 0;
+}
+
+char *get_cstr(mi_output *o)
+{
+ if (!o->c || o->c->type!=t_const)
+    return NULL;
+ return o->c->v.cstr;
+}
+
+int mi_get_response(mi_h *h)
+{
+ int l=mi_getline(h);
+ if (!l)
+    return 0;
+
+ if (h->from_gdb_echo)
+    h->from_gdb_echo(h->line,h->from_gdb_echo_data);
+ if (strncmp(h->line,"(gdb)",5)==0)
+   {/* End of response. */
+    return 1;
+   }
+ else
+   {/* Add to the response. */
+    mi_output *o;
+    int add=1, is_exit=0;
+    o=mi_parse_gdb_output(h->line);
+
+    if (!o)
+       return 0;
+    /* Tunneled streams callbacks. */
+    if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_STREAM)
+      {
+       char *aux;
+       add=0;
+       switch (o->sstype)
+         {
+          case MI_SST_CONSOLE:
+               aux=get_cstr(o);
+               if (h->console)
+                  h->console(aux,h->console_data);
+               if (h->catch_console && aux)
+                 {
+                  h->catch_console--;
+                  if (!h->catch_console)
+                    {
+                     free(h->catched_console);
+                     h->catched_console=strdup(aux);
+                    }
+                 }
+               break;
+          case MI_SST_TARGET:
+               /* This one seems to be useless. */
+               if (h->target)
+                  h->target(get_cstr(o),h->target_data);
+               break;
+          case MI_SST_LOG:
+               if (h->log)
+                  h->log(get_cstr(o),h->log_data);
+               break;
+         }
+      }
+    else if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_ASYNC)
+      {
+       if (h->async)
+          h->async(o,h->async_data);
+      }
+    else if (o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_ERROR)
+      {/* Error from gdb, record it. */
+       mi_error=MI_FROM_GDB;
+       free(mi_error_from_gdb);
+       mi_error_from_gdb=NULL;
+       if (o->c && strcmp(o->c->var,"msg")==0 && o->c->type==t_const)
+          mi_error_from_gdb=strdup(o->c->v.cstr);
+      }
+    is_exit=(o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_EXIT);
+    /* Add to the list of responses. */
+    if (add)
+      {
+       if (h->last)
+          h->last->next=o;
+       else
+          h->po=o;
+       h->last=o;
+      }
+    else
+       mi_free_output(o);
+    /* Exit RR means gdb exited, we won't get a new prompt ;-) */
+    if (is_exit)
+       return 1;
+   }
+
+ return 0;
+}
+
+mi_output *mi_retire_response(mi_h *h)
+{
+ mi_output *ret=h->po;
+ h->po=h->last=NULL;
+ return ret;
+}
+
+mi_output *mi_get_response_blk(mi_h *h)
+{
+ int r;
+ /* Sometimes gdb dies. */
+ if (!mi_check_running(h))
+   {
+    h->died=1;
+    mi_error=MI_GDB_DIED;
+    return NULL;
+   }
+ do
+   {
+    if (1)
+      {
+       /*
+        That's a must. If we just keep trying to read and failing things
+        become really sloooowwww. Instead we try and if it fails we wait
+        until something is available.
+        TODO: Implement something with the time out, a callback to ask the
+        application is we have to wait or not could be a good thing.
+       */
+       fd_set set;
+       struct timeval timeout;
+       int ret;
+
+       r=mi_get_response(h);
+       if (r)
+          return mi_retire_response(h);
+
+       FD_ZERO(&set);
+       FD_SET(h->from_gdb[0],&set);
+       timeout.tv_sec=h->time_out;
+       timeout.tv_usec=0;
+       ret=TEMP_FAILURE_RETRY(select(FD_SETSIZE,&set,NULL,NULL,&timeout));
+       if (!ret)
+         {
+          if (!mi_check_running(h))
+            {
+             h->died=1;
+             mi_error=MI_GDB_DIED;
+             return NULL;
+            }
+          if (h->time_out_cb)
+             ret=h->time_out_cb(h->time_out_cb_data);
+          if (!ret)
+            {
+             mi_error=MI_GDB_TIME_OUT;
+             return NULL;
+            }
+         }
+      }
+    else
+      {
+       r=mi_get_response(h);
+       if (r)
+          return mi_retire_response(h);
+       else
+          usleep(100);
+      }
+   }
+ while (!r);
+
+ return NULL;
+}
+
+void mi_send_commands(mi_h *h, const char *file)
+{
+ FILE *f;
+ char b[PATH_MAX];
+
+ //printf("File: %s\n",file);
+ if (!file)
+    return;
+ f=fopen(file,"rt");
+ if (!f)
+    return;
+ while (!feof(f))
+   {
+    if (fgets(b,PATH_MAX,f))
+      {
+       //printf("Send: %s\n",b);
+       mi_send(h,b);
+       mi_res_simple_done(h);
+      }
+   }
+ fclose(f);
+}
+
+void mi_send_target_commands(mi_h *h)
+{
+ mi_send_commands(h,gdb_conn);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Connect to a local copy of gdb. Note that the mi_h structure is something
+similar to a "FILE *" for stdio.
+  
+  Return: A new mi_h structure or NULL on error.
+  
+***************************************************************************/
+
+mi_h *mi_connect_local()
+{
+ mi_h *h;
+ const char *gdb=mi_get_gdb_exe();
+
+ /* Start without error. */
+ mi_error=MI_OK;
+ /* Verify we have a GDB binary. */
+ if (access(gdb,X_OK))
+   {
+    mi_error=MI_MISSING_GDB;
+    return NULL;
+   }
+ /* Alloc the handle structure. */
+ h=mi_alloc_h();
+ if (!h)
+    return h;
+ h->time_out=MI_DEFAULT_TIME_OUT;
+ /* Create the pipes to connect with the child. */
+ if (pipe(h->to_gdb) || pipe(h->from_gdb))
+   {
+    mi_error=MI_PIPE_CREATE;
+    mi_free_h(&h);
+    return NULL;
+   }
+ mi_set_nonblk(h->to_gdb[1]);
+ mi_set_nonblk(h->from_gdb[0]);
+ /* Associate streams to the file handles. */
+ h->to=fdopen(h->to_gdb[1],"w");
+ h->from=fdopen(h->from_gdb[0],"r");
+ if (!h->to || !h->from)
+   {
+    mi_error=MI_PIPE_CREATE;
+    mi_free_h(&h);
+    return NULL;
+   }
+ /* Create the child. */
+ h->pid=fork();
+ if (h->pid==0)
+   {/* We are the child. */
+    char *argv[5];
+    /* Connect stdin/out to the pipes. */
+    dup2(h->to_gdb[0],STDIN_FILENO);
+    dup2(h->from_gdb[1],STDOUT_FILENO);
+    /* Pass the control to gdb. */
+    argv[0]=(char *)gdb; /* Is that OK? */
+    argv[1]="--interpreter=mi";
+    argv[2]="--quiet";
+    argv[3]=disable_psym_search_workaround ? 0 : "--readnow";
+    argv[4]=0;
+    execvp(argv[0],argv);
+    /* We get here only if exec failed. */
+    _exit(127);
+   }
+ /* We are the parent. */
+ if (h->pid==-1)
+   {/* Fork failed. */
+    mi_error=MI_FORK;
+    mi_free_h(&h);
+    return NULL;
+   }
+ if (!mi_check_running(h))
+   {
+    mi_error=MI_DEBUGGER_RUN;
+    mi_free_h(&h);
+    return NULL;
+   }
+ /* Wait for the prompt. */
+ mi_get_response_blk(h);
+ /* Send the start-up commands */
+ mi_send_commands(h,gdb_start);
+
+ return h;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Close connection. You should ask gdb to quit first @x{gmi_gdb_exit}.
+  
+***************************************************************************/
+
+void mi_disconnect(mi_h *h)
+{
+ mi_free_h(&h);
+ free(mi_error_from_gdb);
+ mi_error_from_gdb=NULL;
+}
+
+void mi_set_console_cb(mi_h *h, stream_cb cb, void *data)
+{
+ h->console=cb;
+ h->console_data=data;
+}
+
+void mi_set_target_cb(mi_h *h, stream_cb cb, void *data)
+{
+ h->target=cb;
+ h->target_data=data;
+}
+
+void mi_set_log_cb(mi_h *h, stream_cb cb, void *data)
+{
+ h->log=cb;
+ h->log_data=data;
+}
+
+stream_cb mi_get_console_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->console_data;
+ return h->console;
+}
+
+stream_cb mi_get_target_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->target_data;
+ return h->target;
+}
+
+stream_cb mi_get_log_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->log_data;
+ return h->log;
+}
+
+void mi_set_async_cb(mi_h *h, async_cb cb, void *data)
+{
+ h->async=cb;
+ h->async_data=data;
+}
+
+async_cb mi_get_async_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->async_data;
+ return h->async;
+}
+
+void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data)
+{
+ h->to_gdb_echo=cb;
+ h->to_gdb_echo_data=data;
+}
+
+void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data)
+{
+ h->from_gdb_echo=cb;
+ h->from_gdb_echo_data=data;
+}
+
+stream_cb mi_get_to_gdb_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->to_gdb_echo_data;
+ return h->to_gdb_echo;
+}
+
+stream_cb mi_get_from_gdb_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->from_gdb_echo_data;
+ return h->from_gdb_echo;
+}
+
+void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data)
+{
+ h->time_out_cb=cb;
+ h->time_out_cb_data=data;
+}
+
+tm_cb mi_get_time_out_cb(mi_h *h, void **data)
+{
+ if (data)
+    *data=h->time_out_cb_data;
+ return h->time_out_cb;
+}
+
+void mi_set_time_out(mi_h *h, int to)
+{
+ h->time_out=to;
+}
+
+int mi_get_time_out(mi_h *h)
+{
+ return h->time_out;
+}
+
+int mi_send(mi_h *h, const char *format, ...)
+{
+ int ret;
+ char *str;
+ va_list argptr;
+
+ if (h->died)
+    return 0;
+
+ va_start(argptr,format);
+ ret=vasprintf(&str,format,argptr);
+ va_end(argptr);
+ fputs(str,h->to);
+ fflush(h->to);
+ if (h->to_gdb_echo)
+    h->to_gdb_echo(str,h->to_gdb_echo_data);
+ free(str);
+
+ return ret;
+}
+
+void mi_clean_up_globals()
+{
+ free(gdb_exe);
+ gdb_exe=NULL;
+ free(xterm_exe);
+ xterm_exe=NULL;
+ free(gdb_start);
+ gdb_start=NULL;
+ free(gdb_conn);
+ gdb_conn=NULL;
+ free(main_func);
+ main_func=NULL;
+}
+
+void mi_register_exit()
+{
+ static int registered=0;
+ if (!registered)
+   {
+    registered=1;
+    atexit(mi_clean_up_globals);
+   }
+}
+
+void mi_set_gdb_exe(const char *name)
+{
+ free(gdb_exe);
+ gdb_exe=name ? strdup(name) : NULL;
+ mi_register_exit();
+}
+
+void mi_set_gdb_start(const char *name)
+{
+ free(gdb_start);
+ gdb_start=name ? strdup(name) : NULL;
+ mi_register_exit();
+}
+
+void mi_set_gdb_conn(const char *name)
+{
+ free(gdb_conn);
+ gdb_conn=name ? strdup(name) : NULL;
+ mi_register_exit();
+}
+
+static
+char *mi_search_in_path(const char *file)
+{
+ char *path, *pt, *r;
+ char test[PATH_MAX];
+ struct stat st;
+
+ path=getenv("PATH");
+ if (!path)
+    return NULL;
+ pt=strdup(path);
+ r=strtok(pt,":");
+ while (r)
+   {
+    strcpy(test,r);
+    strcat(test,"/");
+    strcat(test,file);
+    if (stat(test,&st)==0 && S_ISREG(st.st_mode))
+      {
+       free(pt);
+       return strdup(test);
+      }
+    r=strtok(NULL,":");
+   }
+ free(pt);
+ return NULL;
+}
+
+const char *mi_get_gdb_exe()
+{
+ if (!gdb_exe)
+   {/* Look for gdb in path */
+    gdb_exe=mi_search_in_path("gdb");
+    if (!gdb_exe)
+       return "/usr/bin/gdb";
+   }
+ return gdb_exe;
+}
+
+const char *mi_get_gdb_start()
+{
+ return gdb_start;
+}
+
+const char *mi_get_gdb_conn()
+{
+ return gdb_conn;
+}
+
+void mi_set_xterm_exe(const char *name)
+{
+ free(xterm_exe);
+ xterm_exe=name ? strdup(name) : NULL;
+ mi_register_exit();
+}
+
+const char *mi_get_xterm_exe()
+{
+ if (!xterm_exe)
+   {/* Look for xterm in path */
+    xterm_exe=mi_search_in_path("xterm");
+    if (!xterm_exe)
+       return "/usr/bin/X11/xterm";
+   }
+ return xterm_exe;
+}
+
+void mi_set_main_func(const char *name)
+{
+ free(main_func);
+ main_func=name ? strdup(name) : NULL;
+ mi_register_exit();
+}
+
+const char *mi_get_main_func()
+{
+ if (main_func)
+    return main_func;
+ return "main";
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Opens a new xterm to be used by the child process to debug.
+  
+  Return: A new mi_aux_term structure, you can use @x{gmi_end_aux_term} to
+release it.
+  
+***************************************************************************/
+
+mi_aux_term *gmi_start_xterm()
+{
+ char nsh[14]="/tmp/shXXXXXX";
+ char ntt[14]="/tmp/ttXXXXXX";
+ const char *xterm;
+ struct stat st;
+ int hsh, htt=-1;
+ mi_aux_term *res=NULL;
+ FILE *f;
+ pid_t pid;
+ char buf[PATH_MAX];
+
+ /* Verify we have an X terminal. */
+ xterm=mi_get_xterm_exe();
+ if (access(xterm,X_OK))
+   {
+    mi_error=MI_MISSING_XTERM;
+    return NULL;
+   }
+
+ /* Create 2 temporals. */
+ hsh=mkstemp(nsh);
+ if (hsh==-1)
+   {
+    mi_error=MI_CREATE_TEMPORAL;
+    return NULL;
+   }
+ htt=mkstemp(ntt);
+ if (htt==-1)
+   {
+    close(hsh);
+    unlink(nsh);
+    mi_error=MI_CREATE_TEMPORAL;
+    return NULL;
+   }
+ close(htt);
+ /* Create the script. */
+ f=fdopen(hsh,"w");
+ if (!f)
+   {
+    close(hsh);
+    unlink(nsh);
+    unlink(ntt);
+    mi_error=MI_CREATE_TEMPORAL;
+    return NULL;
+   }
+ fprintf(f,"#!/bin/sh\n");
+ fprintf(f,"tty > %s\n",ntt);
+ fprintf(f,"rm %s\n",nsh);
+ fprintf(f,"sleep 365d\n");
+ fclose(f);
+ /* Spawn xterm. */
+ /* Create the child. */
+ pid=fork();
+ if (pid==0)
+   {/* We are the child. */
+    char *argv[5];
+    /* Pass the control to gdb. */
+    argv[0]=(char *)mi_get_xterm_exe(); /* Is that ok? */
+    argv[1]="-e";
+    argv[2]="/bin/sh";
+    argv[3]=nsh;
+    argv[4]=0;
+    execvp(argv[0],argv);
+    /* We get here only if exec failed. */
+    unlink(nsh);
+    unlink(ntt);
+    _exit(127);
+   }
+ /* We are the parent. */
+ if (pid==-1)
+   {/* Fork failed. */
+    unlink(nsh);
+    unlink(ntt);
+    mi_error=MI_FORK;
+    return NULL;
+   }
+ /* Wait until the shell is deleted. */
+ while (stat(nsh,&st)==0)
+   usleep(1000);
+ /* Try to read the tty name. */
+ f=fopen(ntt,"rt");
+ if (f)
+   {
+    if (fgets(buf,PATH_MAX,f))
+      {
+       char *s; /* Strip the \n. */
+       for (s=buf; *s && *s!='\n'; s++);
+       *s=0;
+       res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
+       if (res)
+         {
+          res->pid=pid;
+          res->tty=strdup(buf);
+         }
+      }
+    fclose(f);
+   }
+ unlink(ntt);
+ return res;
+}
+
+void mi_free_aux_term(mi_aux_term *t)
+{
+ if (!t)
+    return;
+ free(t->tty);
+ free(t);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Closes the auxiliar terminal and releases the allocated memory.
+  
+***************************************************************************/
+
+void gmi_end_aux_term(mi_aux_term *t)
+{
+ if (!t)
+    return;
+ if (t->pid!=-1 && mi_check_running_pid(t->pid))
+    mi_kill_child(t->pid);
+ mi_free_aux_term(t);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Forces the MI version. Currently the library can't detect it so you must
+force it manually. GDB 5.x implemented MI v1 and 6.x v2.
+  
+***************************************************************************/
+
+void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
+                      unsigned vMinor)
+{
+ h->version=MI_VERSION2U(vMajor,vMiddle,vMinor);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Dis/Enables the @var{wa} workaround for a bug in gdb.
+
+***************************************************************************/
+
+void mi_set_workaround(unsigned wa, int enable)
+{
+ switch (wa)
+   {
+    case MI_PSYM_SEARCH:
+         disable_psym_search_workaround=enable ? 0 : 1;
+         break;
+   }
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Finds if the @var{wa} workaround for a bug in gdb is enabled.
+  
+  Return: !=0 if enabled.
+  
+***************************************************************************/
+
+int mi_get_workaround(unsigned wa)
+{
+ switch (wa)
+   {
+    case MI_PSYM_SEARCH:
+         return disable_psym_search_workaround==0;
+   }
+ return 0;
+}
+
diff --git a/src/cpp_int.cc b/src/cpp_int.cc
new file mode 100644 (file)
index 0000000..815d6f7
--- /dev/null
@@ -0,0 +1,1123 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004-2007 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: C++ Interface.
+  Comments:
+  Implements a very simple (naive ;-) C++ wrapper.@p
+
+***************************************************************************/
+
+#include <string.h>
+#include <limits.h>
+#include "mi_gdb.h"
+
+/**[txh]********************************************************************
+
+  Description:
+  Initializes a debugger object. It starts in the "disconnected" state.
+Use @x{::Connect} after it.
+  
+***************************************************************************/
+
+MIDebugger::MIDebugger()
+{
+ state=disconnected;
+ h=NULL;
+ aux_tty=NULL;
+ waitingTempBkpt=0;
+ targetEndian=enUnknown;
+ targetArch=arUnknown;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  This is the destructor for the class. It tries to change the state to
+"disconnected" doing the needed actions.
+  
+***************************************************************************/
+
+MIDebugger::~MIDebugger()
+{
+ if (state==running)
+   {
+    Stop();
+    mi_stop *rs;
+    // TODO: Some kind of time-out
+    while (!Poll(rs));
+    mi_free_stop(rs);
+    state=stopped;
+   }
+ if (state==stopped)
+   {
+    Kill();
+    state=target_specified;
+   }
+ if (state==target_specified)
+   {
+    TargetUnselect();
+    state=connected;
+   }
+ if (state==connected)
+    Disconnect();
+ // Here state==disconnected
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Connects to gdb. Currently only local connections are supported, that's
+a gdb limitation. Call it when in "unconnected" state, on success it will
+change to the "connected" state.  After it you should call one of the
+SelectTarget members. @x{::SelectTargetX11}, @x{::SelectTargetLinux} or
+@x{::SelectTargetRemote}. To finish the connection use @x{::Disconnect}.
+
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int MIDebugger::Connect(bool )
+{
+ if (state==disconnected)
+   {
+    h=mi_connect_local();
+    if (h!=NULL)
+      {
+       state=connected;
+       return 1;
+      }
+   }
+ return 0;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Finishes the connection to gdb. Call when in "connected" state, on success
+it will change to "disconnected" state. This function first tries to exit
+from gdb and then close the connection. But if gdb fails to exit it will be
+killed.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::Disconnect()
+{
+ if (state==connected)
+   {
+    gmi_gdb_exit(h);
+    mi_disconnect(h);
+    state=disconnected;
+    return 1;
+   }
+ return 0;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Protected member that implements @x{::SelectTargetX11} and
+@x{::SelectTargetLinux}.
+  
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int MIDebugger::SelectTargetTTY(const char *exec, const char *args,
+                                const char *auxtty, dMode m)
+{
+ if (state!=connected)
+    return 0;
+
+ targetEndian=enUnknown;
+ targetArch=arUnknown;
+ mode=m;
+ if (!gmi_set_exec(h,exec,args))
+    return 0;
+
+ const char *tty_name;
+ #ifndef __CYGWIN__
+ if (!auxtty)
+   {
+    aux_tty=m==dmLinux ? gmi_look_for_free_vt() : gmi_start_xterm();
+    if (!aux_tty)
+       return 0;
+    tty_name=aux_tty->tty;
+   }
+ else
+   {
+    tty_name=auxtty;
+   }
+ if (!gmi_target_terminal(h,tty_name))
+    return 0;
+ #else
+ tty_name=NULL;
+ if (!gmi_gdb_set(h,"new-console","on"))
+    return 0;
+ #endif
+
+ state=target_specified;
+ preRun=false;
+ return 1;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Starts a debug session for X11. It opens an xterm console for the program
+to debug and tells gdb which executable to debug and the command line
+options to pass. You can specify an already existing tty console to be used.
+Can be called when the state is "connected". On success will change to the
+"target_specified" state. After it you can use @x{::Run} or use the members
+to define breakpoints and similar stuff. To finish it use
+@x{::TargetUnselect}.
+  
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int MIDebugger::SelectTargetX11(const char *exec, const char *args,
+                                const char *auxtty)
+{
+ return SelectTargetTTY(exec,args,auxtty,dmX11);
+}
+
+
+/**[txh]********************************************************************
+
+  Description:
+  Starts a debug session for Linux console. It selects an empty VT for the
+program to debug and tells gdb which executable to debug and the command line
+options to pass. You can specify an already existing tty console to be used.
+Can be called when the state is "connected". On success will change to the
+"target_specified" state. After it you can use @x{::Run} or use the members
+to define breakpoints and similar stuff. To finish it use
+@x{::TargetUnselect}.
+  
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int MIDebugger::SelectTargetLinux(const char *exec, const char *args,
+                                  const char *auxtty)
+{
+ return SelectTargetTTY(exec,args,auxtty,dmLinux);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Starts a remote session. The other end should be running gdbserver. You
+must specify a local copy of the program to debug with debug info. The remote
+copy can be stripped. The @var{rtype} and @var{rparams} selects the protocol
+and the remote machine. Read gdb docs to know more about the available
+options. If @var{rtype} is omitted "extended-remote" protocol is used.
+Can be called when the state is "connected". On success will change to the
+"target_specified" state. After it you can use @x{::Run} or use the members
+to define breakpoints and similar stuff. To finish it use
+@x{::TargetUnselect}. Note that when gdb uses remote debugging the remote
+program starts running. The @x{::Run} member knows about it.
+  
+  Return: !=0 OK.
+  Example:
+  o->SelectTargetRemote("./exec_file","192.168.1.65:5000");
+  
+***************************************************************************/
+
+int MIDebugger::SelectTargetRemote(const char *exec, const char *rparams,
+                                   const char *rtype, bool download)
+{
+ if (state!=connected)
+    return 0;
+
+ mode=dmRemote;
+ preRun=true;
+ targetEndian=enUnknown;
+ targetArch=arUnknown;
+ if (rtype==NULL)
+    rtype="extended-remote";
+
+ /* Tell gdb to load symbols from the local copy. */
+ int res=download ? gmi_set_exec(h,exec,NULL) : gmi_file_symbol_file(h,exec);
+ if (!res)
+    return 0;
+ /* Select the target */
+ if (!gmi_target_select(h,rtype,rparams))
+    return 0;
+ /* Download the binary */
+ if (download)
+   {
+    if (!gmi_target_download(h))
+       return 0;
+   }
+
+ state=target_specified;
+ return 1;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Starts a local session using an already running process.
+  
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+mi_frames *MIDebugger::SelectTargetPID(const char *exec, int pid)
+{
+ if (state!=connected)
+    return NULL;
+
+ mode=dmPID;
+ preRun=false;
+ targetEndian=enUnknown;
+ targetArch=arUnknown;
+
+ mi_frames *res=gmi_target_attach(h,pid);
+ if (res)
+   {
+    state=stopped;
+
+    /* Tell gdb to load symbols from the local copy. */
+    if (!gmi_file_symbol_file(h,exec))
+      {
+       mi_free_frames(res);
+       return NULL;
+      }
+   }
+
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Used to unselect the current target. When X11 mode it closes the auxiliar
+terminal. For remote debugging it uses "detach". Can be called when in
+"target_specified" state. On success it changes to "connected" state.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::TargetUnselect()
+{
+ switch (mode)
+   {
+    case dmX11:
+    case dmLinux:
+         if (state!=target_specified)
+            return 0;
+         if (aux_tty)
+           {
+            gmi_end_aux_term(aux_tty);
+            aux_tty=NULL;
+           }
+         break;
+    case dmPID:
+    case dmRemote:
+         if (state!=target_specified)
+           {
+            if (state!=stopped || !gmi_target_detach(h))
+               return 0;
+           }
+         break;
+   }
+ state=connected;
+ return 1;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Starts running the program. You should set breakpoint before it. Can be
+called when state is "target_specified". On success will change to "running"
+state. After it you should poll for async responses using @x{::Poll}. The
+program can stop for many reasons asynchronously and also exit. This
+information is known using Poll. You can stop the program using @x{::Stop}.
+  
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int MIDebugger::Run()
+{
+ if (state!=target_specified)
+    return 0;
+
+ int res;
+ if (preRun)
+    res=gmi_exec_continue(h);
+ else
+    res=gmi_exec_run(h);
+ if (res)
+    state=running;
+
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Stops the program execution. GDB sends an interrupt signal to the program.
+Can be called when the state is "running". It won't switch to "stopped"
+state automatically. Instead you must poll for async events and wait for a
+stopped notification. After it you can call @x{::Continue} to resume
+execution.
+  
+  Return: 
+  Example: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::Stop()
+{
+ if (state!=running)
+    return 0;
+ return gmi_exec_interrupt(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Polls gdb looking for async responses. Currently it just looks for
+"stopped" messages. You must call it when the state is "running". But the
+function will poll gdb even if the state isn't "running". When a stopped
+message is received the state changes to stopped or target_specified (the
+last is when we get some exit).
+  
+  Return: !=0 if we got a response. The @var{rs} pointer will point to an
+mi_stop structure if we got it or will be NULL if we didn't.
+  
+***************************************************************************/
+
+int MIDebugger::Poll(mi_stop *&rs)
+{
+ if (state==disconnected || !mi_get_response(h))
+    return 0;
+
+ mi_stop *res=mi_res_stop(h);
+ if (res)
+   {
+    if (res->reason==sr_exited_signalled ||
+        res->reason==sr_exited ||
+        res->reason==sr_exited_normally)
+       // When we use a PID the exit makes it invalid, so we don't have a
+       // valid target to re-run.
+       state=mode==dmPID ? connected : target_specified;
+    else
+       state=stopped;
+    if (res->reason==sr_unknown && waitingTempBkpt)
+      {
+       waitingTempBkpt=0;
+       res->reason=sr_bkpt_hit;
+      }
+   }
+ else
+   {// We got an error. It looks like most async commands returns running even
+    // before they are sure the process is running. Latter we get the real
+    // error. So I'm assuming the program is stopped.
+    // Lamentably -target-exec-status isn't implemented and even in this case
+    // if the program is really running as real async isn't implemented it
+    // will fail anyways.
+    if (state==running)
+       state=stopped;
+   }
+ rs=res;
+ return 1;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Resumes execution after the program "stopped". Can be called when the state
+is stopped. On success will change to "running" state.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::Continue()
+{
+ if (state!=stopped)
+    return 0;
+ int res=gmi_exec_continue(h);
+ if (res)
+    state=running;
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Starts program execution or resumes it. When the state is target_specified
+it calls @x{::Run} otherwise it uses @x{::Continue}. Can be called when the
+state is "target_specified" or "stopped". On success will change to
+"running" state.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::RunOrContinue()
+{
+ if (state==target_specified)
+    return Run();
+ return Continue();
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Kills the program you are debugging. Can be called when the state is
+"stopped" or "running". On success changes the state to "target_specified".
+Note that if you want to restart the program you can just call @x{::Run} and
+if you want to just stop the program call @x{::Stop}.
+
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::Kill()
+{
+ if (state!=stopped && state!=running)
+    return 0;
+ /* GDB/MI doesn't implement it (yet), so we use the regular kill. */
+ /* Ensure confirm is off. */
+ char *prev=gmi_gdb_show(h,"confirm");
+ if (!prev)
+    return 0;
+ if (strcmp(prev,"off"))
+   {
+    if (!gmi_gdb_set(h,"confirm","off"))
+      {
+       free(prev);
+       return 0;
+      }
+   }
+ else
+   {
+    free(prev);
+    prev=NULL;
+   }
+ /* Do the kill. */
+ int res=gmi_exec_kill(h);
+ /* Revert confirm option if needed. */
+ if (prev)
+   {
+    gmi_gdb_set(h,"confirm",prev);
+    free(prev);
+   }
+
+ if (res)
+    state=target_specified;
+
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Inserts a breakpoint at @var{file} and @var{line}. Can be called when the
+state is "stopped" or "target_specified".
+  
+  Return: An mi_bkpt structure or NULL if error.
+  
+***************************************************************************/
+
+mi_bkpt *MIDebugger::Breakpoint(const char *file, int line)
+{
+ if (state!=stopped && state!=target_specified)
+    return NULL;
+ return gmi_break_insert(h,file,line);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Inserts a breakpoint at @var{where}, all options available. Can be called
+when the state is "stopped" or "target_specified".
+  
+  Return: An mi_bkpt structure or NULL if error.
+  
+***************************************************************************/
+
+mi_bkpt *MIDebugger::Breakpoint(const char *where, bool temporary,
+                                const char *cond, int count, int thread,
+                                bool hard_assist)
+{
+ if (state!=stopped && state!=target_specified)
+    return NULL;
+ return gmi_break_insert_full(h,temporary,hard_assist,cond,count,thread,where);
+}
+
+
+const int maxWhere=PATH_MAX+256;
+
+mi_bkpt *MIDebugger::Breakpoint(mi_bkpt *b)
+{
+ if (state!=stopped && state!=target_specified)
+    return NULL;
+
+ char buf[maxWhere];
+ buf[0]=0;
+ switch (b->mode)
+   {
+    case m_file_line:
+         snprintf(buf,maxWhere,"%s:%d",b->file,b->line);
+         break;
+    case m_function:
+         snprintf(buf,maxWhere,"%s",b->func);
+         break;
+    case m_file_function:
+         snprintf(buf,maxWhere,"%s:%s",b->file,b->func);
+         break;
+    case m_address:
+         snprintf(buf,maxWhere,"*%p",b->addr);
+         break;
+   }
+ return Breakpoint(buf,b->disp==d_del,b->cond,b->ignore,b->thread,
+                   b->type==t_hw);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Inserts a breakpoint at @var{file} and @var{line} all options available.
+Can be called when the state is "stopped" or "target_specified".
+  
+  Return: An mi_bkpt structure or NULL if error.
+  
+***************************************************************************/
+
+mi_bkpt *MIDebugger::BreakpointFull(const char *file, int line,
+                                    bool temporary, const char *cond,
+                                    int count, int thread, bool hard_assist)
+{
+ if (state!=stopped && state!=target_specified)
+    return NULL;
+ return gmi_break_insert_full_fl(h,file,line,temporary,hard_assist,cond,
+                                 count,thread);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Removes the specified breakpoint. It doesn't free the structure. Can be
+called when the state is "stopped" or "target_specified".
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::BreakDelete(mi_bkpt *b)
+{
+ if ((state!=stopped && state!=target_specified) || !b)
+    return 0;
+ return gmi_break_delete(h,b->number);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Inserts a watchpoint for the specified expression. Can be called when the
+state is "stopped" or "target_specified".
+  
+  Return: An mi_wp structure or NULL if error.
+  
+***************************************************************************/
+
+mi_wp *MIDebugger::Watchpoint(enum mi_wp_mode mode, const char *exp)
+{
+ if (state!=stopped && state!=target_specified)
+    return NULL;
+ return gmi_break_watch(h,mode,exp);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Removes the specified watchpoint. It doesn't free the structure. Can be
+called when the state is "stopped" or "target_specified".
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::WatchDelete(mi_wp *w)
+{
+ if ((state!=stopped && state!=target_specified) || !w)
+    return 0;
+ return gmi_break_delete(h,w->number);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Puts a temporal breakpoint in main function and starts running. Can be
+called when the state is "target_specified". If successful the state will
+change to "running".
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::RunToMain()
+{
+ if (state!=target_specified)
+    return 0;
+ mi_bkpt *b=Breakpoint(mi_get_main_func(),true);
+ if (!b)
+    return 0;
+ mi_free_bkpt(b);
+ waitingTempBkpt=1;
+ return Run();
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Executes upto the next line, doesn't follow function calls. The @var{inst}
+argument is for assembler. If the state is "target_specified" it will go to
+the first line in the main function. If the state is "stopped" will use the
+next command. If successfully the state will change to "running".
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::StepOver(bool inst)
+{
+ int res=0;
+
+ if (state==target_specified)
+   {// We aren't running
+    // Walk to main
+    return RunToMain();
+   }
+ if (state==stopped)
+   {
+    if (inst)
+       res=gmi_exec_next_instruction(h);
+    else
+       res=gmi_exec_next(h);
+    if (res)
+       state=running;
+   }
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Executes until the specified point. If the state is "target_specified" it
+uses a temporal breakpoint. If the state is "stopped" it uses -exec-until.
+Fails for any other state.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::GoTo(const char *file, int line)
+{
+ int res=0;
+
+ if (state==target_specified)
+   {// We aren't running
+    // Use a temporal breakpoint
+    int l=strlen(file)+32;
+    char buf[l];
+    snprintf(buf,l,"%s:%d",file,line);
+    mi_bkpt *b=Breakpoint(buf,true);
+    if (b)
+      {
+       mi_free_bkpt(b);
+       waitingTempBkpt=1;
+       res=Run();
+      }
+   }
+ else if (state==stopped)
+   {
+    res=gmi_exec_until(h,file,line);
+    if (res)
+       state=running;
+   }
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Executes until the specified point. If the state is "target_specified" it
+uses a temporal breakpoint. If the state is "stopped" it uses -exec-until.
+Fails for any other state.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::GoTo(void *addr)
+{
+ int res=0;
+
+ if (state==target_specified)
+   {// We aren't running
+    // Use a temporal breakpoint
+    char buf[32];
+    snprintf(buf,32,"*%p",addr);
+    mi_bkpt *b=Breakpoint(buf,true);
+    if (b)
+      {
+       mi_free_bkpt(b);
+       waitingTempBkpt=1;
+       res=Run();
+      }
+   }
+ else if (state==stopped)
+   {
+    res=gmi_exec_until_addr(h,addr);
+    if (res)
+       state=running;
+   }
+ return res;
+}
+
+
+/**[txh]********************************************************************
+
+  Description:
+  Resumes execution until the end of the current funtion is reached. Only
+usable when we are in the "stopped" state.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::FinishFun()
+{
+ if (state!=stopped)
+    return 0;
+ int res=gmi_exec_finish(h);
+ if (res)
+    state=running;
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Returns immediately. Only usable when we are in the "stopped" state.
+  
+  Return: !=NULL OK, the returned frame is the current location. That's a
+synchronous function.
+  
+***************************************************************************/
+
+mi_frames *MIDebugger::ReturnNow()
+{
+ if (state!=stopped)
+    return 0;
+ return gmi_exec_return(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Returns the current list of frames.
+  
+  Return: !=NULL OK, the list of frames is returned.
+  
+***************************************************************************/
+
+mi_frames *MIDebugger::CallStack(bool args)
+{
+ if (state!=stopped)
+    return 0;
+ mi_frames *fr1=gmi_stack_list_frames(h);
+ if (fr1 && args)
+   {// Get the function arguments
+    mi_frames *fr2=gmi_stack_list_arguments(h,1);
+    if (fr2)
+      {// Transfer them to the other list
+       mi_frames *p=fr1, *p2=fr2;
+       while (p2 && p)
+         {
+          p->args=p2->args;
+          p2->args=NULL;
+          p2=p2->next;
+          p=p->next;
+         }
+       mi_free_frames(fr2);
+      }
+   }
+ return fr1;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Executes upto the next line, it follows function calls. The @var{inst}
+argument is for assembler. If the state is "target_specified" it will go to
+the first line in the main function. If the state is "stopped" will use the
+next command. If successfully the state will change to "running".
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::TraceInto(bool inst)
+{
+ int res=0;
+
+ if (state==target_specified)
+   {// We aren't running
+    // Walk to main
+    return RunToMain();
+   }
+ if (state==stopped)
+   {
+    if (inst)
+       res=gmi_exec_step_instruction(h);
+    else
+       res=gmi_exec_step(h);
+    if (res)
+       state=running;
+   }
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Evaluates the provided expression. If we get an error the error
+description is returned instead. Can't be called if "disconnected" or
+"running".
+  
+  Return: The result of the expression (use free) or NULL.
+  
+***************************************************************************/
+
+char *MIDebugger::EvalExpression(const char *exp)
+{
+ if (state==disconnected ||
+     state==running) // No async :-(
+    return NULL;
+ // Evaluate it
+ mi_error=MI_OK;
+ char *res=gmi_data_evaluate_expression(h,exp);
+ if (!res && mi_error_from_gdb)
+   {// Not valid, return the error
+    res=strdup(mi_error_from_gdb);
+   }
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Modifies the provided expression. If we get an error the error
+description is returned instead. Can't be called if "disconnected" or
+"running".
+  
+  Return: The result of the expression (use free) or NULL.
+  
+***************************************************************************/
+
+char *MIDebugger::ModifyExpression(char *exp, char *newVal)
+{
+ if (state==disconnected ||
+     state==running) // No async :-(
+    return NULL;
+ // Create an assignment
+ int l1=strlen(exp);
+ int l2=strlen(newVal);
+ char b[l1+l2+2], *s=b;
+ memcpy(s,exp,l1);
+ s+=l1;
+ *s='=';
+ memcpy(++s,newVal,l2);
+ s[l2]=0;
+ // Evaluate it
+ char *res=gmi_data_evaluate_expression(h,b);
+ if (!res && mi_error_from_gdb)
+   {// Not valid, return the error
+    res=strdup(mi_error_from_gdb);
+   }
+ return res;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Sends a command to gdb.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::Send(const char *command)
+{
+ if (state==disconnected ||
+     state==running) // No async :-(
+    return 0;
+ // TODO: detect and use -interpreter-exec?
+ mi_send(h,"%s\n",command);
+ return mi_res_simple_done(h);
+}
+
+
+/**[txh]********************************************************************
+
+  Description:
+  Fills the type and value fields of the mi_gvar provided list.
+  
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int MIDebugger::FillTypeVal(mi_gvar *var)
+{
+ while (var)
+   {
+    if (!var->type && !gmi_var_info_type(h,var))
+       return 0;
+    if (!var->value && !gmi_var_evaluate_expression(h,var))
+       return 0;
+    var=var->next;
+   }
+ return 1;
+}
+
+int MIDebugger::FillOneTypeVal(mi_gvar *var)
+{
+ if (!var)
+    return 0;
+
+ int ok=1;
+ if (!var->type && !gmi_var_info_type(h,var))
+   {
+    var->type=strdup("");
+    ok=0;
+   }
+ if (!var->value && !gmi_var_evaluate_expression(h,var))
+   {
+    var->value=strdup("");
+    ok=0;
+   }
+ return ok;
+}
+
+int MIDebugger::AssigngVar(mi_gvar *var, const char *exp)
+{
+ if (state!=stopped)
+    return 0;
+ return gmi_var_assign(h,var,exp);
+}
+
+char *MIDebugger::Show(const char *var)
+{
+ if (state==running || state==disconnected)
+    return 0;
+ // GDB 5.x doesn't reply all in the response record, just to the console :-(
+ h->catch_console=1;
+ if (h->catched_console)
+   {
+    free(h->catched_console);
+    h->catched_console=NULL;
+   }
+ char *res=gmi_gdb_show(h,var);
+ h->catch_console=0;
+ if (!res && h->catched_console)
+   {
+    res=h->catched_console;
+    h->catched_console=NULL;
+   }
+ return res;
+}
+
+MIDebugger::endianType MIDebugger::GetTargetEndian()
+{
+ if (targetEndian!=enUnknown)
+    return targetEndian;
+ if (state!=stopped && state!=target_specified)
+    return enUnknown;
+
+ char *end=Show("endian");
+ if (end)
+   {
+    if (strstr(end,"big"))
+       targetEndian=enBig;
+    else if (strstr(end,"little"))
+       targetEndian=enLittle;
+    free(end);
+   }
+ return targetEndian;
+}
+
+MIDebugger::archType MIDebugger::GetTargetArchitecture()
+{
+ if (targetArch!=arUnknown)
+    return targetArch;
+ if (state!=stopped && state!=target_specified)
+    return arUnknown;
+
+ char *end=Show("architecture");
+ if (end)
+   {
+    if (strstr(end,"i386"))
+       targetArch=arIA32;
+    else if (strstr(end,"sparc"))
+       targetArch=arSPARC;
+    else if (strstr(end,"pic14"))
+       targetArch=arPIC14;
+    else if (strstr(end,"avr"))
+       targetArch=arAVR;
+    free(end);
+   }
+ return targetArch;
+}
+
+int MIDebugger::GetErrorNumberSt()
+{
+ if (mi_error==MI_GDB_DIED)
+   {
+    state=target_specified;
+    TargetUnselect();
+    state=connected;
+    Disconnect();
+   }
+ return mi_error;
+}
+
+int MIDebugger::UpdateRegisters(mi_chg_reg *regs)
+{
+ int updated=0;
+ mi_chg_reg *chg=GetChangedRegisters();
+ if (chg)
+   {
+    mi_chg_reg *r=regs, *c;
+    while (r)
+      {
+       c=chg;
+       while (c && c->reg!=r->reg)
+          c=c->next;
+       if (c)
+         {
+          r->updated=1;
+          free(r->val);
+          r->val=c->val;
+          c->val=NULL;
+          updated++;
+         }
+       else
+          r->updated=0;
+       r=r->next;
+      }
+   }
+ return updated;
+}
+
diff --git a/src/data_man.c b/src/data_man.c
new file mode 100644 (file)
index 0000000..a7e9f11
--- /dev/null
@@ -0,0 +1,241 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Data manipulation.
+  Comments:
+  GDB/MI commands for the "Data manipulation" section.@p
+
+@<pre>
+gdb command:                       Implemented?
+
+-data-disassemble                  Yes
+-data-evaluate-expression          Yes
+-data-list-changed-registers       No
+-data-list-register-names          Yes
+-data-list-register-values         No
+-data-read-memory                  No
+-display-delete                    N.A. (delete display)
+-display-disable                   N.A. (disable display)
+-display-enable                    N.A. (enable display)
+-display-insert                    N.A. (display)
+-display-list                      N.A. (info display)
+-environment-cd                    No
+-environment-directory             Yes, MI v1 implementation
+-environment-path                  No
+@</pre>
+
+Notes:@p
+
+1) -display* aren't implemented. You can use CLI command display, but the
+results are sent to the console. So it looks like the best is to manually
+use -data-evaluate-expression to emulate it.@p
+
+2) GDB bug mi/1770: Affects gdb<=6.2, when you ask for the names of the
+registers you get it plus the name of the "pseudo-registers", but if you
+try to get the value of a pseudo-register you get an error saying the
+register number is invalid. I reported to gdb-patches@sources.redhat.com
+on 2004/08/25 and as I didn't get any answer I filled a bug report on
+2004/09/02. The patch to fix this annoying bug is:
+
+Index: gdb/mi/mi-main.c
+===================================================================
+RCS file: /cvs/src/src/gdb/mi/mi-main.c,v
+retrieving revision 1.64
+diff -u -r1.64 mi-main.c
+--- gdb/mi/mi-main.c    3 Aug 2004 00:57:27 -0000       1.64
++++ gdb/mi/mi-main.c    25 Aug 2004 14:12:50 -0000
+@@ -423,7 +423,7 @@
+      case, some entries of REGISTER_NAME will change depending upon
+      the particular processor being debugged.
+
+-  numregs = NUM_REGS;
++  numregs = NUM_REGS + NUM_PSEUDO_REGS;
+
+   if (argc == 0)
+     {
+----
+
+Note I had to remove an end of comment in the patch to include it here.
+This bug forced me to create another set of functions. The only way is to
+first get the values and then the names.
+Fixed by Changelog entry:
+
+2004-09-12  Salvador E. Tropea  <set@users.sf.net>
+            Andrew Cagney  <cagney@gnu.org>
+
+        * mi/mi-main.c (mi_cmd_data_list_changed_registers)
+        (mi_cmd_data_list_register_values)
+        (mi_cmd_data_write_register_values): Include the PSEUDO_REGS in
+        the register number computation.
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_data_evaluate_expression(mi_h *h, const char *expression)
+{
+ mi_send(h,"-data-evaluate-expression \"%s\"\n",expression);
+}
+
+void mi_dir(mi_h *h, const char *path)
+{
+ if (h->version>=MI_VERSION2U(2,0,0))
+   {// MI v2
+    if (path)
+       mi_send(h,"-environment-directory \"%s\"\n",path);
+    else
+       mi_send(h,"-environment-directory -r\n");
+   }
+ else
+   {
+    mi_send(h,"-environment-directory %s\n",path ? path : "");
+   }
+}
+
+void mi_data_read_memory_hx(mi_h *h, const char *exp, unsigned ws,
+                            unsigned c, int convAddr)
+{
+ if (convAddr)
+    mi_send(h,"-data-read-memory \"&%s\" x %d 1 %d\n",exp,ws,c);
+ else
+    mi_send(h,"-data-read-memory \"%s\" x %d 1 %d\n",exp,ws,c);
+}
+
+void mi_data_disassemble_se(mi_h *h, const char *start, const char *end,
+                            int mode)
+{
+ mi_send(h,"-data-disassemble -s \"%s\" -e \"%s\" -- %d\n",start,end,mode);
+}
+
+void mi_data_disassemble_fl(mi_h *h, const char *file, int line, int lines,
+                            int mode)
+{
+ mi_send(h,"-data-disassemble -f \"%s\" -l %d -n %d -- %d\n",file,line,lines,
+         mode);
+}
+
+void mi_data_list_register_names(mi_h *h)
+{
+ mi_send(h,"-data-list-register-names\n");
+}
+
+void mi_data_list_register_names_l(mi_h *h, mi_chg_reg *l)
+{
+ mi_send(h,"-data-list-register-names ");
+ while (l)
+   {
+    mi_send(h,"%d ",l->reg);
+    l=l->next;
+   }
+ mi_send(h,"\n");
+}
+
+void mi_data_list_changed_registers(mi_h *h)
+{
+ mi_send(h,"-data-list-changed-registers\n");
+}
+
+void mi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l)
+{
+ mi_send(h,"-data-list-register-values %c ",mi_format_enum_to_char(fmt));
+ while (l)
+   {
+    mi_send(h,"%d ",l->reg);
+    l=l->next;
+   }
+ mi_send(h,"\n");
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  Evaluate an expression. Returns a parsed tree.
+
+  Command: -data-evaluate-expression
+  Return: The resulting value (as plain text) or NULL on error.
+  
+***************************************************************************/
+
+char *gmi_data_evaluate_expression(mi_h *h, const char *expression)
+{
+ mi_data_evaluate_expression(h,expression);
+ return mi_res_value(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Path for sources. You must use it to indicate where are the sources for
+the program to debug. Only the MI v1 implementation is available.
+
+  Command: -environment-directory
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_dir(mi_h *h, const char *path)
+{
+ mi_dir(h,path);
+ return mi_res_simple_done(h);
+}
+
+int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
+                    unsigned char *dest, int *na, int convAddr,
+                    unsigned long *addr)
+{
+ mi_data_read_memory_hx(h,exp,1,size,convAddr);
+ return mi_get_read_memory(h,dest,1,na,addr);
+}
+
+mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
+                                      const char *end, int mode)
+{
+ mi_data_disassemble_se(h,start,end,mode);
+ return mi_get_asm_insns(h);
+}
+
+mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
+                                      int lines, int mode)
+{
+ mi_data_disassemble_fl(h,file,line,lines,mode);
+ return mi_get_asm_insns(h);
+}
+
+// Affected by gdb bug mi/1770
+mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many)
+{
+ mi_data_list_register_names(h);
+ return mi_get_list_registers(h,how_many);
+}
+
+int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l)
+{
+ mi_data_list_register_names_l(h,l);
+ return mi_get_list_registers_l(h,l);
+}
+
+mi_chg_reg *gmi_data_list_changed_registers(mi_h *h)
+{
+ mi_error=MI_OK;
+ mi_data_list_changed_registers(h);
+ return mi_get_list_changed_regs(h);
+}
+
+int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l)
+{
+ mi_data_list_register_values(h,fmt,l);
+ return mi_get_reg_values(h,l);
+}
+
+mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many)
+{
+ mi_data_list_register_values(h,fmt,NULL);
+ return mi_get_reg_values_l(h,how_many);
+}
+
diff --git a/src/error.c b/src/error.c
new file mode 100644 (file)
index 0000000..adeb16c
--- /dev/null
@@ -0,0 +1,38 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Error.
+  Comment:
+  Translates error numbers into messages.
+  
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+static
+const char *error_strs[]=
+{
+ "Ok",
+ "Out of memory",
+ "Pipe creation",
+ "Fork failed",
+ "GDB not running",
+ "Parser failed",
+ "Unknown asyn response",
+ "Unknown result response",
+ "Error from gdb",
+ "Time out in gdb response",
+ "GDB suddenly died",
+ "Can't execute X terminal",
+ "Failed to create temporal",
+ "Can't execute the debugger"
+};
+
+const char *mi_get_error_str()
+{
+ if (mi_error<0 || mi_error>MI_LAST_ERROR)
+    return "Unknown";
+ return error_strs[mi_error];
+}
diff --git a/src/get_free_pty.c b/src/get_free_pty.c
new file mode 100644 (file)
index 0000000..8c145d0
--- /dev/null
@@ -0,0 +1,132 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: pseudo terminal
+  Comments:
+  Helper to find a free pseudo terminal. Use this if you need to manage
+  input *and* output to the target process. If you just need output then
+  define a handler for target output stream records (assuming that this
+  is working for your particular version of gdb).
+  Usage:
+
+        mi_pty *pty = gmi_look_for_free_pty();
+        if (pty) gmi_target_terminal(mih, pty->slave);
+        ...
+        * reading from pty->master will get stdout from target *
+        * writing to pty->master will send to target stdin *
+        
+  Note: Contributed by Greg Watson (gwatson lanl gov)
+
+***************************************************************************/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "mi_gdb.h"
+
+/**[txh]********************************************************************
+
+  Description:
+  Look for a free and usable pseudo terminal. Low level, use
+@x{gmi_look_for_free_pty}.
+  
+  Return: A file descriptor connected to the master pty and the name of the slave device, or <0 on error.
+  
+***************************************************************************/
+
+#ifdef __APPLE__
+
+#include <util.h>
+
+int mi_look_for_free_pty(int *master, char **slave)
+{
+ int fdmaster;
+ int fdslave;
+ static char name[BUFSIZ];
+
+ if (openpty(&fdmaster,&fdslave,name,NULL,NULL)<0)
+    return -1;
+
+ (void)close(fdslave); /* this will be reopened by gdb */
+ *master=fdmaster;
+ *slave =name;
+
+ return 0;
+}
+
+#elif defined(__linux__)
+
+int mi_look_for_free_pty(int *master, char **slave)
+{
+ if ((*master=open("/dev/ptmx",O_RDWR))<0)
+    return -1;
+ if (grantpt(*master)<0 || unlockpt(*master)<0)
+    return -1;
+ *slave = ptsname(*master);
+
+ return 0;
+}
+
+#else /* undefined o/s */
+
+int mi_look_for_free_pty(int *master, char **slave)
+{
+ return -1;
+}
+#endif
+
+/**[txh]********************************************************************
+
+  Description:
+  Look for a free and usable pseudo terminal to be used by the child.
+  
+  Return: A new mi_pty structure, you can use @x{gmi_end_pty} to
+release it.
+  
+***************************************************************************/
+
+mi_pty *gmi_look_for_free_pty()
+{
+ int master;
+ char *slave;
+ int pty=mi_look_for_free_pty(&master,&slave);
+ mi_pty *res;
+
+ if (pty<0)
+    return NULL;
+ res=(mi_pty *)malloc(sizeof(mi_pty));
+ if (!res)
+    return NULL;
+ res->slave=strdup(slave);
+ res->master=master;
+ return res;
+}
+
+void mi_free_pty(mi_pty *p)
+{
+ if (!p)
+    return;
+ free(p->slave);
+ free(p);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Closes the pseudo termial master and releases the allocated memory.
+  
+***************************************************************************/
+
+void gmi_end_pty(mi_pty *p)
+{
+ if (!p)
+    return;
+ close(p->master);
+ mi_free_pty(p);
+}
diff --git a/src/get_free_vt.c b/src/get_free_vt.c
new file mode 100644 (file)
index 0000000..f5c9800
--- /dev/null
@@ -0,0 +1,153 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Linux VT.
+  Comments:
+  Helper to find a free VT. That's 100% Linux specific.@p
+  The code comes from "lconsole.c" from Allegro project and was originally
+created by Marek Habersack and then modified by George Foot. I addapted it
+to my needs and changed license from giftware to GPL.@p
+  
+***************************************************************************/
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#ifdef __APPLE__
+#include <util.h>
+#endif /* __APPLE__ */
+
+#include "mi_gdb.h"
+
+#if !defined(__linux__)
+
+int mi_look_for_free_vt()
+{
+ return -1;
+}
+
+mi_aux_term *gmi_look_for_free_vt()
+{
+ return NULL;
+}
+
+#else
+
+#include <linux/vt.h>
+
+/**[txh]********************************************************************
+
+  Description:
+  Look for a free and usable Linux VT. Low level, use
+@x{gmi_look_for_free_vt}.
+  
+  Return: The VT number or <0 on error.
+  
+***************************************************************************/
+
+int mi_look_for_free_vt()
+{/* Code from Allegro. */
+ int tty, console_fd, fd;
+ unsigned short mask;
+ char tty_name[16];
+ struct vt_stat vts; 
+
+ /* Now we need to find a VT we can use.  It must be readable and
+  * writable by us, if we're not setuid root.  VT_OPENQRY itself
+  * isn't too useful because it'll only ever come up with one 
+  * suggestion, with no guarrantee that we actually have access 
+  * to it.
+  *
+  * At some stage I think this is a candidate for config
+  * file overriding, but for now we'll stat the first N consoles
+  * to see which ones we can write to (hopefully at least one!),
+  * so that we can use that one to do ioctls.  We used to use 
+  * /dev/console for that purpose but it looks like it's not 
+  * always writable by enough people.
+  *
+  * Having found and opened a writable device, we query the state
+  * of the first sixteen (fifteen really) consoles, and try 
+  * opening each unused one in turn.
+  */
+
+ console_fd=open("/dev/console",O_WRONLY);
+ if (console_fd<0)
+   {
+    int n;
+    /* Try some ttys instead... */
+    for (n=1; n<=24; n++)
+       {
+        snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",n);
+        console_fd=open(tty_name,O_WRONLY);
+        if (console_fd>=0)
+           break;
+       }
+    if (n>24)
+       return -1;
+   }
+
+ /* Get the state of the console -- in particular, the free VT field */
+ if (ioctl(console_fd,VT_GETSTATE,&vts))
+    return -2;
+ close(console_fd);
+
+ /* We attempt to set our euid to 0; if we were run with euid 0 to
+  * start with, we'll be able to do this now.  Otherwise, we'll just
+  * ignore the error returned since it might not be a problem if the
+  * ttys we look at are owned by the user running the program. */
+ seteuid(0);
+
+ /* tty0 is not really a console, so start counting at 2. */
+ fd=-1;
+ for (tty=1, mask=2; mask; tty++, mask<<=1)
+     if (!(vts.v_state & mask))
+       {
+        snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",tty);
+        fd=open(tty_name,O_RDWR);
+        if (fd!=-1)
+          {
+           close(fd);
+           break;
+          }
+       }
+
+ seteuid(getuid());
+
+ if (!mask)
+    return -3;
+
+ return tty;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Look for a free and usable Linux VT to be used by the child.
+  
+  Return: A new mi_aux_term structure, you can use @x{gmi_end_aux_term} to
+release it.
+  
+***************************************************************************/
+
+mi_aux_term *gmi_look_for_free_vt()
+{
+ int vt=mi_look_for_free_vt();
+ mi_aux_term *res;
+
+ if (vt<0)
+    return NULL;
+ res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
+ if (!res)
+    return NULL;
+ res->pid=-1;
+ asprintf(&res->tty,"/dev/tty%d",vt);
+ return res;
+}
+
+#endif
+
diff --git a/src/mi_gdb.h b/src/mi_gdb.h
new file mode 100644 (file)
index 0000000..df932b4
--- /dev/null
@@ -0,0 +1,972 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004-2009 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Comments:
+  Main header for libmigdb.
+  
+***************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> /* pid_t */
+
+#define MI_OK                      0
+#define MI_OUT_OF_MEMORY           1
+#define MI_PIPE_CREATE             2
+#define MI_FORK                    3
+#define MI_DEBUGGER_RUN            4
+#define MI_PARSER                  5
+#define MI_UNKNOWN_ASYNC           6
+#define MI_UNKNOWN_RESULT          7
+#define MI_FROM_GDB                8
+#define MI_GDB_TIME_OUT            9
+#define MI_GDB_DIED               10
+#define MI_MISSING_XTERM          11
+#define MI_CREATE_TEMPORAL        12
+#define MI_MISSING_GDB            13
+#define MI_LAST_ERROR             13
+
+#define MI_R_NONE                  0 /* We are no waiting any response. */
+#define MI_R_SKIP                  1 /* We want to discard it. */
+#define MI_R_FE_AND_S              2 /* Wait for done. */
+#define MI_R_E_ARGS                3
+
+enum mi_val_type { t_const, t_tuple, t_list };
+
+/* Types and subtypes. */
+/* Type. */
+#define MI_T_OUT_OF_BAND   0
+#define MI_T_RESULT_RECORD 1
+/* Out of band subtypes. */
+#define MI_ST_ASYNC        0
+#define MI_ST_STREAM       1
+/* Async sub-subtypes. */
+#define MI_SST_EXEC        0
+#define MI_SST_STATUS      1
+#define MI_SST_NOTIFY      2
+/* Stream sub-subtypes. */
+#define MI_SST_CONSOLE     3
+#define MI_SST_TARGET      4
+#define MI_SST_LOG         5
+/* Classes. */
+/* Async classes. */
+#define MI_CL_UNKNOWN      0
+#define MI_CL_STOPPED      1
+#define MI_CL_DOWNLOAD     2
+/* Result classes. */
+#define MI_CL_DONE         2
+#define MI_CL_RUNNING      3
+#define MI_CL_CONNECTED    4
+#define MI_CL_ERROR        5
+#define MI_CL_EXIT         6
+
+#define MI_DEFAULT_TIME_OUT 10
+
+#define MI_DIS_ASM        0
+#define MI_DIS_SRC_ASM    1
+
+/* Implemented workaround for gdb bugs that we can dis/enable. */
+/* At least gdb<=6.1.1 fails to find a source file with absolute path if the
+   name is for a psym instead of a sym. psym==partially loaded symbol table. */
+#define MI_PSYM_SEARCH    0
+
+#define MI_VERSION_STR "0.8.12"
+#define MI_VERSION_MAJOR  0
+#define MI_VERSION_MIDDLE 8
+#define MI_VERSION_MINOR  12
+
+struct mi_results_struct
+{
+ char *var; /* Result name or NULL if just a value. */
+ enum mi_val_type type;
+ union
+ {
+  char *cstr;
+  struct mi_results_struct *rs;
+ } v;
+ struct mi_results_struct *next;
+};
+typedef struct mi_results_struct mi_results;
+
+struct mi_output_struct
+{
+ /* Type of output. */
+ char type;
+ char stype;
+ char sstype;
+ char tclass;
+ /* Content. */
+ mi_results *c;
+ /* Always modeled as a list. */
+ struct mi_output_struct *next;
+};
+typedef struct mi_output_struct mi_output;
+
+typedef void (*stream_cb)(const char *, void *);
+typedef void (*async_cb)(mi_output *o, void *);
+typedef int  (*tm_cb)(void *);
+
+/* Values of this structure shouldn't be manipulated by the user. */
+struct mi_h_struct
+{
+ /* Pipes connected to gdb. */
+ int to_gdb[2];
+ int from_gdb[2];
+ /* Streams for the pipes. */
+ FILE *to, *from;
+ /* PID of child gdb. */
+ pid_t pid;
+ char died;
+ /* Which rensponse we are waiting for. */
+ /*int response;*/
+ /* The line we are reading. */
+ char *line;
+ int   llen, lread;
+ /* Parsed output. */
+ mi_output *po, *last;
+ /* Tunneled streams callbacks. */
+ stream_cb console;
+ void *console_data;
+ stream_cb target;
+ void *target_data;
+ stream_cb log;
+ void *log_data;
+ /* Async responses callback. */
+ async_cb async;
+ void *async_data;
+ /* Callbacks to get echo of gdb dialog. */
+ stream_cb to_gdb_echo;
+ void *to_gdb_echo_data;
+ stream_cb from_gdb_echo;
+ void *from_gdb_echo_data;
+ /* Time out */
+ tm_cb time_out_cb;
+ void *time_out_cb_data;
+ int time_out;
+ /* Ugly workaround for some of the show responses :-( */
+ int catch_console;
+ char *catched_console;
+ /* MI version, currently unknown but the user can force v2 */
+ unsigned version;
+};
+typedef struct mi_h_struct mi_h;
+
+#define MI_TO(a) ((a)->to_gdb[1])
+
+enum mi_bkp_type { t_unknown=0, t_breakpoint=1, t_hw=2 };
+enum mi_bkp_disp { d_unknown=0, d_keep=1, d_del=2 };
+enum mi_bkp_mode { m_file_line=0, m_function=1, m_file_function=2, m_address=3 };
+
+struct mi_bkpt_struct
+{
+ int number;
+ enum mi_bkp_type type;
+ enum mi_bkp_disp disp; /* keep or del if temporal */
+ char enabled;
+ void *addr;
+ char *func;
+ char *file;
+ int line;
+ int ignore;
+ int times;
+
+ /* For the user: */
+ char *cond;
+ char *file_abs;
+ int thread;
+ enum mi_bkp_mode mode;
+ struct mi_bkpt_struct *next;
+};
+typedef struct mi_bkpt_struct mi_bkpt;
+
+enum mi_wp_mode { wm_unknown=0, wm_write=1, wm_read=2, wm_rw=3 };
+
+struct mi_wp_struct
+{
+ int number;
+ char *exp;
+ enum mi_wp_mode mode;
+
+ /* For the user: */
+ struct mi_wp_struct *next;
+ char enabled;
+};
+typedef struct mi_wp_struct mi_wp;
+
+struct mi_frames_struct
+{
+ int level;  /* The frame number, 0 being the topmost frame, i.e. the innermost
+                function. */
+ void *addr; /* The `$pc' value for that frame. */
+ char *func; /* Function name. */
+ char *file; /* File name of the source file where the function lives. */
+ char *from;
+ int line;   /* Line number corresponding to the `$pc'. */
+ /* When arguments are available: */
+ mi_results *args;
+ int thread_id;
+ /* When more than one is provided: */
+ struct mi_frames_struct *next;
+};
+typedef struct mi_frames_struct mi_frames;
+
+struct mi_aux_term_struct
+{
+ pid_t pid;
+ char *tty;
+};
+typedef struct mi_aux_term_struct mi_aux_term;
+
+struct mi_pty_struct
+{
+ char *slave;
+ int master;
+};
+typedef struct mi_pty_struct mi_pty;
+
+enum mi_gvar_fmt { fm_natural=0, fm_binary=1, fm_decimal=2, fm_hexadecimal=3,
+                   fm_octal=4,
+                   /* Only for registers format: */
+                   fm_raw=5 };
+enum mi_gvar_lang { lg_unknown=0, lg_c, lg_cpp, lg_java };
+
+#define MI_ATTR_DONT_KNOW   0
+#define MI_ATTR_NONEDITABLE 1
+#define MI_ATTR_EDITABLE    2
+
+struct mi_gvar_struct
+{
+ char *name;
+ int   numchild;
+ char *type;
+ enum mi_gvar_fmt format;
+ enum mi_gvar_lang lang;
+ char *exp;
+ int   attr;
+
+ /* MI v2 fills it, not yet implemented here. */
+ /* Use gmi_var_evaluate_expression. */
+ char *value;
+
+ /* Pointer to the parent. NULL if none. */
+ struct mi_gvar_struct *parent;
+ /* List containing the children.
+    Filled by gmi_var_list_children.
+    NULL if numchild==0 or not yet filled. */
+ struct mi_gvar_struct *child;
+ /* Next var in the list. */
+ struct mi_gvar_struct *next;
+
+ /* For the user: */
+ char opened;  /* We will show its children. 1 when we fill "child" */
+ char changed; /* Needs to be updated. 0 when created. */
+ int vischild; /* How many items visible. numchild when we fill "child" */
+ int depth;    /* How deep is this var. */
+ char ispointer;
+};
+typedef struct mi_gvar_struct mi_gvar;
+
+struct mi_gvar_chg_struct
+{
+ char *name;
+ int   in_scope;  /* if true the other fields apply. */
+ char *new_type;  /* NULL if type_changed==false */
+ int   new_num_children; /* only when new_type!=NULL */
+
+ struct mi_gvar_chg_struct *next;
+};
+typedef struct mi_gvar_chg_struct mi_gvar_chg;
+
+
+/* A list of assembler instructions. */
+struct mi_asm_insn_struct
+{
+ void *addr;
+ char *func;
+ unsigned offset;
+ char *inst;
+
+ struct mi_asm_insn_struct *next;
+};
+typedef struct mi_asm_insn_struct mi_asm_insn;
+
+/* A list of source lines containing assembler instructions. */
+struct mi_asm_insns_struct
+{
+ char *file;
+ int line;
+ mi_asm_insn *ins;
+
+ struct mi_asm_insns_struct *next;
+};
+typedef struct mi_asm_insns_struct mi_asm_insns;
+
+/* Changed register. */
+struct mi_chg_reg_struct
+{
+ int reg;
+ char *val;
+ char *name;
+ char updated;
+
+ struct mi_chg_reg_struct *next;
+};
+typedef struct mi_chg_reg_struct mi_chg_reg;
+
+/*
+ Examining gdb sources and looking at docs I can see the following "stop"
+reasons:
+
+Breakpoints:
+a) breakpoint-hit (bkptno) + frame
+Also: without reason for temporal breakpoints.
+
+Watchpoints:
+b) watchpoint-trigger (wpt={number,exp};value={old,new}) + frame
+c) read-watchpoint-trigger (hw-rwpt{number,exp};value={value}) + frame
+d) access-watchpoint-trigger (hw-awpt{number,exp};value={[old,]new}) + frame
+e) watchpoint-scope (wpnum) + frame
+
+Movement:
+f) function-finished ([gdb-result-var,return-value]) + frame
+g) location-reached + frame
+h) end-stepping-range + frame
+
+Exit:
+i) exited-signalled (signal-name,signal-meaning)
+j) exited (exit-code)
+k) exited-normally
+
+Signal:
+l) signal-received (signal-name,signal-meaning) + frame
+
+Plus: thread-id
+*/
+enum mi_stop_reason
+{
+ sr_unknown=0,
+ sr_bkpt_hit,
+ sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
+ sr_function_finished, sr_location_reached, sr_end_stepping_range,
+ sr_exited_signalled, sr_exited, sr_exited_normally,
+ sr_signal_received
+};
+
+struct mi_stop_struct
+{
+ enum mi_stop_reason reason; /* If more than one reason just the last. */
+ /* Flags indicating if non-pointer fields are filled. */
+ char have_thread_id;
+ char have_bkptno;
+ char have_exit_code;
+ char have_wpno;
+ /* Where stopped. Doesn't exist for sr_exited*. */
+ int thread_id;
+ mi_frames *frame;
+ /* sr_bkpt_hit */
+ int bkptno;
+ /* sr_*wp_* no scope */
+ mi_wp *wp;
+ char *wp_old;
+ char *wp_val;
+ /* sr_wp_scope */
+ int wpno;
+ /* sr_function_finished. Not for void func. */
+ char *gdb_result_var;
+ char *return_value;
+ /* sr_exited_signalled, sr_signal_received */
+ char *signal_name;
+ char *signal_meaning;
+ /* sr_exited */
+ int exit_code;
+};
+typedef struct mi_stop_struct mi_stop;
+
+/* Variable containing the last error. */
+extern int mi_error;
+extern char *mi_error_from_gdb;
+const char *mi_get_error_str();
+
+/* Indicate the name of gdb exe. Default is /usr/bin/gdb */
+void mi_set_gdb_exe(const char *name);
+const char *mi_get_gdb_exe();
+/* Indicate the name of a file containing commands to send at start-up */
+void mi_set_gdb_start(const char *name);
+const char *mi_get_gdb_start();
+/* Indicate the name of a file containing commands to send after connection */
+void mi_set_gdb_conn(const char *name);
+const char *mi_get_gdb_conn();
+void mi_send_target_commands(mi_h *h);
+/* Connect to a local copy of gdb. */
+mi_h *mi_connect_local();
+/* Close connection. You should ask gdb to quit first. */
+void  mi_disconnect(mi_h *h);
+/* Force MI version. */
+#define MI_VERSION2U(maj,mid,min) (maj*0x1000000+mid*0x10000+min)
+void  mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
+                       unsigned vMinor);
+void  mi_set_workaround(unsigned wa, int enable);
+int   mi_get_workaround(unsigned wa);
+/* Parse gdb output. */
+mi_output *mi_parse_gdb_output(const char *str);
+/* Functions to set/get the tunneled streams callbacks. */
+void mi_set_console_cb(mi_h *h, stream_cb cb, void *data);
+void mi_set_target_cb(mi_h *h, stream_cb cb, void *data);
+void mi_set_log_cb(mi_h *h, stream_cb cb, void *data);
+stream_cb mi_get_console_cb(mi_h *h, void **data);
+stream_cb mi_get_target_cb(mi_h *h, void **data);
+stream_cb mi_get_log_cb(mi_h *h, void **data);
+/* The callback to deal with async events. */
+void mi_set_async_cb(mi_h *h, async_cb cb, void *data);
+async_cb mi_get_async_cb(mi_h *h, void **data);
+/* Time out in gdb responses. */
+void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data);
+tm_cb mi_get_time_out_cb(mi_h *h, void **data);
+void mi_set_time_out(mi_h *h, int to);
+int mi_get_time_out(mi_h *h);
+/* Callbacks to "see" the dialog with gdb. */
+void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data);
+void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data);
+stream_cb mi_get_to_gdb_cb(mi_h *h, void **data);
+stream_cb mi_get_from_gdb_cb(mi_h *h, void **data);
+/* Sends a message to gdb. */
+int mi_send(mi_h *h, const char *format, ...);
+/* Wait until gdb sends a response. */
+mi_output *mi_get_response_blk(mi_h *h);
+/* Check if gdb sent a complete response. Use with mi_retire_response. */
+int mi_get_response(mi_h *h);
+/* Get the last response. Use with mi_get_response. */
+mi_output *mi_retire_response(mi_h *h);
+/* Look for a result record in gdb output. */
+mi_output *mi_get_rrecord(mi_output *r);
+/* Look if the output contains an async stop.
+   If that's the case return the reason for the stop.
+   If the output contains an error the description is returned in reason. */
+int mi_get_async_stop_reason(mi_output *r, char **reason);
+mi_stop *mi_get_stopped(mi_results *r);
+mi_frames *mi_get_async_frame(mi_output *r);
+/* Wait until gdb sends a response.
+   Then check if the response is of the desired type. */
+int mi_res_simple_exit(mi_h *h);
+int mi_res_simple_done(mi_h *h);
+int mi_res_simple_running(mi_h *h);
+int mi_res_simple_connected(mi_h *h);
+/* It additionally extracts an specified variable. */
+mi_results *mi_res_done_var(mi_h *h, const char *var);
+/* Extract a frames list from the response. */
+mi_frames *mi_res_frames_array(mi_h *h, const char *var);
+mi_frames *mi_res_frames_list(mi_h *h);
+mi_frames *mi_parse_frame(mi_results *c);
+mi_frames *mi_res_frame(mi_h *h);
+/* Create an auxiliar terminal using xterm. */
+mi_aux_term *gmi_start_xterm();
+/* Indicate the name of xterm exe. Default is /usr/bin/X11/xterm */
+void mi_set_xterm_exe(const char *name);
+const char *mi_get_xterm_exe();
+/* Kill the auxiliar terminal and release the structure. */
+void gmi_end_aux_term(mi_aux_term *t);
+/* Look for a free Linux VT for the child. */
+mi_aux_term *gmi_look_for_free_vt();
+/* Look for a free and usable Linux VT. */
+int mi_look_for_free_vt();
+/* Close master and release the structure. */
+void gmi_end_pty(mi_pty *p);
+/* Look for a free pseudo terminal. */
+mi_pty *gmi_look_for_free_pty();
+/* Extract a list of thread IDs from response. */
+int mi_res_thread_ids(mi_h *h, int **list);
+int mi_get_thread_ids(mi_output *res, int **list);
+/* A variable response. */
+mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression);
+enum mi_gvar_fmt mi_format_str_to_enum(const char *format);
+const char *mi_format_enum_to_str(enum mi_gvar_fmt format);
+char mi_format_enum_to_char(enum mi_gvar_fmt format);
+enum mi_gvar_lang mi_lang_str_to_enum(const char *lang);
+const char *mi_lang_enum_to_str(enum mi_gvar_lang lang);
+int mi_res_changelist(mi_h *h, mi_gvar_chg **changed);
+int mi_res_children(mi_h *h, mi_gvar *v);
+mi_bkpt *mi_res_bkpt(mi_h *h);
+mi_wp *mi_res_wp(mi_h *h);
+char *mi_res_value(mi_h *h);
+mi_stop *mi_res_stop(mi_h *h);
+enum mi_stop_reason mi_reason_str_to_enum(const char *s);
+const char *mi_reason_enum_to_str(enum mi_stop_reason r);
+int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
+                       unsigned long *addr);
+mi_asm_insns *mi_get_asm_insns(mi_h *h);
+/* Starting point of the program. */
+void mi_set_main_func(const char *name);
+const char *mi_get_main_func();
+mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many);
+int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l);
+mi_chg_reg *mi_get_list_changed_regs(mi_h *h);
+int mi_get_reg_values(mi_h *h, mi_chg_reg *l);
+mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many);
+int gmi_target_download(mi_h *h);
+
+/* Allocation functions: */
+void *mi_calloc(size_t count, size_t sz);
+void *mi_calloc1(size_t sz);
+char *mi_malloc(size_t sz);
+mi_results       *mi_alloc_results(void);
+mi_output        *mi_alloc_output(void);
+mi_frames        *mi_alloc_frames(void);
+mi_gvar          *mi_alloc_gvar(void);
+mi_gvar_chg      *mi_alloc_gvar_chg(void);
+mi_bkpt          *mi_alloc_bkpt(void);
+mi_wp            *mi_alloc_wp(void);
+mi_stop          *mi_alloc_stop(void);
+mi_asm_insns     *mi_alloc_asm_insns(void);
+mi_asm_insn      *mi_alloc_asm_insn(void);
+mi_chg_reg       *mi_alloc_chg_reg(void);
+void mi_free_output(mi_output *r);
+void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r);
+void mi_free_frames(mi_frames *f);
+void mi_free_aux_term(mi_aux_term *t);
+void mi_free_results(mi_results *r);
+void mi_free_results_but(mi_results *r, mi_results *no);
+void mi_free_gvar(mi_gvar *v);
+void mi_free_gvar_chg(mi_gvar_chg *p);
+void mi_free_wp(mi_wp *wp);
+void mi_free_stop(mi_stop *s);
+void mi_free_asm_insns(mi_asm_insns *i);
+void mi_free_asm_insn(mi_asm_insn *i);
+void mi_free_charp_list(char **l);
+void mi_free_chg_reg(mi_chg_reg *r);
+
+/* Porgram control: */
+/* Specify the executable and arguments for local debug. */
+int gmi_set_exec(mi_h *h, const char *file, const char *args);
+/* Start running the executable. Remote sessions starts running. */
+int gmi_exec_run(mi_h *h);
+/* Continue the execution after a "stop". */
+int gmi_exec_continue(mi_h *h);
+/* Indicate which terminal will use the target program. For local sessions. */
+int gmi_target_terminal(mi_h *h, const char *tty_name);
+/* Specify what's the local copy that have debug info. For remote sessions. */
+int gmi_file_symbol_file(mi_h *h, const char *file);
+/* Continue until function return, the return value is included in the async
+   response. */
+int gmi_exec_finish(mi_h *h);
+/* Stop the program using SIGINT. */
+int gmi_exec_interrupt(mi_h *h);
+/* Next line of code. */
+int gmi_exec_next(mi_h *h);
+/* Next count lines of code. */
+int gmi_exec_next_cnt(mi_h *h, int count);
+/* Next line of assembler code. */
+int gmi_exec_next_instruction(mi_h *h);
+/* Next line of code. Get inside functions. */
+int gmi_exec_step(mi_h *h);
+/* Next count lines of code. Get inside functions. */
+int gmi_exec_step_cnt(mi_h *h, int count);
+/* Next line of assembler code. Get inside calls. */
+int gmi_exec_step_instruction(mi_h *h);
+/* Execute until location is reached. If file is NULL then is until next line. */
+int gmi_exec_until(mi_h *h, const char *file, int line);
+int gmi_exec_until_addr(mi_h *h, void *addr);
+/* Return to previous frame inmediatly. */
+mi_frames *gmi_exec_return(mi_h *h);
+/* Just kill the program. Please read the notes in prg_control.c. */
+int gmi_exec_kill(mi_h *h);
+
+/* Target manipulation: */
+/* Connect to a remote gdbserver using the specified methode. */
+int gmi_target_select(mi_h *h, const char *type, const char *params);
+/* Attach to an already running process. */
+mi_frames *gmi_target_attach(mi_h *h, pid_t pid);
+/* Detach from an attached process. */
+int gmi_target_detach(mi_h *h);
+
+/* Miscellaneous commands: */
+/* Exit gdb killing the child is it is running. */
+void gmi_gdb_exit(mi_h *h);
+/* Send the version to the console. */
+int gmi_gdb_version(mi_h *h);
+/* Set a gdb variable. */
+int gmi_gdb_set(mi_h *h, const char *var, const char *val);
+/* Get a gdb variable. */
+char *gmi_gdb_show(mi_h *h, const char *var);
+
+/* Breakpoints manipulation: */
+/* Insert a breakpoint at file:line. */
+mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line);
+/* Insert a breakpoint, all available options. */
+mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
+                               const char *cond, int count, int thread,
+                               const char *where);
+mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
+                                  int temporary, int hard_assist,
+                                  const char *cond, int count, int thread);
+/* Remove a breakpoint. */
+int gmi_break_delete(mi_h *h, int number);
+/* Free the memory used for a breakpoint description. */
+void mi_free_bkpt(mi_bkpt *b);
+/* Modify the "ignore" count for a breakpoint. */
+int gmi_break_set_times(mi_h *h, int number, int count);
+/* Associate a condition with the breakpoint. */
+int gmi_break_set_condition(mi_h *h, int number, const char *condition);
+/* Enable or disable a breakpoint. */
+int gmi_break_state(mi_h *h, int number, int enable);
+/* Set a watchpoint. It doesn't work for remote targets! */
+mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp);
+
+/* Data Manipulation. */
+/* Evaluate an expression. Returns a parsed tree. */
+char *gmi_data_evaluate_expression(mi_h *h, const char *expression);
+/* Path for sources. */
+int gmi_dir(mi_h *h, const char *path);
+/* A very limited "data read memory" implementation. */
+int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
+                    unsigned char *dest, int *na, int convAddr,
+                    unsigned long *addr);
+mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
+                                      const char *end, int mode);
+mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
+                                      int lines, int mode);
+mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many);
+int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l);
+mi_chg_reg *gmi_data_list_changed_registers(mi_h *h);
+int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l);
+mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many);
+
+/* Stack manipulation. */
+/* List of frames. Arguments aren't filled. */
+mi_frames *gmi_stack_list_frames(mi_h *h);
+/* List of frames. Indicating a range. */
+mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to);
+/* List arguments. Only level and args filled. */
+mi_frames *gmi_stack_list_arguments(mi_h *h, int show);
+/* List arguments. Indicating a range. Only level and args filled. */
+mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to);
+/* Information about the current frame, including args. */
+mi_frames *gmi_stack_info_frame(mi_h *h);
+/* Stack info depth. error => -1 */
+int gmi_stack_info_depth_get(mi_h *h);
+/* Set stack info depth. error => -1 */
+int gmi_stack_info_depth(mi_h *h, int max_depth);
+/* Change current frame. */
+int gmi_stack_select_frame(mi_h *h, int framenum);
+/* List of local vars. */
+mi_results *gmi_stack_list_locals(mi_h *h, int show);
+
+/* Thread. */
+/* List available thread ids. */
+int gmi_thread_list_ids(mi_h *h, int **list);
+/* Select a thread. */
+mi_frames *gmi_thread_select(mi_h *h, int id);
+/* List available threads. */
+mi_frames *gmi_thread_list_all_threads(mi_h *h);
+
+/* Variable objects. */
+/* Create a variable object. */
+mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp);
+mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp);
+/* Create the variable and also fill the lang and attr fields. */
+mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp);
+/* Delete a variable object. Doesn't free the mi_gvar data. */
+int gmi_var_delete(mi_h *h, mi_gvar *var);
+/* Set the format used to represent the result. */
+int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format);
+/* Fill the format field with info from gdb. */
+int gmi_var_show_format(mi_h *h, mi_gvar *var);
+/* Fill the numchild field with info from gdb. */
+int gmi_var_info_num_children(mi_h *h, mi_gvar *var);
+/* Fill the type field with info from gdb. */
+int gmi_var_info_type(mi_h *h, mi_gvar *var);
+/* Fill the expression and lang fields with info from gdb.
+   Note that lang isn't filled during creation. */
+int gmi_var_info_expression(mi_h *h, mi_gvar *var);
+/* Fill the attr field with info from gdb.
+   Note that attr isn't filled during creation. */
+int gmi_var_show_attributes(mi_h *h, mi_gvar *var);
+/* Update variable. Use NULL for all.
+   Note that *changed can be NULL if none updated. */
+int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed);
+/* Change variable. Fills the value field. */
+int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression);
+/* Get current value for a variable. */
+int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var);
+/* List children. It ONLY returns the first level information. :-( */
+int gmi_var_list_children(mi_h *h, mi_gvar *var);
+
+#ifdef __cplusplus
+};
+
+/* C++ interface */
+
+/*
+ State                Can:
+ disconnected         Connect
+  connected           SelectTarget, Disconnect
+   target_specified    TargetUnselect, Run, Set breakpoints/watchpoints, etc.
+    running            Stop
+    stopped            Kill, Restart?, Step, Trace, Continue, etc.
+    [auto exit]
+
+  Modes:
+  dmX11                 Local debug for X11.
+  dmLinux               Local debug for Linux console.
+  dmRemote              Remote debug.
+*/
+class MIDebugger
+{
+public:
+ MIDebugger();
+ ~MIDebugger();
+
+ enum eState { disconnected, connected, target_specified, running, stopped };
+ enum dMode  { dmX11, dmLinux, dmRemote, dmPID };
+ enum endianType { enUnknown, enLittle, enBig };
+ // Currently tested architectures
+ enum archType { arUnknown, arIA32, arSPARC, arPIC14, arAVR, arUnsupported };
+
+ int Connect(bool remote=false); /* remote is currently ignored. */
+ int Disconnect();
+ /* SelectTarget* */
+ int SelectTargetX11(const char *exec, const char *args=NULL,
+                     const char *auxtty=NULL);
+ int SelectTargetLinux(const char *exec, const char *args,
+                       const char *auxtty=NULL);
+ int SelectTargetRemote(const char *exec, const char *rparams,
+                        const char *rtype=NULL, bool download=false);
+ // TODO: Linux PIDs can be represented as intergers. What should I use?
+ // ato_pid_t doesn't exist ;-)
+ mi_frames *SelectTargetPID(const char *exec, int pid);
+ int TargetUnselect();
+ int Run();
+ int Stop();
+ int Poll(mi_stop *&rs);
+ int Continue();
+ int RunOrContinue();
+ int Kill();
+ mi_bkpt *Breakpoint(const char *file, int line);
+ mi_bkpt *Breakpoint(const char *where, bool temporary=false, const char *cond=NULL,
+                     int count=-1, int thread=-1, bool hard_assist=false);
+ mi_bkpt *BreakpointFull(const char *file, int line, bool temporary=false,
+                         const char *cond=NULL, int count=-1, int thread=-1,
+                         bool hard_assist=false);
+ mi_bkpt *Breakpoint(mi_bkpt *b);
+ int BreakDelete(mi_bkpt *b);
+ int BreakAfter(mi_bkpt *b)
+ {
+  if (state!=target_specified && state!=stopped)
+     return 0;
+  return gmi_break_set_times(h,b->number,b->ignore);
+ }
+ mi_wp *Watchpoint(enum mi_wp_mode mode, const char *exp);
+ int WatchDelete(mi_wp *w);
+ int RunToMain();
+ int StepOver(bool inst=false);
+ int TraceInto(bool inst=false);
+ int GoTo(const char *file, int line);
+ int GoTo(void *addr);
+ int FinishFun();
+ mi_frames *ReturnNow();
+ mi_frames *CallStack(bool args);
+ char *EvalExpression(const char *exp);
+ char *ModifyExpression(char *exp, char *newVal);
+ mi_gvar *AddgVar(const char *exp, int frame=-1)
+ {
+  if (state!=stopped)
+     return NULL;
+  return gmi_full_var_create(h,frame,exp);
+ }
+ int DelgVar(mi_gvar *var)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_delete(h,var);
+ }
+ int EvalgVar(mi_gvar *var)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_evaluate_expression(h,var);
+ }
+ int GetChildgVar(mi_gvar *var)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_list_children(h,var);
+ }
+ int FillTypeVal(mi_gvar *var);
+ int FillOneTypeVal(mi_gvar *var);
+ int FillAttr(mi_gvar *var)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_show_attributes(h,var);
+ }
+ int FillFormat(mi_gvar *var)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_show_format(h,var);
+ }
+ int SetFormatgVar(mi_gvar *var, enum mi_gvar_fmt format)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_set_format(h,var,format);
+ }
+ int ListChangedgVar(mi_gvar_chg *&changed)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_var_update(h,NULL,&changed);
+ }
+ int AssigngVar(mi_gvar *var, const char *exp);
+ int Send(const char *command);
+ int Version()
+ {
+  if (state==running || state==disconnected)
+     return 0;
+  return gmi_gdb_version(h);
+ }
+ int PathSources(const char *path)
+ {
+  if (state==running || state==disconnected)
+     return 0;
+  return gmi_dir(h,path);
+ }
+ int ReadMemory(const char *exp, unsigned size, unsigned char *dest,
+                int &na, int convAddr, unsigned long *addr)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_read_memory(h,exp,size,dest,&na,convAddr,addr);
+ }
+ char *Show(const char *var);
+ int ThreadListIDs(int *&list)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_thread_list_ids(h,&list);
+ }
+ mi_frames *ThreadList()
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_thread_list_all_threads(h);
+ }
+ mi_frames *ThreadSelect(int id)
+ {
+  if (state!=stopped)
+     return NULL;
+  return gmi_thread_select(h,id);
+ }
+ mi_asm_insns *Disassemble(const char *start, const char *end, int mode)
+ {
+  if (state!=stopped)
+     return NULL;
+  return gmi_data_disassemble_se(h,start,end,mode);
+ }
+ mi_asm_insns *Disassemble(const char *file, int line, int lines, int mode)
+ {
+  if (state!=stopped)
+     return NULL;
+  return gmi_data_disassemble_fl(h,file,line,lines,mode);
+ }
+ mi_chg_reg *GetRegisterNames(int *how_many)
+ {
+  if (state!=target_specified && state!=stopped)
+     return NULL;
+  return gmi_data_list_register_names(h,how_many);
+ }
+ int GetRegisterNames(mi_chg_reg *chg)
+ {
+  if (state!=target_specified && state!=stopped)
+     return 0;
+  return gmi_data_list_register_names_l(h,chg);
+ }
+ int GetRegisterValues(mi_chg_reg *chg)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_data_list_register_values(h,fm_natural,chg);
+ }
+ mi_chg_reg *GetRegisterValues(int *how_many)
+ {
+  if (state!=stopped)
+     return 0;
+  return gmi_data_list_all_register_values(h,fm_natural,how_many);
+ }
+ mi_chg_reg *GetChangedRegisters()
+ {
+  if (state!=stopped)
+     return NULL;
+  mi_chg_reg *chg=gmi_data_list_changed_registers(h);
+  if (chg && !gmi_data_list_register_values(h,fm_natural,chg))
+    {
+     mi_free_chg_reg(chg);
+     chg=NULL;
+    }
+  return chg;
+ }
+ int UpdateRegisters(mi_chg_reg *regs);
+
+ endianType GetTargetEndian();
+ archType   GetTargetArchitecture();
+ eState GetState() { return state; }
+
+ /* Some wrappers */
+ static void SetGDBExe(const char *name) { mi_set_gdb_exe(name); }
+ static const char *GetGDBExe() { return mi_get_gdb_exe(); }
+ static void SetXTermExe(const char *name) { mi_set_xterm_exe(name); }
+ static const char *GetXTermExe() { return mi_get_xterm_exe(); }
+ static void SetGDBStartFile(const char *name) { mi_set_gdb_start(name); }
+ static const char *GetGDBStartFile() { return mi_get_gdb_start(); }
+ static void SetGDBConnFile(const char *name) { mi_set_gdb_conn(name); }
+ static const char *GetGDBConnFile() { return mi_get_gdb_conn(); }
+ static void SetMainFunc(const char *name) { mi_set_main_func(name); }
+ static const char *GetMainFunc() { return mi_get_main_func(); }
+
+ static const char *GetErrorStr() { return mi_get_error_str(); }
+ static const char *GetGDBError() { return mi_error_from_gdb; }
+ static int GetErrorNumber() { return mi_error; }
+ int GetErrorNumberSt();
+ void SetConsoleCB(stream_cb cb, void *data=NULL)
+   { mi_set_console_cb(h,cb,data); }
+ void SetTargetCB(stream_cb cb, void *data=NULL)
+   { mi_set_target_cb(h,cb,data); }
+ void SetLogCB(stream_cb cb, void *data=NULL)
+   { mi_set_log_cb(h,cb,data); }
+ void SetAsyncCB(async_cb cb, void *data=NULL)
+   { mi_set_async_cb(h,cb,data); }
+ void SetToGDBCB(stream_cb cb, void *data=NULL)
+   { mi_set_to_gdb_cb(h,cb,data); }
+ void SetFromGDBCB(stream_cb cb, void *data=NULL)
+   { mi_set_from_gdb_cb(h,cb,data); }
+ void SetTimeOutCB(tm_cb cb, void *data)
+   { mi_set_time_out_cb(h,cb,data); }
+ void SetTimeOut(int to)
+   { mi_set_time_out(h,to); }
+ void ForceMIVersion(unsigned vMajor, unsigned vMiddle, unsigned vMinor)
+   { mi_force_version(h,vMajor,vMiddle,vMinor); }
+
+ const char *GetAuxTTY()
+   { return aux_tty ? aux_tty->tty : NULL; }
+
+protected:
+ eState state;
+ dMode mode;
+ endianType targetEndian;
+ archType targetArch;
+ bool  preRun;  // Remote targets starts running but outside main.
+ mi_h *h;
+ mi_aux_term *aux_tty;
+ int waitingTempBkpt;
+
+ int SelectTargetTTY(const char *exec, const char *args, const char *auxtty,
+                     dMode m);
+};
+
+#endif
+
diff --git a/src/misc.c b/src/misc.c
new file mode 100644 (file)
index 0000000..5440ab0
--- /dev/null
@@ -0,0 +1,118 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Miscellaneous commands.
+  Comments:
+  GDB/MI commands for the "Miscellaneous Commands" section.@p
+
+@<pre>
+gdb command:       Implemented?
+
+-gdb-exit          Yes
+-gdb-set           Yes
+-gdb-show          Yes
+-gdb-version       Yes
+@</pre>
+
+GDB Bug workaround for "-gdb-show architecture": gdb 6.1 and olders doesn't
+report it in "value", but they give the output of "show architecture". In
+6.4 we observed that not even a clue is reported. So now we always use
+"show architecture".
+
+***************************************************************************/
+
+#include <string.h>
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_gdb_exit(mi_h *h)
+{
+ mi_send(h,"-gdb-exit\n");
+}
+
+void mi_gdb_version(mi_h *h)
+{
+ mi_send(h,"-gdb-version\n");
+}
+
+void mi_gdb_set(mi_h *h, const char *var, const char *val)
+{
+ mi_send(h,"-gdb-set %s %s\n",var,val);
+}
+
+void mi_gdb_show(mi_h *h, const char *var)
+{
+ if (strcmp(var,"architecture")==0)
+    mi_send(h,"show %s\n",var);
+ else
+    mi_send(h,"-gdb-show %s\n",var);
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  Exit gdb killing the child is it is running.
+
+  Command: -gdb-exit
+
+***************************************************************************/
+
+void gmi_gdb_exit(mi_h *h)
+{
+ mi_gdb_exit(h);
+ mi_res_simple_exit(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Send the version to the console.
+
+  Command: -gdb-version
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_gdb_version(mi_h *h)
+{
+ mi_gdb_version(h);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Set a gdb variable.
+
+  Command: -gdb-set
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_gdb_set(mi_h *h, const char *var, const char *val)
+{
+ mi_gdb_set(h,var,val);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Get a gdb variable.
+
+  Command: -gdb-show
+  Return: The current value of the variable or NULL on error.
+  
+***************************************************************************/
+
+char *gmi_gdb_show(mi_h *h, const char *var)
+{
+ mi_gdb_show(h,var);
+ return mi_res_value(h);
+}
+
diff --git a/src/parse.c b/src/parse.c
new file mode 100644 (file)
index 0000000..0dea6cb
--- /dev/null
@@ -0,0 +1,1923 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004-2007 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Parser.
+  Comments:
+  Parses the output of gdb. It basically converts the text from gdb into a
+tree (could be a complex one) that we can easily interpret using C code.
+  
+***************************************************************************/
+
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include "mi_gdb.h"
+
+mi_results *mi_get_result(const char *str, const char **end);
+int mi_get_value(mi_results *r, const char *str, const char **end);
+
+
+/* GDB BUG!!!! I got:
+^error,msg="Problem parsing arguments: data-evaluate-expression ""1+2"""
+Afects gdb 2002-04-01-cvs and 6.1.1 for sure.
+That's an heuristical workaround.
+*/
+static inline
+int EndOfStr(const char *s)
+{
+ if (*s=='"')
+   {
+    s++;
+    return !*s || *s==',' || *s==']' || *s=='}';
+   }
+ return 0;
+}
+
+int mi_get_cstring_r(mi_results *r, const char *str, const char **end)
+{
+ const char *s;
+ char *d;
+ int len;
+
+ if (*str!='"')
+   {
+    mi_error=MI_PARSER;
+    return 0;
+   }
+ str++;
+ /* Meassure. */
+ for (s=str, len=0; *s && !EndOfStr(s); s++)
+    {
+     if (*s=='\\')
+       {
+        if (!*s)
+          {
+           mi_error=MI_PARSER;
+           return 0;
+          }
+        s++;
+       }
+     len++;
+    }
+ /* Copy. */
+ r->type=t_const;
+ d=r->v.cstr=mi_malloc(len+1);
+ if (!r->v.cstr)
+    return 0;
+ for (s=str; *s && !EndOfStr(s); s++, d++)
+    {
+     if (*s=='\\')
+       {
+        s++;
+        switch (*s)
+          {
+           case 'n':
+                *d='\n';
+                break;
+           case 't':
+                *d='\t';
+                break;
+           default:
+                *d=*s;
+          }
+       }
+     else
+        *d=*s;
+    }
+ *d=0;
+ if (end)
+    *end=s+1;
+
+ return 1;
+}
+
+/* TODO: What's a valid variable name?
+   I'll assume a-zA-Z0-9_- */
+inline
+int mi_is_var_name_char(char c)
+{
+ return isalnum(c) || c=='-' || c=='_';
+}
+
+char *mi_get_var_name(const char *str, const char **end)
+{
+ const char *s;
+ char *r;
+ int l;
+ /* Meassure. */
+ for (s=str; *s && mi_is_var_name_char(*s); s++);
+ if (*s!='=')
+   {
+    mi_error=MI_PARSER;
+    return NULL;
+   }
+ /* Allocate. */
+ l=s-str;
+ r=mi_malloc(l+1);
+ /* Copy. */
+ memcpy(r,str,l);
+ r[l]=0;
+ if (end)
+    *end=s+1;
+ return r;
+}
+
+
+int mi_get_list_res(mi_results *r, const char *str, const char **end, char closeC)
+{
+ mi_results *last_r, *rs;
+
+ last_r=NULL;
+ do
+   {
+    rs=mi_get_result(str,&str);
+    if (last_r)
+       last_r->next=rs;
+    else
+       r->v.rs=rs;
+    last_r=rs;
+    if (*str==closeC)
+      {
+       *end=str+1;
+       return 1;
+      }
+    if (*str!=',')
+       break;
+    str++;
+   }
+ while (1);
+
+ mi_error=MI_PARSER;
+ return 0;
+}
+
+#ifdef __APPLE__
+int mi_get_tuple_val(mi_results *r, const char *str, const char **end)
+{
+ mi_results *last_r, *rs;
+
+ last_r=NULL;
+ do
+   {
+    rs=mi_alloc_results();
+    if (!rs || !mi_get_value(rs,str,&str))
+      {
+       mi_free_results(rs);
+       return 0;
+      }
+    /* Note that rs->var is NULL, that indicates that's just a value and not
+       a result. */
+    if (last_r)
+       last_r->next=rs;
+    else
+       r->v.rs=rs;
+    last_r=rs;
+    if (*str=='}')
+      {
+       *end=str+1;
+       return 1;
+      }
+    if (*str!=',')
+       break;
+    str++;
+   }
+ while (1);
+
+ mi_error=MI_PARSER;
+ return 0;
+}
+#endif /* __APPLE__ */
+
+int mi_get_tuple(mi_results *r, const char *str, const char **end)
+{
+ if (*str!='{')
+   {
+    mi_error=MI_PARSER;
+    return 0;
+   }
+ r->type=t_tuple;
+ str++;
+ if (*str=='}')
+   {/* Special case: empty tuple */
+    *end=str+1;
+    return 1;
+   }
+ #ifdef __APPLE__
+ if (mi_is_var_name_char(*str))
+    return mi_get_list_res(r,str,end,'}');
+ return mi_get_tuple_val(r,str,end);
+ #else /* __APPLE__ */
+ return mi_get_list_res(r,str,end,'}');
+ #endif /* __APPLE__ */
+}
+
+int mi_get_list_val(mi_results *r, const char *str, const char **end)
+{
+ mi_results *last_r, *rs;
+
+ last_r=NULL;
+ do
+   {
+    rs=mi_alloc_results();
+    if (!rs || !mi_get_value(rs,str,&str))
+      {
+       mi_free_results(rs);
+       return 0;
+      }
+    /* Note that rs->var is NULL, that indicates that's just a value and not
+       a result. */
+    if (last_r)
+       last_r->next=rs;
+    else
+       r->v.rs=rs;
+    last_r=rs;
+    if (*str==']')
+      {
+       *end=str+1;
+       return 1;
+      }
+    if (*str!=',')
+       break;
+    str++;
+   }
+ while (1);
+
+ mi_error=MI_PARSER;
+ return 0;
+}
+
+int mi_get_list(mi_results *r, const char *str, const char **end)
+{
+ if (*str!='[')
+   {
+    mi_error=MI_PARSER;
+    return 0;
+   }
+ r->type=t_list;
+ str++;
+ if (*str==']')
+   {/* Special case: empty list */
+    *end=str+1;
+    return 1;
+   }
+ /* Comment: I think they could choose () for values. Is confusing in this way. */
+ if (mi_is_var_name_char(*str))
+    return mi_get_list_res(r,str,end,']');
+ return mi_get_list_val(r,str,end);
+}
+
+int mi_get_value(mi_results *r, const char *str, const char **end)
+{
+ switch (str[0])
+   {
+    case '"':
+         return mi_get_cstring_r(r,str,end);
+    case '{':
+         return mi_get_tuple(r,str,end);
+    case '[':
+         return mi_get_list(r,str,end);
+   }
+ mi_error=MI_PARSER;
+ return 0;
+}
+
+mi_results *mi_get_result(const char *str, const char **end)
+{
+ char *var;
+ mi_results *r;
+
+ var=mi_get_var_name(str,&str);
+ if (!var)
+    return NULL;
+
+ r=mi_alloc_results();
+ if (!r)
+   {
+    free(var);
+    return NULL;
+   }
+ r->var=var;
+
+ if (!mi_get_value(r,str,end))
+   {
+    mi_free_results(r);
+    return NULL;
+   }
+
+ return r;
+}
+
+mi_output *mi_get_results_alone(mi_output *r,const char *str)
+{
+ mi_results *last_r, *rs;
+
+ /* * results */
+ last_r=NULL;
+ do
+   {
+    if (!*str)
+       return r;
+    if (*str!=',')
+      {
+       mi_error=MI_PARSER;
+       break;
+      }
+    str++;
+    rs=mi_get_result(str,&str);
+    if (!rs)
+       break;
+    if (!last_r)
+       r->c=rs;
+    else
+       last_r->next=rs;
+    last_r=rs;
+   }
+ while (1);
+ mi_free_output(r);
+ return NULL;
+}
+
+mi_output *mi_parse_result_record(mi_output *r,const char *str)
+{
+ r->type=MI_T_RESULT_RECORD;
+
+ /* Solve the result-class. */
+ if (strncmp(str,"done",4)==0)
+   {
+    str+=4;
+    r->tclass=MI_CL_DONE;
+   }
+ else if (strncmp(str,"running",7)==0)
+   {
+    str+=7;
+    r->tclass=MI_CL_RUNNING;
+   }
+ else if (strncmp(str,"connected",9)==0)
+   {
+    str+=9;
+    r->tclass=MI_CL_CONNECTED;
+   }
+ else if (strncmp(str,"error",5)==0)
+   {
+    str+=5;
+    r->tclass=MI_CL_ERROR;
+   }
+ else if (strncmp(str,"exit",4)==0)
+   {
+    str+=4;
+    r->tclass=MI_CL_EXIT;
+   }
+ else
+   {
+    mi_error=MI_UNKNOWN_RESULT;
+    return NULL;
+   }
+
+ return mi_get_results_alone(r,str);
+}
+
+mi_output *mi_parse_asyn(mi_output *r,const char *str)
+{
+ r->type=MI_T_OUT_OF_BAND;
+ r->stype=MI_ST_ASYNC;
+ /* async-class. */
+ if (strncmp(str,"stopped",7)==0)
+   {
+    r->tclass=MI_CL_STOPPED;
+    str+=7;
+    return mi_get_results_alone(r,str);
+   }
+ if (strncmp(str,"download",8)==0)
+   {
+    r->tclass=MI_CL_DOWNLOAD;
+    str+=8;
+    return mi_get_results_alone(r,str);
+   }
+ mi_error=MI_UNKNOWN_ASYNC;
+ mi_free_output(r);
+ return NULL;
+}
+
+mi_output *mi_parse_exec_asyn(mi_output *r,const char *str)
+{
+ r->sstype=MI_SST_EXEC;
+ return mi_parse_asyn(r,str);
+}
+
+mi_output *mi_parse_status_asyn(mi_output *r,const char *str)
+{
+ r->sstype=MI_SST_STATUS;
+ return mi_parse_asyn(r,str);
+}
+
+mi_output *mi_parse_notify_asyn(mi_output *r,const char *str)
+{
+ r->sstype=MI_SST_NOTIFY;
+ return mi_parse_asyn(r,str);
+}
+
+mi_output *mi_console(mi_output *r,const char *str)
+{
+ r->type=MI_T_OUT_OF_BAND;
+ r->stype=MI_ST_STREAM;
+ r->c=mi_alloc_results();
+ if (!r->c || !mi_get_cstring_r(r->c,str,NULL))
+   {
+    mi_free_output(r);
+    return NULL;
+   }
+ return r;
+}
+
+mi_output *mi_console_stream(mi_output *r,const char *str)
+{
+ r->sstype=MI_SST_CONSOLE;
+ return mi_console(r,str);
+}
+
+mi_output *mi_target_stream(mi_output *r,const char *str)
+{
+ r->sstype=MI_SST_TARGET;
+ return mi_console(r,str);
+}
+
+mi_output *mi_log_stream(mi_output *r,const char *str)
+{
+ r->sstype=MI_SST_LOG;
+ return mi_console(r,str);
+}
+
+mi_output *mi_parse_gdb_output(const char *str)
+{
+ char type=str[0];
+
+ mi_output *r=mi_alloc_output();
+ if (!r)
+   {
+    mi_error=MI_OUT_OF_MEMORY;
+    return NULL;
+   }
+ str++;
+ switch (type)
+   {
+    case '^':
+         return mi_parse_result_record(r,str);
+    case '*':
+         return mi_parse_exec_asyn(r,str);
+    case '+':
+         return mi_parse_status_asyn(r,str);
+    case '=':
+         return mi_parse_notify_asyn(r,str);
+    case '~':
+         return mi_console_stream(r,str);
+    case '@':
+         return mi_target_stream(r,str);
+    case '&':
+         return mi_log_stream(r,str);
+   }   
+ mi_error=MI_PARSER;
+ return NULL;
+}
+
+mi_output *mi_get_rrecord(mi_output *r)
+{
+ if (!r)
+    return NULL;
+ while (r)
+   {
+    if (r->type==MI_T_RESULT_RECORD)
+       return r;
+    r=r->next;
+   }
+ return r;
+}
+
+mi_results *mi_get_var_r(mi_results *r, const char *var)
+{
+ while (r)
+   {
+    if (strcmp(r->var,var)==0)
+       return r;
+    r=r->next;
+   }
+ return NULL;
+}
+
+mi_results *mi_get_var(mi_output *res, const char *var)
+{
+ if (!res)
+    return NULL;
+ return mi_get_var_r(res->c,var);
+}
+
+int mi_get_async_stop_reason(mi_output *r, char **reason)
+{
+ int found_stopped=0;
+
+ *reason=NULL;
+ while (r)
+   {
+    if (r->type==MI_T_RESULT_RECORD && r->tclass==MI_CL_ERROR)
+      {
+       if (r->c->type==t_const)
+          *reason=r->c->v.cstr;
+       return 0;
+      }
+    if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
+        r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
+      {
+       mi_results *p=r->c;
+       found_stopped=1;
+       while (p)
+         {
+          if (strcmp(p->var,"reason")==0)
+            {
+             *reason=p->v.cstr;
+             return 1;
+            }
+          p=p->next;
+         }
+      }
+    r=r->next;
+   }
+ if (*reason==NULL && found_stopped)
+   {
+    *reason=strdup("unknown (temp bkpt?)");
+    return 1;
+   }
+ return 0;
+}
+
+mi_frames *mi_get_async_frame(mi_output *r)
+{
+ while (r)
+   {
+    if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
+        r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
+      {
+       mi_results *p=r->c;
+       while (p)
+         {
+          if (strcmp(p->var,"frame")==0)
+             return mi_parse_frame(p->v.rs);
+          p=p->next;
+         }
+      }
+    r=r->next;
+   }
+ return NULL;
+}
+
+int mi_res_simple(mi_h *h, int tclass, int accert_ret)
+{
+ mi_output *r, *res;
+ int ret=0;
+
+ r=mi_get_response_blk(h);
+ res=mi_get_rrecord(r);
+
+ if (res)
+    ret=res->tclass==tclass;
+ mi_free_output(r);
+
+ return ret;
+}
+
+
+int mi_res_simple_done(mi_h *h)
+{
+ return mi_res_simple(h,MI_CL_DONE,0);
+}
+
+int mi_res_simple_exit(mi_h *h)
+{
+ return mi_res_simple(h,MI_CL_EXIT,1);
+}
+
+int mi_res_simple_running(mi_h *h)
+{
+ return mi_res_simple(h,MI_CL_RUNNING,0);
+}
+
+int mi_res_simple_connected(mi_h *h)
+{
+ return mi_res_simple(h,MI_CL_CONNECTED,0);
+}
+
+mi_results *mi_res_var(mi_h *h, const char *var, int tclass)
+{
+ mi_output *r, *res;
+ mi_results *the_var=NULL;
+
+ r=mi_get_response_blk(h);
+ /* All the code that follows is "NULL" tolerant. */
+ /* Look for the result-record. */
+ res=mi_get_rrecord(r);
+ /* Look for the desired var. */
+ if (res && res->tclass==tclass)
+    the_var=mi_get_var(res,var);
+ /* Release all but the one we want. */
+ mi_free_output_but(r,NULL,the_var);
+ return the_var;
+}
+
+mi_results *mi_res_done_var(mi_h *h, const char *var)
+{
+ return mi_res_var(h,var,MI_CL_DONE);
+}
+
+mi_frames *mi_parse_frame(mi_results *c)
+{
+ mi_frames *res=mi_alloc_frames();
+ char *end;
+
+ if (res)
+   {
+    while (c)
+      {
+       if (c->type==t_const)
+         {
+          if (strcmp(c->var,"level")==0)
+             res->level=atoi(c->v.cstr);
+          else if (strcmp(c->var,"addr")==0)
+             res->addr=(void *)strtoul(c->v.cstr,&end,0);
+          else if (strcmp(c->var,"func")==0)
+            {
+             res->func=c->v.cstr;
+             c->v.cstr=NULL;
+            }
+          else if (strcmp(c->var,"file")==0)
+            {
+             res->file=c->v.cstr;
+             c->v.cstr=NULL;
+            }
+          else if (strcmp(c->var,"from")==0)
+            {
+             res->from=c->v.cstr;
+             c->v.cstr=NULL;
+            }
+          else if (strcmp(c->var,"line")==0)
+             res->line=atoi(c->v.cstr);
+         }
+       else if (c->type==t_list && strcmp(c->var,"args")==0)
+         {
+          res->args=c->v.rs;
+          c->v.rs=NULL;
+         }
+       c=c->next;
+      }
+   }
+ return res;
+}
+
+mi_frames *mi_res_frame(mi_h *h)
+{
+ mi_results *r=mi_res_done_var(h,"frame");
+ mi_frames *f=NULL;
+
+ if (r && r->type==t_tuple)
+    f=mi_parse_frame(r->v.rs);
+ mi_free_results(r);
+ return f;
+}
+
+mi_frames *mi_res_frames_array(mi_h *h, const char *var)
+{
+ mi_results *r=mi_res_done_var(h,var), *c;
+ mi_frames *res=NULL, *nframe, *last=NULL;
+
+ if (!r)
+    return NULL;
+#ifdef __APPLE__
+ if (r->type!=t_list && r->type!=t_tuple)
+#else
+ if (r->type!=t_list)
+#endif
+   {
+    mi_free_results(r);
+    return NULL;
+   }
+ c=r->v.rs;
+ while (c)
+   {
+    if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
+      {
+       nframe=mi_parse_frame(c->v.rs);
+       if (nframe)
+         {
+          if (!last)
+             res=nframe;
+          else
+             last->next=nframe;
+          last=nframe;
+         }
+      }
+    c=c->next;
+   }
+ mi_free_results(r);
+ return res;
+}
+
+mi_frames *mi_res_frames_list(mi_h *h)
+{
+ mi_output *r, *res;
+ mi_frames *ret=NULL, *nframe, *last=NULL;
+ mi_results *c;
+
+ r=mi_get_response_blk(h);
+ res=mi_get_rrecord(r);
+ if (res && res->tclass==MI_CL_DONE)
+   {
+    c=res->c;
+    while (c)
+      {
+       if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
+         {
+          nframe=mi_parse_frame(c->v.rs);
+          if (nframe)
+            {
+             if (!last)
+                ret=nframe;
+             else
+                last->next=nframe;
+             last=nframe;
+            }
+         }
+       c=c->next;
+      }
+   }
+ mi_free_output(r);
+ return ret;
+}
+
+int mi_get_thread_ids(mi_output *res, int **list)
+{
+ mi_results *vids, *lids;
+ int ids=-1, i;
+
+ *list=NULL;
+ vids=mi_get_var(res,"number-of-threads");
+ lids=mi_get_var(res,"thread-ids");
+ if (vids && vids->type==t_const &&
+     lids && lids->type==t_tuple)
+   {
+    ids=atoi(vids->v.cstr);
+    if (ids)
+      {
+       int *lst;
+       lst=(int *)mi_calloc(ids,sizeof(int));
+       if (lst)
+         {
+          lids=lids->v.rs;
+          i=0;
+          while (lids)
+            {
+             if (strcmp(lids->var,"thread-id")==0 && lids->type==t_const)
+                lst[i++]=atoi(lids->v.cstr);
+             lids=lids->next;
+            }
+          *list=lst;
+         }
+       else
+          ids=-1;
+      }
+   }
+ return ids;
+}
+
+int mi_res_thread_ids(mi_h *h, int **list)
+{
+ mi_output *r, *res;
+ int ids=-1;
+
+ r=mi_get_response_blk(h);
+ res=mi_get_rrecord(r);
+ if (res && res->tclass==MI_CL_DONE)
+    ids=mi_get_thread_ids(res,list);
+ mi_free_output(r);
+ return ids;
+}
+
+enum mi_gvar_lang mi_lang_str_to_enum(const char *lang)
+{
+ enum mi_gvar_lang lg=lg_unknown;
+
+ if (strcmp(lang,"C")==0)
+    lg=lg_c;
+ else if (strcmp(lang,"C++")==0)
+    lg=lg_cpp;
+ else if (strcmp(lang,"Java")==0)
+    lg=lg_java;
+
+ return lg;
+}
+
+const char *mi_lang_enum_to_str(enum mi_gvar_lang lang)
+{
+ const char *lg;
+
+ switch (lang)
+   {
+    case lg_c:
+         lg="C";
+         break;
+    case lg_cpp:
+         lg="C++";
+         break;
+    case lg_java:
+         lg="Java";
+         break;
+    /*case lg_unknown:*/
+    default:
+         lg="unknown";
+         break;
+   }
+ return lg;
+}
+
+enum mi_gvar_fmt mi_format_str_to_enum(const char *format)
+{
+ enum mi_gvar_fmt fmt=fm_natural;
+
+ if (strcmp(format,"binary")==0)
+    fmt=fm_binary;
+ else if (strcmp(format,"decimal")==0)
+    fmt=fm_decimal;
+ else if (strcmp(format,"hexadecimal")==0)
+    fmt=fm_hexadecimal;
+ else if (strcmp(format,"octal")==0)
+    fmt=fm_octal;
+
+ return fmt;
+}
+
+const char *mi_format_enum_to_str(enum mi_gvar_fmt format)
+{
+ const char *fmt;
+
+ switch (format)
+   {
+    case fm_natural:
+         fmt="natural";
+         break;
+    case fm_binary:
+         fmt="binary";
+         break;
+    case fm_decimal:
+         fmt="decimal";
+         break;
+    case fm_hexadecimal:
+         fmt="hexadecimal";
+         break;
+    case fm_octal:
+         fmt="octal";
+         break;
+    case fm_raw:
+         fmt="raw";
+         break;
+    default:
+         fmt="unknown";
+   }
+ return fmt;
+}
+
+char mi_format_enum_to_char(enum mi_gvar_fmt format)
+{
+ char fmt;
+
+ switch (format)
+   {
+    case fm_natural:
+         fmt='N';
+         break;
+    case fm_binary:
+         fmt='t';
+         break;
+    case fm_decimal:
+         fmt='d';
+         break;
+    case fm_hexadecimal:
+         fmt='x';
+         break;
+    case fm_octal:
+         fmt='o';
+         break;
+    case fm_raw:
+         fmt='r';
+         break;
+    default:
+         fmt=' ';
+   }
+ return fmt;
+}
+
+mi_gvar *mi_get_gvar(mi_output *o, mi_gvar *cur, const char *expression)
+{
+ mi_results *r;
+ mi_gvar *res=cur ? cur : mi_alloc_gvar();
+ int l;
+
+ if (!res)
+    return res;
+ r=o->c;
+ if (expression)
+    res->exp=strdup(expression);
+ while (r)
+   {
+    if (r->type==t_const)
+      {
+       if (strcmp(r->var,"name")==0)
+         {
+          free(res->name);
+          res->name=r->v.cstr;
+          r->v.cstr=NULL;
+         }
+       else if (strcmp(r->var,"numchild")==0)
+         {
+          res->numchild=atoi(r->v.cstr);
+         }
+       else if (strcmp(r->var,"type")==0)
+         {
+          free(res->type);
+          res->type=r->v.cstr;
+          r->v.cstr=NULL;
+          l=strlen(res->type);
+          if (l && res->type[l-1]=='*')
+             res->ispointer=1;
+         }
+       else if (strcmp(r->var,"lang")==0)
+         {
+          res->lang=mi_lang_str_to_enum(r->v.cstr);
+         }
+       else if (strcmp(r->var,"exp")==0)
+         {
+          free(res->exp);
+          res->exp=r->v.cstr;
+          r->v.cstr=NULL;
+         }
+       else if (strcmp(r->var,"format")==0)
+         {
+          res->format=mi_format_str_to_enum(r->v.cstr);
+         }
+       else if (strcmp(r->var,"attr")==0)
+         { /* Note: gdb 6.1.1 have only this: */
+          if (strcmp(r->v.cstr,"editable")==0)
+             res->attr=MI_ATTR_EDITABLE;
+          else /* noneditable */
+             res->attr=MI_ATTR_NONEDITABLE;
+         }
+      }
+    r=r->next;
+   }
+ return res;
+}
+
+mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression)
+{
+ mi_output *r, *res;
+ mi_gvar *gvar=NULL;
+
+ r=mi_get_response_blk(h);
+ res=mi_get_rrecord(r);
+ if (res && res->tclass==MI_CL_DONE)
+    gvar=mi_get_gvar(res,cur,expression);
+ mi_free_output(r);
+ return gvar;
+}
+
+mi_gvar_chg *mi_get_gvar_chg(mi_results *r)
+{
+ mi_gvar_chg *n;
+
+ if (r->type!=t_const)
+    return NULL;
+ n=mi_alloc_gvar_chg();
+ if (n)
+   {
+    while (r)
+      {
+       if (r->type==t_const)
+         {
+          if (strcmp(r->var,"name")==0)
+            {
+             n->name=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"in_scope")==0)
+            {
+             n->in_scope=strcmp(r->v.cstr,"true")==0;
+            }
+          else if (strcmp(r->var,"new_type")==0)
+            {
+             n->new_type=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"new_num_children")==0)
+            {
+             n->new_num_children=atoi(r->v.cstr);
+            }
+          // type_changed="false" is the default
+         }
+       r=r->next;
+      }
+   }
+ return n;
+}
+
+int mi_res_changelist(mi_h *h, mi_gvar_chg **changed)
+{
+ mi_gvar_chg *last, *n;
+ mi_results *res=mi_res_done_var(h,"changelist"), *r;
+ int count=0;
+
+ *changed=NULL;
+ if (!res)
+    return 0;
+ last=NULL;
+ count=1;
+ n=NULL;
+ r=res->v.rs;
+
+ if (res->type==t_list)
+   {// MI v2 a list of tuples
+    while (r)
+      {
+       if (r->type==t_tuple)
+         {
+          n=mi_get_gvar_chg(r->v.rs);
+          if (n)
+            {
+             if (last)
+                last->next=n;
+             else
+                *changed=n;
+             last=n;
+             count++;
+            }
+         }
+       r=r->next;
+      }
+   }
+ else if (res->type==t_tuple)
+   {// MI v1 a tuple with all together *8-P
+    while (r)
+      {
+       if (r->type==t_const) /* Just in case. */
+         {/* Get one var. */
+          if (strcmp(r->var,"name")==0)
+            {
+             if (n)
+               {/* Add to the list*/
+                if (last)
+                   last->next=n;
+                else
+                   *changed=n;
+                last=n;
+                count++;
+               }
+             n=mi_alloc_gvar_chg();
+             if (!n)
+               {
+                mi_free_gvar_chg(*changed);
+                return 0;
+               }
+             n->name=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"in_scope")==0)
+            {
+             n->in_scope=strcmp(r->v.cstr,"true")==0;
+            }
+          else if (strcmp(r->var,"new_type")==0)
+            {
+             n->new_type=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"new_num_children")==0)
+            {
+             n->new_num_children=atoi(r->v.cstr);
+            }
+          // type_changed="false" is the default
+         }
+       r=r->next;
+      }
+    if (n)
+      {/* Add to the list*/
+       if (last)
+          last->next=n;
+       else
+          *changed=n;
+       last=n;
+       count++;
+      }
+   }
+ mi_free_results(res);
+
+ return count;
+}
+
+int mi_get_children(mi_results *ch, mi_gvar *v)
+{
+ mi_gvar *cur=NULL, *aux;
+ int i=0, count=v->numchild, l;
+
+ while (ch)
+   {
+    if (strcmp(ch->var,"child")==0 && ch->type==t_tuple && i<count)
+      {
+       mi_results *r=ch->v.rs;
+       aux=mi_alloc_gvar();
+       if (!aux)
+          return 0;
+       if (!v->child)
+          v->child=aux;
+       else
+          cur->next=aux;
+       cur=aux;
+       cur->parent=v;
+       cur->depth=v->depth+1;
+
+       while (r)
+         {
+          if (r->type==t_const)
+            {
+             if (strcmp(r->var,"name")==0)
+               {
+                cur->name=r->v.cstr;
+                r->v.cstr=NULL;
+               }
+             else if (strcmp(r->var,"exp")==0)
+               {
+                cur->exp=r->v.cstr;
+                r->v.cstr=NULL;
+               }
+             else if (strcmp(r->var,"type")==0)
+               {
+                cur->type=r->v.cstr;
+                r->v.cstr=NULL;
+                l=strlen(cur->type);
+                if (l && cur->type[l-1]=='*')
+                   cur->ispointer=1;
+               }
+             else if (strcmp(r->var,"value")==0)
+               {
+                cur->value=r->v.cstr;
+                r->v.cstr=NULL;
+               }                     
+             else if (strcmp(r->var,"numchild")==0)
+               {
+                cur->numchild=atoi(r->v.cstr);
+               }
+            }
+          r=r->next;
+         }
+       i++;
+      }
+    ch=ch->next;
+   }
+ v->vischild=i;
+ v->opened=1;
+ return i==v->numchild;
+}
+
+int mi_res_children(mi_h *h, mi_gvar *v)
+{
+ mi_output *r, *res;
+ int ok=0;
+
+ r=mi_get_response_blk(h);
+ res=mi_get_rrecord(r);
+ if (res && res->tclass==MI_CL_DONE)
+   {
+    mi_results *num=mi_get_var(res,"numchild");
+    if (num && num->type==t_const)
+      {
+       v->numchild=atoi(num->v.cstr);
+       if (v->child)
+         {
+          mi_free_gvar(v->child);
+          v->child=NULL;
+         }
+       if (v->numchild)
+         {
+          mi_results *ch =mi_get_var(res,"children");
+          if (ch && ch->type!=t_const) /* MI v1 tuple, MI v2 list */
+             ok=mi_get_children(ch->v.rs,v);
+         }
+       else
+          ok=1;
+      }
+   }
+ mi_free_output(r);
+ return ok;
+}
+
+mi_bkpt *mi_get_bkpt(mi_results *p)
+{
+ mi_bkpt *res;
+ char *end;
+
+ res=mi_alloc_bkpt();
+ if (!res)
+    return NULL;
+ while (p)
+   {
+    if (p->type==t_const && p->var)
+      {
+       if (strcmp(p->var,"number")==0)
+          res->number=atoi(p->v.cstr);
+       else if (strcmp(p->var,"type")==0)
+         {
+          if (strcmp(p->v.cstr,"breakpoint")==0)
+             res->type=t_breakpoint;
+          else
+             res->type=t_unknown;
+         }
+       else if (strcmp(p->var,"disp")==0)
+         {
+          if (strcmp(p->v.cstr,"keep")==0)
+             res->disp=d_keep;
+          else if (strcmp(p->v.cstr,"del")==0)
+             res->disp=d_del;
+          else
+             res->disp=d_unknown;
+         }
+       else if (strcmp(p->var,"enabled")==0)
+          res->enabled=p->v.cstr[0]=='y';
+       else if (strcmp(p->var,"addr")==0)
+          res->addr=(void *)strtoul(p->v.cstr,&end,0);
+       else if (strcmp(p->var,"func")==0)
+         {
+          res->func=p->v.cstr;
+          p->v.cstr=NULL;
+         }
+       else if (strcmp(p->var,"file")==0)
+         {
+          res->file=p->v.cstr;
+          p->v.cstr=NULL;
+         }
+       else if (strcmp(p->var,"line")==0)
+          res->line=atoi(p->v.cstr);
+       else if (strcmp(p->var,"times")==0)
+          res->times=atoi(p->v.cstr);
+       else if (strcmp(p->var,"ignore")==0)
+          res->ignore=atoi(p->v.cstr);
+       else if (strcmp(p->var,"cond")==0)
+         {
+          res->cond=p->v.cstr;
+          p->v.cstr=NULL;
+         }
+      }
+    p=p->next;
+   }
+ return res;
+}
+
+mi_bkpt *mi_res_bkpt(mi_h *h)
+{
+ mi_results *r=mi_res_done_var(h,"bkpt");
+ mi_bkpt *b=NULL;
+
+ if (r && r->type==t_tuple)
+    b=mi_get_bkpt(r->v.rs);
+ mi_free_results(r);
+ return b;
+}
+
+mi_wp *mi_get_wp(mi_results *p, enum mi_wp_mode m)
+{
+ mi_wp *res=mi_alloc_wp();
+
+ if (res)
+   {
+    res->mode=m;
+    while (p)
+      {
+       if (p->type==t_const && p->var)
+         {
+          if (strcmp(p->var,"number")==0)
+            {
+             res->number=atoi(p->v.cstr);
+             res->enabled=1;
+            }
+          else if (strcmp(p->var,"exp")==0)
+            {
+             res->exp=p->v.cstr;
+             p->v.cstr=NULL;
+            }
+         }
+       p=p->next;
+      }
+   }
+ return res;
+}
+
+mi_wp *mi_parse_wp_res(mi_output *r)
+{
+ mi_results *p;
+ enum mi_wp_mode m=wm_unknown;
+
+ /* The info is in a result wpt=... */
+ p=r->c;
+ while (p)
+   {
+    if (p->var)
+      {
+       if (strcmp(p->var,"wpt")==0)
+          m=wm_write;
+       else if (strcmp(p->var,"hw-rwpt")==0)
+          m=wm_read;
+       else if (strcmp(p->var,"hw-awpt")==0)
+          m=wm_rw;
+       if (m!=wm_unknown)
+          break;
+      }
+    p=p->next;
+   }
+ if (!p || p->type!=t_tuple)
+    return NULL;
+ /* Scan the values inside it. */
+ return mi_get_wp(p->v.rs,m);
+}
+
+mi_wp *mi_res_wp(mi_h *h)
+{
+ mi_output *r, *res;
+ mi_wp *ret=NULL;
+
+ r=mi_get_response_blk(h);
+ res=mi_get_rrecord(r);
+
+ if (res)
+    ret=mi_parse_wp_res(res);
+
+ mi_free_output(r);
+ return ret;
+}
+
+char *mi_res_value(mi_h *h)
+{
+ mi_results *r=mi_res_done_var(h,"value");
+ char *s=NULL;
+
+ if (r && r->type==t_const)
+   {
+    s=r->v.cstr;
+    r->v.rs=NULL;
+   }
+ mi_free_results(r);
+ return s;
+}
+
+mi_output *mi_get_stop_record(mi_output *r)
+{
+ while (r)
+   {
+    if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
+        r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
+       return r;
+    r=r->next;
+   }
+ return r;
+}
+
+static
+char *reason_names[]=
+{
+ "breakpoint-hit",
+ "watchpoint-trigger",
+ "read-watchpoint-trigger",
+ "access-watchpoint-trigger",
+ "watchpoint-scope",
+ "function-finished",
+ "location-reached",
+ "end-stepping-range",
+ "exited-signalled",
+ "exited",
+ "exited-normally",
+ "signal-received"
+};
+
+static
+enum mi_stop_reason reason_values[]=
+{
+ sr_bkpt_hit,
+ sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
+ sr_function_finished, sr_location_reached, sr_end_stepping_range,
+ sr_exited_signalled, sr_exited, sr_exited_normally,
+ sr_signal_received
+};
+
+static
+char *reason_expl[]=
+{
+ "Hit a breakpoint",
+ "Write watchpoint",
+ "Read watchpoint",
+ "Access watchpoint",
+ "Watchpoint out of scope",
+ "Function finished",
+ "Location reached",
+ "End of stepping",
+ "Exited signalled",
+ "Exited with error",
+ "Exited normally",
+ "Signal received"
+};
+
+enum mi_stop_reason mi_reason_str_to_enum(const char *s)
+{
+ int i;
+
+ for (i=0; i<sizeof(reason_names)/sizeof(char *); i++)
+     if (strcmp(reason_names[i],s)==0)
+        return reason_values[i];
+ return sr_unknown;
+}
+
+const char *mi_reason_enum_to_str(enum mi_stop_reason r)
+{
+ int i;
+
+ if (r==sr_unknown)
+    return "Unknown (temp bkp?)";
+ for (i=0; i<sizeof(reason_values)/sizeof(char *); i++)
+     if (reason_values[i]==r)
+        return reason_expl[i];
+ return NULL;
+}
+
+mi_stop *mi_get_stopped(mi_results *r)
+{
+ mi_stop *res=mi_alloc_stop();
+
+ if (res)
+   {
+    while (r)
+      {
+       if (r->type==t_const)
+         {
+          if (strcmp(r->var,"reason")==0)
+             res->reason=mi_reason_str_to_enum(r->v.cstr);
+          else if (!res->have_thread_id && strcmp(r->var,"thread-id")==0)
+            {
+             res->have_thread_id=1;
+             res->thread_id=atoi(r->v.cstr);
+            }
+          else if (!res->have_bkptno && strcmp(r->var,"bkptno")==0)
+            {
+             res->have_bkptno=1;
+             res->bkptno=atoi(r->v.cstr);
+            }
+          else if (!res->have_bkptno && strcmp(r->var,"wpnum")==0)
+            {
+             res->have_wpno=1;
+             res->wpno=atoi(r->v.cstr);
+            }
+          else if (strcmp(r->var,"gdb-result-var")==0)
+            {
+             res->gdb_result_var=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"return-value")==0)
+            {
+             res->return_value=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"signal-name")==0)
+            {
+             res->signal_name=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (strcmp(r->var,"signal-meaning")==0)
+            {
+             res->signal_meaning=r->v.cstr;
+             r->v.cstr=NULL;
+            }
+          else if (!res->have_exit_code && strcmp(r->var,"exit-code")==0)
+            {
+             res->have_exit_code=1;
+             res->exit_code=atoi(r->v.cstr);
+            }
+         }
+       else // tuple or list
+         {
+          if (strcmp(r->var,"frame")==0)
+             res->frame=mi_parse_frame(r->v.rs);
+          else if (!res->wp && strcmp(r->var,"wpt")==0)
+             res->wp=mi_get_wp(r->v.rs,wm_write);
+          else if (!res->wp && strcmp(r->var,"hw-rwpt")==0)
+             res->wp=mi_get_wp(r->v.rs,wm_read);
+          else if (!res->wp && strcmp(r->var,"hw-awpt")==0)
+             res->wp=mi_get_wp(r->v.rs,wm_rw);
+          else if (!(res->wp_old || res->wp_val) && strcmp(r->var,"value")==0)
+             {
+              mi_results *p=r->v.rs;
+              while (p)
+                {
+                 if (strcmp(p->var,"value")==0 || strcmp(p->var,"new")==0)
+                   {
+                    res->wp_val=p->v.cstr;
+                    p->v.cstr=NULL;
+                   }
+                 else if (strcmp(p->var,"old")==0)
+                   {
+                    res->wp_old=p->v.cstr;
+                    p->v.cstr=NULL;
+                   }
+                 p=p->next;
+                }
+             }
+         }
+       r=r->next;
+      }
+   }
+ return res;
+}
+
+mi_stop *mi_res_stop(mi_h *h)
+{
+ mi_output *o=mi_retire_response(h);
+ mi_stop *stop=NULL;
+
+ if (o)
+   {
+    mi_output *sr=mi_get_stop_record(o);
+    if (sr)
+       stop=mi_get_stopped(sr->c);
+   }
+ mi_free_output(o);
+
+ return stop;
+}
+
+int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
+                       unsigned long *addr)
+{
+ char *end;
+ mi_results *res=mi_res_done_var(h,"memory"), *r;
+ int ok=0;
+
+ *na=0;
+ r=res;
+ if (r && r->type==t_list && ws==1)
+   {
+    r=r->v.rs;
+    if (r->type!=t_tuple)
+      {
+       mi_free_results(res);
+       return 0;
+      }
+    r=r->v.rs;
+    while (r)
+      {
+       if (r->type==t_list && strcmp(r->var,"data")==0)
+         {
+          mi_results *data=r->v.rs;
+          ok++;
+          if (data && data->type==t_const &&
+              strcmp(data->v.cstr,"N/A")==0)
+             *na=1;
+          else
+             while (data)
+               {
+                if (data->type==t_const)
+                   *(dest++)=strtol(data->v.cstr,&end,0);
+                data=data->next;
+               }
+         }
+       else if (r->type==t_const && strcmp(r->var,"addr")==0)
+         {
+          ok++;
+          if (addr)
+             *addr=strtoul(r->v.cstr,&end,0);
+         }
+       r=r->next;
+      }
+
+   }
+ mi_free_results(res);
+ return ok==2;
+}
+
+mi_asm_insn *mi_parse_insn(mi_results *c)
+{
+ mi_asm_insn *res=NULL, *cur=NULL;
+ mi_results *sub;
+ char *end;
+
+ while (c)
+   {
+    if (c->type==t_tuple)
+      {
+       if (!res)
+          res=cur=mi_alloc_asm_insn();
+       else
+         {
+          cur->next=mi_alloc_asm_insn();
+          cur=cur->next;
+         }
+       if (!cur)
+         {
+          mi_free_asm_insn(res);
+          return NULL;
+         }
+       sub=c->v.rs;
+       while (sub)
+         {
+          if (sub->type==t_const)
+            {
+             if (strcmp(sub->var,"address")==0)
+                cur->addr=(void *)strtoul(sub->v.cstr,&end,0);
+             else if (strcmp(sub->var,"func-name")==0)
+               {
+                cur->func=sub->v.cstr;
+                sub->v.cstr=NULL;
+               }
+             else if (strcmp(sub->var,"offset")==0)
+                cur->offset=atoi(sub->v.cstr);
+             else if (strcmp(sub->var,"inst")==0)
+               {
+                cur->inst=sub->v.cstr;
+                sub->v.cstr=NULL;
+               }
+            }
+          sub=sub->next;
+         }
+      }
+    c=c->next;
+   }
+ return res;
+}
+
+mi_asm_insns *mi_parse_insns(mi_results *c)
+{
+ mi_asm_insns *res=NULL, *cur=NULL;
+ mi_results *sub;
+
+ while (c)
+   {
+    if (c->var)
+      {
+       if (strcmp(c->var,"src_and_asm_line")==0 && c->type==t_tuple)
+         {
+          if (!res)
+             res=cur=mi_alloc_asm_insns();
+          else
+            {
+             cur->next=mi_alloc_asm_insns();
+             cur=cur->next;
+            }
+          if (!cur)
+            {
+             mi_free_asm_insns(res);
+             return NULL;
+            }
+          sub=c->v.rs;
+          while (sub)
+            {
+             if (sub->var)
+               {
+                if (sub->type==t_const)
+                  {
+                   if (strcmp(sub->var,"line")==0)
+                      cur->line=atoi(sub->v.cstr);
+                   else if (strcmp(sub->var,"file")==0)
+                     {
+                      cur->file=sub->v.cstr;
+                      sub->v.cstr=NULL;
+                     }
+                  }
+                else if (sub->type==t_list)
+                  {
+                   if (strcmp(sub->var,"line_asm_insn")==0)
+                      cur->ins=mi_parse_insn(sub->v.rs);
+                  }
+               }
+             sub=sub->next;
+            }
+         }
+      }
+    else
+      {/* No source line, just instructions */
+       res=mi_alloc_asm_insns();
+       res->ins=mi_parse_insn(c);
+       break;
+      }
+    c=c->next;
+   }
+ return res;
+}
+
+
+mi_asm_insns *mi_get_asm_insns(mi_h *h)
+{
+ mi_results *r=mi_res_done_var(h,"asm_insns");
+ mi_asm_insns *f=NULL;
+
+ if (r && r->type==t_list)
+    f=mi_parse_insns(r->v.rs);
+ mi_free_results(r);
+ return f;
+}
+
+mi_chg_reg *mi_parse_list_regs(mi_results *r, int *how_many)
+{
+ mi_results *c=r;
+ int cregs=0;
+ mi_chg_reg *first=NULL, *cur=NULL;
+
+ /* Create the list. */
+ while (c)
+   {
+    if (c->type==t_const && !c->var)
+      {
+       if (first)
+          cur=cur->next=mi_alloc_chg_reg();
+       else
+          first=cur=mi_alloc_chg_reg();
+       cur->name=c->v.cstr;
+       cur->reg=cregs++;
+       c->v.cstr=NULL;
+      }
+    c=c->next;
+   }
+ if (how_many)
+    *how_many=cregs;
+
+ return first;
+}
+
+mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many)
+{
+ mi_results *r=mi_res_done_var(h,"register-names");
+ mi_chg_reg *l=NULL;
+
+ if (r && r->type==t_list)
+    l=mi_parse_list_regs(r->v.rs,how_many);
+ mi_free_results(r);
+ return l;
+}
+
+mi_chg_reg *mi_parse_list_changed_regs(mi_results *r)
+{
+ mi_results *c=r;
+ mi_chg_reg *first=NULL, *cur=NULL;
+
+ /* Create the list. */
+ while (c)
+   {
+    if (c->type==t_const && !c->var)
+      {
+       if (first)
+          cur=cur->next=mi_alloc_chg_reg();
+       else
+          first=cur=mi_alloc_chg_reg();
+       cur->reg=atoi(c->v.cstr);
+      }
+    c=c->next;
+   }
+
+ return first;
+}
+
+mi_chg_reg *mi_get_list_changed_regs(mi_h *h)
+{
+ mi_results *r=mi_res_done_var(h,"changed-registers");
+ mi_chg_reg *changed=NULL;
+
+ if (r && r->type==t_list)
+    changed=mi_parse_list_changed_regs(r->v.rs);
+ mi_free_results(r);
+ return changed;
+}
+
+int mi_parse_reg_values(mi_results *r, mi_chg_reg *l)
+{
+ mi_results *c;
+
+ while (r && l)
+   {
+    if (r->type==t_tuple && !r->var)
+      {
+       c=r->v.rs;
+       while (c)
+         {
+          if (c->type==t_const && c->var)
+            {
+             if (strcmp(c->var,"number")==0)
+               {
+                if (atoi(c->v.cstr)!=l->reg)
+                  {
+                   mi_error=MI_PARSER;
+                   return 0;
+                  }
+               }
+             else if (strcmp(c->var,"value")==0)
+               {
+                l->val=c->v.cstr;
+                c->v.cstr=NULL;
+               }
+            }
+          c=c->next;
+         }
+      }
+    r=r->next;
+    l=l->next;
+   }
+
+ return !l && !r;
+}
+
+int mi_get_reg_values(mi_h *h, mi_chg_reg *l)
+{
+ mi_results *r=mi_res_done_var(h,"register-values");
+ int ok=0;
+
+ if (r && r->type==t_list)
+    ok=mi_parse_reg_values(r->v.rs,l);
+ mi_free_results(r);
+ return ok;
+}
+
+int mi_parse_list_regs_l(mi_results *r, mi_chg_reg *l)
+{
+ while (r && l)
+   {
+    if (r->type==t_const && !r->var)
+      {
+       free(l->name);
+       l->name=r->v.cstr;
+       r->v.cstr=NULL;
+       l=l->next;
+      }
+    r=r->next;
+   }
+
+ return !l && !r;
+}
+
+int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l)
+{
+ mi_results *r=mi_res_done_var(h,"register-names");
+ int ok=0;
+
+ if (r && r->type==t_list)
+    ok=mi_parse_list_regs_l(r->v.rs,l);
+ mi_free_results(r);
+ return ok;
+}
+
+mi_chg_reg *mi_parse_reg_values_l(mi_results *r, int *how_many)
+{
+ mi_results *c;
+ mi_chg_reg *first=NULL, *cur=NULL;
+ *how_many=0;
+
+ while (r)
+   {
+    if (r->type==t_tuple && !r->var)
+      {
+       c=r->v.rs;
+       if (first)
+          cur=cur->next=mi_alloc_chg_reg();
+       else
+          first=cur=mi_alloc_chg_reg();
+       while (c)
+         {
+          if (c->type==t_const && c->var)
+            {
+             if (strcmp(c->var,"number")==0)
+               {
+                cur->reg=atoi(c->v.cstr);
+                (*how_many)++;
+               }
+             else if (strcmp(c->var,"value")==0)
+               {
+                cur->val=c->v.cstr;
+                c->v.cstr=NULL;
+               }
+            }
+          c=c->next;
+         }
+      }
+    r=r->next;
+   }
+
+ return first;
+}
+
+mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many)
+{
+ mi_results *r=mi_res_done_var(h,"register-values");
+ mi_chg_reg *rgs=NULL;
+
+ if (r && r->type==t_list)
+    rgs=mi_parse_reg_values_l(r->v.rs,how_many);
+ mi_free_results(r);
+ return rgs;
+}
+
+
diff --git a/src/prg_control.c b/src/prg_control.c
new file mode 100644 (file)
index 0000000..f2e3a81
--- /dev/null
@@ -0,0 +1,454 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Program control.
+  Comments:
+  GDB/MI commands for the "Program Control" section.@p
+
+@<pre>
+gdb command:                   Implemented?
+
+-exec-abort                    N.A. (*) (kill, but with non-interactive options)
+-exec-arguments                Yes
+-exec-continue                 Yes  ASYNC
+-exec-finish                   Yes  ASYNC
+-exec-interrupt                Yes  ASYNC
+-exec-next                     Yes  ASYNC
+-exec-next-instruction         Yes  ASYNC
+-exec-return                   Yes
+-exec-run                      Yes  ASYNC
+-exec-show-arguments           N.A. (show args) see gmi_stack_info_frame
+-exec-step                     Yes  ASYNC
+-exec-step-instruction         Yes  ASYNC
+-exec-until                    Yes  ASYNC
+-file-exec-and-symbols         Yes
+-file-exec-file                No
+-file-list-exec-sections       N.A. (info file)
+-file-list-exec-source-files   N.A.
+-file-list-shared-libraries    N.A.
+-file-list-symbol-files        N.A.
+-file-symbol-file              Yes
+@</pre>
+
+(*)  gmi_exec_kill implements it, but you should ensure that
+gmi_gdb_set("confirm","off") was called.@p
+
+GDB Bug workaround for -file-exec-and-symbols and -file-symbol-file: This
+is complex, but a real bug. When you set a breakpoint you never know the
+name of the file as it appears in the debug info. So you can be specifying
+an absolute file name or a relative file name. The reference point could be
+different than the one used in the debug info. To solve all the combinations
+gdb does a search trying various combinations. GDB isn't very smart so you
+must at least specify the working directory and the directory where the
+binary is located to get a good chance (+ user options to solve the rest).
+Once you did it gdb can find the file by doing transformations to the
+"canonical" filename. This search works OK for already loaded symtabs
+(symbol tables), but it have a bug when the search is done for psymtabs
+(partial symtabs). The bug is in the use of source_full_path_of (source.c).
+This function calls openp indicating try_cwd_first. It makes the search file
+if the psymtab file name have at least one dirseparator. It means that
+psymtabs for files compiled with relative paths will fail. The search for
+symtabs uses symtab_to_filename, it calls open_source_file which finally
+calls openp without try_cwd_first.@*
+To workaround this bug we must ensure gdb loads *all* the symtabs to memory.
+And here comes another problem -file-exec-and-symbols doesn't support it
+according to docs. In real life that's a wrapper for "file", but as nobody
+can say it won't change we must use the CLI command.
+  
+***************************************************************************/
+
+#include <signal.h>
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_file_exec_and_symbols(mi_h *h, const char *file)
+{
+ if (mi_get_workaround(MI_PSYM_SEARCH))
+    mi_send(h,"file -readnow %s\n",file);
+ else
+    mi_send(h,"-file-exec-and-symbols %s\n",file);
+}
+
+void mi_exec_arguments(mi_h *h, const char *args)
+{
+ mi_send(h,"-exec-arguments %s\n",args);
+}
+
+void mi_exec_run(mi_h *h)
+{
+ mi_send(h,"-exec-run\n");
+}
+
+void mi_exec_continue(mi_h *h)
+{
+ mi_send(h,"-exec-continue\n");
+}
+
+void mi_target_terminal(mi_h *h, const char *tty_name)
+{
+ mi_send(h,"tty %s\n",tty_name);
+}
+
+void mi_file_symbol_file(mi_h *h, const char *file)
+{
+ if (mi_get_workaround(MI_PSYM_SEARCH))
+    mi_send(h,"symbol-file -readnow %s\n",file);
+ else
+    mi_send(h,"-file-symbol-file %s\n",file);
+}
+
+void mi_exec_finish(mi_h *h)
+{
+ mi_send(h,"-exec-finish\n");
+}
+
+void mi_exec_interrupt(mi_h *h)
+{
+ mi_send(h,"-exec-interrupt\n");
+}
+
+void mi_exec_next(mi_h *h, int count)
+{
+ if (count>1)
+    mi_send(h,"-exec-next %d\n",count);
+ else
+    mi_send(h,"-exec-next\n");
+}
+
+void mi_exec_next_instruction(mi_h *h)
+{
+ mi_send(h,"-exec-next-instruction\n");
+}
+
+void mi_exec_step(mi_h *h, int count)
+{
+ if (count>1)
+    mi_send(h,"-exec-step %d\n",count);
+ else
+    mi_send(h,"-exec-step\n");
+}
+
+void mi_exec_step_instruction(mi_h *h)
+{
+ mi_send(h,"-exec-step-instruction\n");
+}
+
+void mi_exec_until(mi_h *h, const char *file, int line)
+{
+ if (!file)
+    mi_send(h,"-exec-until\n");
+ else
+    mi_send(h,"-exec-until %s:%d\n",file,line);
+}
+
+void mi_exec_until_addr(mi_h *h, void *addr)
+{
+ mi_send(h,"-exec-until *%p\n",addr);
+}
+
+void mi_exec_return(mi_h *h)
+{
+ mi_send(h,"-exec-return\n");
+}
+
+void mi_exec_kill(mi_h *h)
+{
+ mi_send(h,"kill\n");
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  Specify the executable and arguments for local debug.
+
+  Command: -file-exec-and-symbols + -exec-arguments
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_set_exec(mi_h *h, const char *file, const char *args)
+{
+ mi_file_exec_and_symbols(h,file);
+ if (!mi_res_simple_done(h))
+    return 0;
+ if (!args)
+    return 1;
+ mi_exec_arguments(h,args);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Start running the executable. Remote sessions starts running.
+
+  Command: -exec-run
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_run(mi_h *h)
+{
+ mi_exec_run(h);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Continue the execution after a "stop".
+
+  Command: -exec-continue
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_continue(mi_h *h)
+{
+ mi_exec_continue(h);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Indicate which terminal will use the target program. For local sessions.
+
+  Command: tty
+  Return: !=0 OK
+  Example: 
+  
+***************************************************************************/
+
+int gmi_target_terminal(mi_h *h, const char *tty_name)
+{
+ mi_target_terminal(h,tty_name);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Specify what's the local copy that have debug info. For remote sessions.
+
+  Command: -file-symbol-file
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_file_symbol_file(mi_h *h, const char *file)
+{
+ mi_file_symbol_file(h,file);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Continue until function return, the return value is included in the async
+response.
+
+  Command: -exec-finish
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int gmi_exec_finish(mi_h *h)
+{
+ mi_exec_finish(h);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Stop the program using SIGINT. The corresponding command should be
+-exec-interrupt but not even gdb 6.1.1 can do it because the "async" mode
+isn't really working.
+
+  Command: -exec-interrupt [replacement]
+  Return: Always 1
+  Example: 
+  
+***************************************************************************/
+
+int gmi_exec_interrupt(mi_h *h)
+{
+ // **** IMPORTANT!!! **** Not even gdb 6.1.1 can do it because the "async"
+ // mode isn't really working.
+ //mi_exec_interrupt(h);
+ //return mi_res_simple_running(h);
+
+ kill(h->pid,SIGINT);
+ return 1; // How can I know?
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Next line of code.
+
+  Command: -exec-next
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_next(mi_h *h)
+{
+ mi_exec_next(h,1);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Skip count lines of code.
+
+  Command: -exec-next count
+  Return: !=0 OK
+
+***************************************************************************/
+
+int gmi_exec_next_cnt(mi_h *h, int count)
+{
+ mi_exec_next(h,count);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Next line of assembler code.
+
+  Command: -exec-next-instruction
+  Return: !=0 OK
+
+***************************************************************************/
+
+int gmi_exec_next_instruction(mi_h *h)
+{
+ mi_exec_next_instruction(h);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Next line of code. Get inside functions.
+
+  Command: -exec-step
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_step(mi_h *h)
+{
+ mi_exec_step(h,1);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Next count lines of code. Get inside functions.
+
+  Command: -exec-step count
+  Return: !=0 OK
+
+***************************************************************************/
+
+int gmi_exec_step_cnt(mi_h *h, int count)
+{
+ mi_exec_step(h,count);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Next line of assembler code. Get inside calls.
+
+  Command: -exec-step-instruction
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_step_instruction(mi_h *h)
+{
+ mi_exec_step_instruction(h);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Execute until location is reached. If file is NULL then is until next
+line.
+
+  Command: -exec-until
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_until(mi_h *h, const char *file, int line)
+{
+ mi_exec_until(h,file,line);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Execute until location is reached.
+
+  Command: -exec-until (using *address)
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_until_addr(mi_h *h, void *addr)
+{
+ mi_exec_until_addr(h,addr);
+ return mi_res_simple_running(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Return to previous frame inmediatly.
+
+  Command: -exec-return
+  Return: A pointer to a new mi_frames structure indicating the current
+location. NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_exec_return(mi_h *h)
+{
+ mi_exec_return(h);
+ return mi_res_frame(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Just kill the program. That's what -exec-abort should do, but it isn't
+implemented by gdb. This implementation only works if the interactive mode
+is disabled (gmi_gdb_set("confirm","off")).
+
+  Command: -exec-abort [using kill]
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_exec_kill(mi_h *h)
+{
+ mi_exec_kill(h);
+ return mi_res_simple_done(h);
+}
+
diff --git a/src/stack_man.c b/src/stack_man.c
new file mode 100644 (file)
index 0000000..8e8ed06
--- /dev/null
@@ -0,0 +1,222 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Stack manipulation.
+  Comments:
+  GDB/MI commands for the "Stack Manipulation" section.@p
+
+@<pre>
+gdb command:              Implemented?
+
+-stack-info-frame         Yes, implemented as "frame"
+-stack-info-depth         Yes
+-stack-list-arguments     Yes
+-stack-list-frames        Yes
+-stack-list-locals        Yes
+-stack-select-frame       Yes
+@</pre>
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_stack_list_frames(mi_h *h, int from, int to)
+{
+ if (from<0)
+    mi_send(h,"-stack-list-frames\n");
+ else
+    mi_send(h,"-stack-list-frames %d %d\n",from,to);
+}
+
+void mi_stack_list_arguments(mi_h *h, int show, int from, int to)
+{
+ if (from<0)
+    mi_send(h,"-stack-list-arguments %d\n",show);
+ else
+    mi_send(h,"-stack-list-arguments %d %d %d\n",show,from,to);
+}
+
+void mi_stack_info_frame(mi_h *h)
+{
+ mi_send(h,"frame\n");
+}
+
+void mi_stack_info_depth(mi_h *h, int depth)
+{
+ if (depth<0)
+    mi_send(h,"-stack-info-depth\n");
+ else
+    mi_send(h,"-stack-info-depth %d\n",depth);
+}
+
+void mi_stack_select_frame(mi_h *h, int framenum)
+{
+ mi_send(h,"-stack-select-frame %d\n",framenum);
+}
+
+void mi_stack_list_locals(mi_h *h, int show)
+{
+ mi_send(h,"-stack-list-locals %d\n",show);
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  List of frames. Arguments aren't filled.
+
+  Command: -stack-list-frames
+  Return:  A new list of mi_frames or NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_stack_list_frames(mi_h *h)
+{
+ mi_stack_list_frames(h,-1,-1);
+ return mi_res_frames_array(h,"stack");
+}
+
+/**[txh]********************************************************************
+
+  Description: 
+  List of frames. Arguments aren't filled. Only the frames in the @var{from}
+ - @var{to} range are returned.
+  
+  Command: -stack-list-frames
+  Return:  A new list of mi_frames or NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to)
+{
+ mi_stack_list_frames(h,from,to);
+ return mi_res_frames_array(h,"stack");
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  List arguments. Only @var{level} and @var{args} filled.
+  
+  Command: -stack-list-arguments
+  Return:  A new list of mi_frames or NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_stack_list_arguments(mi_h *h, int show)
+{
+ mi_stack_list_arguments(h,show,-1,-1);
+ return mi_res_frames_array(h,"stack-args");
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  List arguments. Only @var{level} and @var{args} filled. Only for the
+frames in the @var{from} - @var{to} range.
+  
+  Command: -stack-list-arguments
+  Return:  A new list of mi_frames or NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to)
+{
+ mi_stack_list_arguments(h,show,from,to);
+ return mi_res_frames_array(h,"stack-args");
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Information about the current frame, including args.
+
+  Command: -stack-info-frame [using frame]
+  Return: A new mi_frames or NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_stack_info_frame(mi_h *h)
+{
+ mi_stack_info_frame(h);
+ return mi_res_frame(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Stack info depth.
+
+  Command: -stack-info-depth
+  Return: The depth or -1 on error.
+  
+***************************************************************************/
+
+int gmi_stack_info_depth(mi_h *h, int max_depth)
+{
+ mi_results *r;
+ int ret=-1;
+
+ mi_stack_info_depth(h,max_depth);
+ r=mi_res_done_var(h,"depth");
+ if (r && r->type==t_const)
+   {
+    ret=atoi(r->v.cstr);
+    mi_free_results(r);
+   }
+ return ret;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Set stack info depth.
+
+  Command: -stack-info-depth [no args]
+  Return: The depth or -1 on error.
+  Example: 
+  
+***************************************************************************/
+
+int gmi_stack_info_depth_get(mi_h *h)
+{
+ return gmi_stack_info_depth(h,-1);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Change current frame.
+
+  Command: -stack-select-frame
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_stack_select_frame(mi_h *h, int framenum)
+{
+ mi_stack_select_frame(h,framenum);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  List of local vars.
+
+  Command: -stack-list-locals
+  Return: A new mi_results tree containing the variables or NULL on error.
+  
+***************************************************************************/
+
+mi_results *gmi_stack_list_locals(mi_h *h, int show)
+{
+ mi_stack_list_locals(h,show);
+ return mi_res_done_var(h,"locals");
+}
+
diff --git a/src/symbol_query.c b/src/symbol_query.c
new file mode 100644 (file)
index 0000000..55e145f
--- /dev/null
@@ -0,0 +1,32 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Symbol query.
+  Comments:
+  GDB/MI commands for the "Symbol Query" section.@p
+
+@<pre>
+gdb command:              Implemented?
+-symbol-info-address      N.A. (info address, human readable)
+-symbol-info-file         N.A.
+-symbol-info-function     N.A.
+-symbol-info-line         N.A. (info line, human readable)
+-symbol-info-symbol       N.A. (info symbol, human readable)
+-symbol-list-functions    N.A. (info functions, human readable)
+-symbol-list-types        N.A. (info types, human readable)
+-symbol-list-variables    N.A. (info variables, human readable)
+-symbol-list-lines        No (gdb 6.x)
+-symbol-locate            N.A.
+-symbol-type              N.A. (ptype, human readable)
+@</pre>
+
+Note:@p
+
+Only one is implemented and not in gdb 5.x.@p
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
diff --git a/src/target_man.c b/src/target_man.c
new file mode 100644 (file)
index 0000000..cf6c815
--- /dev/null
@@ -0,0 +1,119 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004-2007 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Target manipulation.
+  Comments:
+  GDB/MI commands for the "Target Manipulation" section.@p
+
+@<pre>
+-target-attach                  Yes (implemented using attach)
+-target-compare-sections        N.A. (compare-sections)
+-target-detach                  Yes
+-target-download                Yes
+-target-exec-status             N.A.
+-target-list-available-targets  N.A. (help target)
+-target-list-current-targets    N.A. (info file among other things)
+-target-list-parameters         N.A.
+-target-select                  Yes
+@</pre>
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_target_select(mi_h *h, const char *type, const char *params)
+{
+ mi_send(h,"-target-select %s %s\n",type,params);
+}
+
+/* Note: -target-attach isn't currently implemented :-( (gdb 6.1.1) */
+void mi_target_attach(mi_h *h, pid_t pid)
+{
+ mi_send(h,"attach %d\n",pid);
+}
+
+void mi_target_detach(mi_h *h)
+{
+ mi_send(h,"-target-detach\n");
+}
+
+void mi_target_download(mi_h *h)
+{
+ mi_send(h,"-target-download\n");
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  Connect to a remote gdbserver using the specified methode.
+
+  Command: -target-select
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_target_select(mi_h *h, const char *type, const char *params)
+{
+ mi_target_select(h,type,params);
+ if (!mi_res_simple_connected(h))
+    return 0;
+ mi_send_target_commands(h);
+ return 1;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Attach to an already running process.
+
+  Command: -target-attach [using attach]
+  Return: The frame of the current location, NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_target_attach(mi_h *h, pid_t pid)
+{
+ mi_target_attach(h,pid);
+ //return mi_res_simple_done(h);
+ return mi_res_frame(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Detach from an attached process.
+
+  Command: -target-detach
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_target_detach(mi_h *h)
+{
+ mi_target_detach(h);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Loads the executable onto the remote target.
+
+  Command: -target-download
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_target_download(mi_h *h)
+{
+ mi_target_download(h);
+ // TODO: this response have some data
+ return mi_res_simple_done(h);
+}
+
diff --git a/src/thread.c b/src/thread.c
new file mode 100644 (file)
index 0000000..51a333f
--- /dev/null
@@ -0,0 +1,89 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Thread commands.
+  Comments:
+  GDB/MI commands for the "Thread Commands" section.@p
+
+@<pre>
+gdb command:              Implemented?
+-thread-info              N.A.
+-thread-list-all-threads  Yes, implemented as "info threads"
+-thread-list-ids          Yes
+-thread-select            Yes
+@</pre>
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_thread_list_ids(mi_h *h)
+{
+ mi_send(h,"-thread-list-ids\n");
+}
+
+void mi_thread_select(mi_h *h, int id)
+{
+ mi_send(h,"-thread-select %d\n",id);
+}
+
+void mi_thread_list_all_threads(mi_h *h)
+{
+ mi_send(h,"info threads\n");
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  List available thread ids.
+
+  Command: -thread-list-ids
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_thread_list_ids(mi_h *h, int **list)
+{
+ mi_thread_list_ids(h);
+ return mi_res_thread_ids(h,list);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Select a thread.
+
+  Command: -thread-select
+  Return: A new mi_frames or NULL on error.
+  
+***************************************************************************/
+
+mi_frames *gmi_thread_select(mi_h *h, int id)
+{
+ mi_thread_select(h,id);
+ return mi_res_frame(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Get a list of frames for each available thread. Implemented using "info
+thread".
+
+  Command: -thread-list-all-threads
+  Return: A kist of frames, NULL on error
+  
+***************************************************************************/
+
+mi_frames *gmi_thread_list_all_threads(mi_h *h)
+{
+ mi_thread_list_all_threads(h);
+ return mi_res_frames_list(h);
+}
+
diff --git a/src/var_obj.c b/src/var_obj.c
new file mode 100644 (file)
index 0000000..a027d67
--- /dev/null
@@ -0,0 +1,369 @@
+/**[txh]********************************************************************
+
+  Copyright (c) 2004 by Salvador E. Tropea.
+  Covered by the GPL license.
+
+  Module: Variable objects.
+  Comments:
+  GDB/MI commands for the "Variable Objects" section.@p
+
+@<pre>
+gdb command:              Imp? Description:
+-var-create               Yes  create a variable object
+-var-delete               Yes  delete the variable object and its children
+-var-set-format           Yes  set the display format of this variable
+-var-show-format          Yes  show the display format of this variable
+-var-info-num-children    Yes  tells how many children this object has
+-var-list-children        Yes* return a list of the object's children
+-var-info-type            Yes  show the type of this variable object
+-var-info-expression      Yes  print what this variable object represents
+-var-show-attributes      Yes  is this variable editable?
+-var-evaluate-expression  Yes  get the value of this variable
+-var-assign               Yes  set the value of this variable
+-var-update               Yes* update the variable and its children
+@</pre>
+
+Notes:@p
+1) I suggest letting gdb to choose the names for the variables.@*
+2) -var-list-children supports an optional "show values" argument in MI v2.
+It isn't implemented.@*
+@p
+
+* MI v1 and v2 result formats supported.@p
+
+***************************************************************************/
+
+#include "mi_gdb.h"
+
+/* Low level versions. */
+
+void mi_var_create(mi_h *h, const char *name, int frame, const char *exp)
+{
+ const char *n=name ? name : "-";
+
+ if (frame<0)
+    mi_send(h,"-var-create %s * %s\n",n,exp);
+ else
+    mi_send(h,"-var-create %s %d %s\n",n,frame,exp);
+}
+
+void mi_var_delete(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-delete %s\n",name);
+}
+
+void mi_var_set_format(mi_h *h, const char *name, const char *format)
+{
+ mi_send(h,"-var-set-format \"%s\" %s\n",name,format);
+}
+
+void mi_var_show_format(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-show-format \"%s\"\n",name);
+}
+
+void mi_var_info_num_children(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-info-num-children \"%s\"\n",name);
+}
+
+void mi_var_info_type(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-info-type \"%s\"\n",name);
+}
+
+void mi_var_info_expression(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-info-expression \"%s\"\n",name);
+}
+
+void mi_var_show_attributes(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-show-attributes \"%s\"\n",name);
+}
+
+void mi_var_update(mi_h *h, const char *name)
+{
+ if (name)
+    mi_send(h,"-var-update %s\n",name);
+ else
+    mi_send(h,"-var-update *\n");
+}
+
+void mi_var_assign(mi_h *h, const char *name, const char *expression)
+{
+ mi_send(h,"-var-assign \"%s\" \"%s\"\n",name,expression);
+}
+
+void mi_var_evaluate_expression(mi_h *h, const char *name)
+{
+ mi_send(h,"-var-evaluate-expression \"%s\"\n",name);
+}
+
+void mi_var_list_children(mi_h *h, const char *name)
+{
+ if (h->version>=MI_VERSION2U(2,0,0))
+    mi_send(h,"-var-list-children --all-values \"%s\"\n",name);
+ else
+    mi_send(h,"-var-list-children \"%s\"\n",name);
+}
+
+/* High level versions. */
+
+/**[txh]********************************************************************
+
+  Description:
+  Create a variable object. I recommend using @x{gmi_var_create} and letting
+gdb choose the names.
+
+  Command: -var-create
+  Return: A new mi_gvar strcture or NULL on error.
+  
+***************************************************************************/
+
+mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp)
+{
+ mi_var_create(h,name,frame,exp);
+ return mi_res_gvar(h,NULL,exp);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Create a variable object. The name is selected by gdb. Alternative:
+@x{gmi_full_var_create}.
+
+  Command: -var-create [auto name]
+  Return: A new mi_gvar strcture or NULL on error.
+  
+***************************************************************************/
+
+mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp)
+{
+ return gmi_var_create_nm(h,NULL,frame,exp);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Delete a variable object. Doesn't free the mi_gvar data.
+
+  Command: -var-delete
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_delete(mi_h *h, mi_gvar *var)
+{
+ mi_var_delete(h,var->name);
+ return mi_res_simple_done(h);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Set the format used to represent the result.
+
+  Command: -var-set-format
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format)
+{
+ int ret;
+
+ mi_var_set_format(h,var->name,mi_format_enum_to_str(format));
+ ret=mi_res_simple_done(h);
+ if (ret)
+    var->format=format;
+ return ret;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Fill the format field with info from gdb.
+
+  Command: -var-show-format
+  Return: !=0 OK.
+  
+***************************************************************************/
+
+int gmi_var_show_format(mi_h *h, mi_gvar *var)
+{
+ mi_var_show_format(h,var->name);
+ return mi_res_gvar(h,var,NULL)!=NULL;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Fill the numchild field with info from gdb.
+
+  Command: -var-info-num-children
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_info_num_children(mi_h *h, mi_gvar *var)
+{
+ mi_var_info_num_children(h,var->name);
+ return mi_res_gvar(h,var,NULL)!=NULL;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Fill the type field with info from gdb.
+
+  Command: -var-info-type
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_info_type(mi_h *h, mi_gvar *var)
+{
+ mi_var_info_type(h,var->name);
+ return mi_res_gvar(h,var,NULL)!=NULL;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Fill the expression and lang fields with info from gdb. Note that lang
+isn't filled during creation.
+
+  Command: -var-info-expression
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_info_expression(mi_h *h, mi_gvar *var)
+{
+ mi_var_info_expression(h,var->name);
+ return mi_res_gvar(h,var,NULL)!=NULL;
+}
+
+
+/**[txh]********************************************************************
+
+  Description:
+  Fill the attr field with info from gdb. Note that attr isn't filled
+during creation.
+
+  Command: -var-show-attributes
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_show_attributes(mi_h *h, mi_gvar *var)
+{
+ mi_var_show_attributes(h,var->name);
+ return mi_res_gvar(h,var,NULL)!=NULL;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Create the variable and also fill the lang and attr fields. The name is
+selected by gdb.
+
+  Command: -var-create + -var-info-expression + -var-show-attributes
+  Return: A new mi_gvar strcture or NULL on error.
+  
+***************************************************************************/
+
+mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp)
+{
+ mi_gvar *var=gmi_var_create_nm(h,NULL,frame,exp);
+ if (var)
+   {/* What if it fails? */
+    gmi_var_info_expression(h,var);
+    gmi_var_show_attributes(h,var);
+   }
+ return var;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Update variable. Use NULL for all. Note that *changed can be NULL if none
+updated.
+
+  Command: -var-update
+  Return: !=0 OK. The @var{changed} list contains the list of changed vars.
+  
+***************************************************************************/
+
+int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed)
+{
+ mi_var_update(h,var ? var->name : NULL);
+ return mi_res_changelist(h,changed);
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Change variable. The new value replaces the @var{value} field.
+
+  Command: -var-assign
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression)
+{
+ char *res;
+ mi_var_assign(h,var->name,expression);
+ res=mi_res_value(h);
+ if (res)
+   {
+    free(var->value);
+    var->value=res;
+    return 1;
+   }
+ return 0;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  Fill the value field getting the current value for a variable.
+
+  Command: -var-evaluate-expression
+  Return: !=0 OK, value contains the result.
+  
+***************************************************************************/
+
+int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var)
+{
+ char *s;
+
+ mi_var_evaluate_expression(h,var->name);
+ s=mi_res_value(h);
+ if (s)
+   {
+    free(var->value);
+    var->value=s;
+   }
+ return s!=NULL;
+}
+
+/**[txh]********************************************************************
+
+  Description:
+  List children. It ONLY returns the first level information. :-(@*
+  On success the child field contains the list of children.
+
+  Command: -var-list-children
+  Return: !=0 OK
+  
+***************************************************************************/
+
+int gmi_var_list_children(mi_h *h, mi_gvar *var)
+{
+ mi_var_list_children(h,var->name);
+ return mi_res_children(h,var);
+}
+
diff --git a/version.c b/version.c
new file mode 100644 (file)
index 0000000..b9b78c4
--- /dev/null
+++ b/version.c
@@ -0,0 +1,7 @@
+#include "src/mi_gdb.h"
+
+int main()
+{
+ fputs(MI_VERSION_STR,stdout);
+ return 0;
+}