aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac35
-rw-r--r--contrib/defaults.conf7
-rw-r--r--src/Makefile.am9
-rw-r--r--src/monkey/Makefile.am128
-rw-r--r--src/monkey/action_api.c655
-rw-r--r--src/monkey/bug_assertion_failure.c15
-rw-r--r--src/monkey/bug_bad_memory_access.c16
-rw-r--r--src/monkey/bug_crypto_crc.c121
-rw-r--r--src/monkey/bug_null_pointer_exception.c21
-rw-r--r--src/monkey/edb_api.c194
-rw-r--r--src/monkey/gdbmi.h716
-rw-r--r--src/monkey/gdbmi_alloc.c308
-rw-r--r--src/monkey/gdbmi_breakpoint.c265
-rw-r--r--src/monkey/gdbmi_connect.c885
-rw-r--r--src/monkey/gdbmi_data_man.c243
-rw-r--r--src/monkey/gdbmi_error.c38
-rw-r--r--src/monkey/gdbmi_get_free_pty.c132
-rw-r--r--src/monkey/gdbmi_get_free_vt.c156
-rw-r--r--src/monkey/gdbmi_misc.c118
-rw-r--r--src/monkey/gdbmi_parse.c1927
-rw-r--r--src/monkey/gdbmi_prg_control.c454
-rw-r--r--src/monkey/gdbmi_stack_man.c222
-rw-r--r--src/monkey/gdbmi_symbol_query.c32
-rw-r--r--src/monkey/gdbmi_target_man.c119
-rw-r--r--src/monkey/gdbmi_thread.c89
-rw-r--r--src/monkey/gdbmi_var_obj.c371
-rw-r--r--src/monkey/gnunet-monkey.c201
-rw-r--r--src/monkey/gnunet-service-monkey.c6
-rw-r--r--src/monkey/gnunet_monkey_action.h103
-rw-r--r--src/monkey/gnunet_monkey_edb.h129
-rw-r--r--src/monkey/mail_sender.c226
-rw-r--r--src/monkey/seaspider/C.jj587
-rwxr-xr-xsrc/monkey/seaspider/Makefile5
-rw-r--r--src/monkey/seaspider/SeaspiderTest.c83
-rw-r--r--src/monkey/seaspider/org/gnunet/seaspider/ExpressionDatabaseHandler.java204
-rw-r--r--src/monkey/seaspider/org/gnunet/seaspider/ExpressionExtractorVisitor.java713
-rw-r--r--src/monkey/seaspider/org/gnunet/seaspider/Seaspider.java132
-rw-r--r--src/monkey/seaspider/org/grothoff/LineNumberInfo.java192
-rw-r--r--src/monkey/test.dbbin7168 -> 0 bytes
-rw-r--r--src/monkey/test_gnunet_monkey.c72
-rwxr-xr-xsrc/monkey/test_gnunet_monkey.sh199
-rw-r--r--src/monkey/test_gnunet_monkey_data.conf43
-rw-r--r--src/monkey/test_monkey_edb.c69
-rwxr-xr-xsrc/monkey/test_monkey_npe.sh11
-rw-r--r--src/monkey/tmp30
45 files changed, 6 insertions, 10275 deletions
diff --git a/configure.ac b/configure.ac
index 0fc1ebe02..fe9143dfb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -584,40 +584,6 @@ else
584 AM_CONDITIONAL(HAVE_PYTHON_PEXPECT, 0) 584 AM_CONDITIONAL(HAVE_PYTHON_PEXPECT, 0)
585fi 585fi
586 586
587# libesmtp
588esmtp=0
589AC_MSG_CHECKING([for libesmtp])
590AC_ARG_WITH(esmtp,
591 [ --with-esmtp=PFX base of libesmtp installation],
592 [AC_MSG_RESULT([$with_esmtp])
593 case $with_esmtp in
594 no)
595 ;;
596 yes)
597 AC_CHECK_HEADERS(libesmtp.h,
598 AC_CHECK_LIB([esmtp], [smtp_start_session],
599 esmtp=1))
600 ;;
601 *)
602 LDFLAGS="-L$with_esmtp/lib $LDFLAGS"
603 CPPFLAGS="-I$with_esmtp/include $CPPFLAGS"
604 AC_CHECK_HEADERS(libesmtp.h,
605 AC_CHECK_LIB([esmtp], [smtp_start_session],
606 EXT_LIB_PATH="-L$with_esmtp/lib $EXT_LIB_PATH"
607 esmtp=1))
608 ;;
609 esac
610 ],
611 [AC_MSG_RESULT([--with-esmtp not specified])
612 AC_CHECK_HEADERS(libesmtp.h,
613 AC_CHECK_LIB([esmtp], [smtp_start_session],
614 esmtp=1))])
615AM_CONDITIONAL(HAVE_ESMTP, test x$esmtp = x1)
616AC_DEFINE_UNQUOTED([HAVE_ESMTP], $esmtp, [We have libesmtp])
617# restore LIBS
618LIBS=$SAVE_LIBS
619
620
621 587
622# check for gettext 588# check for gettext
623AM_GNU_GETTEXT([external]) 589AM_GNU_GETTEXT([external])
@@ -826,7 +792,6 @@ src/include/Makefile
826src/include/gnunet_directories.h 792src/include/gnunet_directories.h
827src/hostlist/Makefile 793src/hostlist/Makefile
828src/mesh/Makefile 794src/mesh/Makefile
829src/monkey/Makefile
830src/nat/Makefile 795src/nat/Makefile
831src/peerinfo/Makefile 796src/peerinfo/Makefile
832src/peerinfo-tool/Makefile 797src/peerinfo-tool/Makefile
diff --git a/contrib/defaults.conf b/contrib/defaults.conf
index 9f22167d7..2c2cd7a77 100644
--- a/contrib/defaults.conf
+++ b/contrib/defaults.conf
@@ -55,7 +55,11 @@ DISABLEV6 = NO
55PORT = 2086 55PORT = 2086
56ADVERTISED_PORT = 2086 56ADVERTISED_PORT = 2086
57 57
58TIMEOUT = 300000 58# Maximum number of open TCP connections allowed
59MAX_CONNECTIONS = 128
60
61# After how long do we drop inactive connections?
62TIMEOUT = 5000
59 63
60# Allow use of loopback address 64# Allow use of loopback address
61USE_LOCALADDR = NO 65USE_LOCALADDR = NO
@@ -416,3 +420,4 @@ ACCEPT_FROM = 127.0.0.1;
416ACCEPT_FROM6 = ::1; 420ACCEPT_FROM6 = ::1;
417UNIXPATH = /tmp/gnunet-service-dns.sock 421UNIXPATH = /tmp/gnunet-service-dns.sock
418PROVIDE_EXIT = NO 422PROVIDE_EXIT = NO
423
diff --git a/src/Makefile.am b/src/Makefile.am
index 2871554cf..fdcde2601 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,14 +2,6 @@
2# INTLEMU_SUBDIRS = intlemu 2# INTLEMU_SUBDIRS = intlemu
3#endif 3#endif
4 4
5if HAVE_ESMTP
6if HAVE_OPENSSL
7if HAVE_EXPERIMENTAL
8 MONKEY_DIR = monkey
9endif
10endif
11endif
12
13if HAVE_EXPERIMENTAL 5if HAVE_EXPERIMENTAL
14 EXP_DIR = fragmentation mesh vpn chat 6 EXP_DIR = fragmentation mesh vpn chat
15endif 7endif
@@ -21,7 +13,6 @@ SUBDIRS = \
21 block \ 13 block \
22 statistics \ 14 statistics \
23 arm \ 15 arm \
24 $(MONKEY_DIR) \
25 peerinfo \ 16 peerinfo \
26 datacache \ 17 datacache \
27 datastore \ 18 datastore \
diff --git a/src/monkey/Makefile.am b/src/monkey/Makefile.am
deleted file mode 100644
index ab265daa0..000000000
--- a/src/monkey/Makefile.am
+++ /dev/null
@@ -1,128 +0,0 @@
1INCLUDES = -I$(top_srcdir)/src/include
2
3if MINGW
4 WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
5endif
6
7if USE_COVERAGE
8 AM_CFLAGS = --coverage -O0
9 XLIB = -lgcov
10endif
11
12
13if !MINGW
14if HAVE_ESMTP
15if HAVE_OPENSSL
16
17
18lib_LTLIBRARIES = libmonkeyedb.la \
19 libmonkeyaction.la
20
21libmonkeyedb_la_SOURCES = \
22 edb_api.c \
23 gnunet_monkey_edb.h
24
25libmonkeyedb_la_LIBADD = \
26 $(top_builddir)/src/util/libgnunetutil.la \
27 -lsqlite3 \
28 $(GN_LIBINTL) $(XLIB)
29
30libmonkeyaction_la_SOURCES = \
31 action_api.c \
32 gnunet_monkey_action.h
33
34libmonkeyaction_la_LIBADD = \
35 $(top_builddir)/src/util/libgnunetutil.la \
36 $(GN_LIBINTL) $(XLIB)
37
38bin_PROGRAMS = \
39 gnunet-monkey \
40 gnunet-service-monkey
41
42noinst_PROGRAMS = \
43 bug_null_pointer_exception \
44 bug_bad_memory_access \
45 bug_assertion_failure \
46 bug_crypto_crc
47
48gnunet_monkey_SOURCES = \
49 gdbmi.h \
50 gdbmi_alloc.c \
51 gdbmi_breakpoint.c \
52 gdbmi_connect.c \
53 gdbmi_data_man.c \
54 gdbmi_error.c \
55 gdbmi_get_free_pty.c \
56 gdbmi_get_free_vt.c \
57 gdbmi_misc.c \
58 gdbmi_parse.c \
59 gdbmi_prg_control.c \
60 gdbmi_stack_man.c \
61 gdbmi_symbol_query.c \
62 gdbmi_target_man.c \
63 gdbmi_thread.c \
64 gdbmi_var_obj.c \
65 gnunet-monkey.c \
66 mail_sender.c
67
68gnunet_monkey_LDADD = \
69 $(top_builddir)/src/util/libgnunetutil.la \
70 $(top_builddir)/src/monkey/libmonkeyedb.la \
71 $(top_builddir)/src/monkey/libmonkeyaction.la \
72 -lesmtp \
73 $(GN_LIBINTL)
74
75
76gnunet_service_monkey_SOURCES = \
77 gnunet-service-monkey.c
78gnunet_service_monkey_LDADD = \
79 $(top_builddir)/src/util/libgnunetutil.la \
80 $(GN_LIBINTL)
81
82
83bug_null_pointer_exception:
84 gcc -g -O0 -o bug_null_pointer_exception bug_null_pointer_exception.c
85
86bug_bad_memory_access:
87 gcc -g -O0 -o bug_bad_memory_access bug_bad_memory_access.c
88
89bug_assertion_failure:
90 gcc -g -O0 -o bug_assertion_failure bug_assertion_failure.c
91
92bug_crypto_crc:
93 gcc -g -O0 -o bug_crypto_crc bug_crypto_crc.c
94
95check_PROGRAMS = \
96 test_monkey_edb
97 #test_gnunet_monkey
98
99if ENABLE_TEST_RUN
100# TESTS = $(check_SCRIPTS)
101TESTS = $(check_PROGRAMS)
102endif
103
104test_monkey_edb_SOURCES = \
105 test_monkey_edb.c
106test_monkey_edb_LDADD = \
107 $(top_builddir)/src/util/libgnunetutil.la \
108 $(top_builddir)/src/monkey/libmonkeyedb.la
109
110#test_gnunet_monkey_SOURCES = \
111 #test_gnunet_monkey.c
112#test_gnunet_monkey_LDADD = \
113 #$(top_builddir)/src/arm/libgnunetarm.la \
114 #$(top_builddir)/src/util/libgnunetutil.la
115
116
117check_SCRIPTS = \
118 #test_gnunet_monkey.sh \
119 #test_monkey_npe.sh
120
121EXTRA_DIST = \
122 test_gnunet_monkey_data.conf \
123 test.db
124#$(check_SCRIPTS)
125
126endif
127endif
128endif
diff --git a/src/monkey/action_api.c b/src/monkey/action_api.c
deleted file mode 100644
index 67bd21139..000000000
--- a/src/monkey/action_api.c
+++ /dev/null
@@ -1,655 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file monkey/action_api.c
23 * @brief Monkey API for actions taken by Monkey while debugging
24 */
25
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_monkey_action.h"
29#include "gnunet_monkey_edb.h"
30#include "gnunet_container_lib.h"
31#include <libesmtp.h>
32
33extern void sendMail (const char *messageContents, const char *emailAddress);
34
35
36static int async_c = 0;
37static struct Expression *expressionListHead = NULL;
38static struct Expression *expressionListTail = NULL;
39static struct WatchInfo *watchInfoListHead = NULL;
40static struct WatchInfo *watchInfoListTail = NULL;
41static struct Expression *faultyExpression = NULL;
42
43struct Expression
44{
45 struct Expression *next;
46 struct Expression *prev;
47 const char *expressionSyntax;
48 const char *expressionValue;
49 int lineNo;
50};
51
52struct WatchInfo
53{
54 struct WatchInfo *next;
55 struct WatchInfo *prev;
56 int hitNumber;
57 const char *value;
58};
59
60
61static void
62cb_console (const char *str, void *data)
63{
64 printf ("CONSOLE> %s\n", str);
65}
66
67
68/* Note that unlike what's documented in gdb docs it isn't usable. */
69static void
70cb_target (const char *str, void *data)
71{
72 printf ("TARGET> %s\n", str);
73}
74
75
76static void
77cb_log (const char *str, void *data)
78{
79 printf ("LOG> %s\n", str);
80}
81
82
83static void
84cb_to (const char *str, void *data)
85{
86 printf (">> %s", str);
87}
88
89
90static void
91cb_from (const char *str, void *data)
92{
93 printf ("<< %s\n", str);
94}
95
96
97static void
98cb_async (mi_output * o, void *data)
99{
100 printf ("ASYNC\n");
101 async_c++;
102}
103
104
105static int
106wait_for_stop (struct GNUNET_MONKEY_ACTION_Context *cntxt)
107{
108 while (!mi_get_response (cntxt->gdb_handle))
109 usleep (1000);
110 /* The end of the async. */
111 cntxt->gdb_stop_reason = mi_res_stop (cntxt->gdb_handle);
112 if (cntxt->gdb_stop_reason)
113 {
114 if (cntxt->gdb_stop_reason->reason == sr_exited_normally)
115 return GDB_STATE_EXIT_NORMALLY;
116 else if (cntxt->gdb_stop_reason->reason == sr_bkpt_hit) {
117 /* We want to inspect an expression */
118 /* Set hardware watch at the expression to inspect */
119 mi_wp *wp = gmi_break_watch(cntxt->gdb_handle, wm_write, cntxt->inspect_expression);
120 if (NULL == wp)
121 {
122 printf("Error in setting a watchpoint at expression:%s\n", cntxt->inspect_expression);
123 return GDB_STATE_ERROR;
124 }
125 mi_free_wp(wp);
126 /* continue execution */
127 gmi_exec_continue(cntxt->gdb_handle);
128 return wait_for_stop (cntxt);
129 }
130 else if (cntxt->gdb_stop_reason->reason == sr_wp_trigger) {
131 static int watchPointHitNumber = 0;
132 struct WatchInfo *watchInfo = GNUNET_malloc(sizeof(struct WatchInfo));
133 watchInfo->hitNumber = ++watchPointHitNumber;
134 watchInfo->value = cntxt->gdb_stop_reason->wp_val;
135 GNUNET_CONTAINER_DLL_insert(watchInfoListHead, watchInfoListTail, watchInfo);
136 if (watchPointHitNumber == 1023)
137 printf("HEY! 1023! WE ARE GETTING OUT OF THE LOOP!\n");
138 gmi_exec_continue(cntxt->gdb_handle);
139 return wait_for_stop (cntxt);
140 }
141 else if (cntxt->gdb_stop_reason->reason == sr_wp_scope) {
142 gmi_exec_continue(cntxt->gdb_handle);
143 return wait_for_stop (cntxt);
144 }
145 cntxt->gdb_frames = gmi_stack_info_frame (cntxt->gdb_handle);
146 if (NULL == cntxt->gdb_frames)
147 GNUNET_break (0);
148
149 if (0 == cntxt->gdb_frames->line)
150 {
151 /*
152 * This happens if the program stops in a shared library (inner frames)
153 * We will move to outer frames until reaching the faulty line in the source code
154 */
155 cntxt->gdb_frames = gmi_stack_list_frames (cntxt->gdb_handle);
156 do
157 {
158 cntxt->gdb_frames = cntxt->gdb_frames->next;
159 }
160 while (0 == cntxt->gdb_frames->line);
161 }
162 /* Change current GDB frame to the one containing source code */
163 gmi_stack_select_frame(cntxt->gdb_handle, cntxt->gdb_frames->level);
164
165 return GDB_STATE_STOPPED;
166 }
167 return GDB_STATE_ERROR;
168}
169
170
171int
172GNUNET_MONKEY_ACTION_report_file (struct GNUNET_MONKEY_ACTION_Context *cntxt,
173 const char *dumpFileName)
174{
175 FILE *file = fopen (dumpFileName, "w");
176 GNUNET_assert (NULL != file);
177 fprintf (file, "%s", cntxt->debug_report);
178 fclose (file);
179 return GNUNET_OK;
180}
181
182
183int
184GNUNET_MONKEY_ACTION_report_email (struct GNUNET_MONKEY_ACTION_Context *cntxt)
185{
186 if (cntxt->debug_mode == DEBUG_MODE_REPORT_READY)
187 sendMail (cntxt->debug_report, cntxt->email_address);
188
189 return GNUNET_OK;
190}
191
192
193static int
194iterateExpressions (void *cls, int numColumns, char **colValues,
195 char **colNames)
196{
197 struct Expression *expression;
198
199 if (NULL == colValues[0] || NULL == colValues[1])
200 return 1; /* Error */
201
202 expression = GNUNET_malloc (sizeof (struct Expression));
203 expression->expressionSyntax = strdup (colValues[0]);
204 expression->lineNo = atoi (colValues[1]);
205
206 GNUNET_CONTAINER_DLL_insert (expressionListHead, expressionListTail,
207 expression);
208
209 return 0; /* OK */
210}
211
212
213static int
214scopeEndCallback (void *cls, int numColumns, char **colValues,
215 char **colNames)
216{
217 int *scopeEnd = (int *) cls;
218
219 *scopeEnd = atoi (colValues[0]);
220 if (*scopeEnd < 0)
221 return 1; /* Error */
222 return 0;
223}
224
225
226static struct Expression *
227getFaultyExpression (struct GNUNET_MONKEY_ACTION_Context *cntxt)
228{
229 struct Expression *faultyExpression = NULL;
230 struct Expression *tmp = NULL;
231 int expressionLength = 0;
232
233 tmp = expressionListHead;
234 while (NULL != tmp)
235 {
236 if ((tmp->lineNo == cntxt->gdb_frames->line)
237 && (strlen (tmp->expressionSyntax) > expressionLength))
238 {
239 expressionLength = strlen (tmp->expressionSyntax);
240 faultyExpression = tmp;
241 }
242 tmp = tmp->next;
243 }
244
245 return faultyExpression;
246}
247
248static int
249analyzeSegmentationFault (struct GNUNET_MONKEY_ACTION_Context *cntxt)
250{
251 struct Expression *tmp;
252
253
254 faultyExpression = getFaultyExpression (cntxt);
255
256 if (NULL != faultyExpression)
257 {
258 tmp = expressionListHead;
259 while (NULL != tmp)
260 {
261 const char *eval;
262 if (tmp != faultyExpression)
263 {
264 eval =
265 gmi_data_evaluate_expression (cntxt->gdb_handle,
266 tmp->expressionSyntax);
267 if (NULL != eval
268 && (strcmp (eval, "0x0") == 0
269 || strcmp (eval, "NULL") == 0))
270 {
271 cntxt->gdb_null_variable = tmp->expressionSyntax;
272 return GNUNET_OK;
273 }
274 }
275 tmp = tmp->next;
276 }
277 }
278 /* Set watch points on the faulty-expression's subexpressions */
279// if (NULL != faultyExpression) {
280// tmp = expressionListHead;
281// while (NULL != tmp) {
282// if (tmp != faultyExpression) {
283// /* Only subexpressions are interesting */
284// watchPoint = gmi_break_watch(cntxt->gdb_handle, wm_write, tmp->expressionSyntax);
285// if (!watchPoint)
286// {
287// printf("Error in setting watchpoint\n");
288// return 1;
289// }
290// printf("Watchpoint %d for expression: %s\n", watchPoint->number, watchPoint->exp);
291// mi_free_wp(watchPoint);
292// }
293// tmp = tmp->next;
294// }
295// return GNUNET_OK;
296// }
297 return GDB_STATE_ERROR;
298}
299
300
301
302static int
303analyzeCustomFault (struct GNUNET_MONKEY_ACTION_Context *cntxt)
304{
305 struct Expression *tmp;
306 faultyExpression = getFaultyExpression (cntxt);
307
308
309 if (NULL != faultyExpression)
310 {
311 tmp = expressionListHead;
312 while (NULL != tmp)
313 {
314 const char *eval;
315 eval =
316 gmi_data_evaluate_expression (cntxt->gdb_handle,
317 tmp->expressionSyntax);
318 if (NULL != eval) {
319 tmp->expressionValue = eval;
320 }
321 tmp = tmp->next;
322 }
323 }
324 return GNUNET_OK;
325}
326
327
328int
329GNUNET_MONKEY_ACTION_inspect_expression_database (struct
330 GNUNET_MONKEY_ACTION_Context
331 *cntxt)
332{
333 struct GNUNET_MONKEY_EDB_Context *edbCntxt;
334 int ret = GNUNET_OK;
335 int endScope;
336 const char *signalMeaning = cntxt->gdb_stop_reason->signal_meaning;
337
338 edbCntxt = GNUNET_MONKEY_EDB_connect (cntxt->expression_database_path);
339 if (NULL == edbCntxt)
340 {
341 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
342 "Unable to connect to Expression Database file!\n");
343 return GNUNET_NO;
344 }
345
346 ret = GNUNET_MONKEY_EDB_get_expression_scope_end (edbCntxt,
347 cntxt->gdb_frames->file,
348 cntxt->gdb_frames->line,
349 &scopeEndCallback,
350 &endScope);
351 if (endScope < 0)
352 return GNUNET_NO;
353
354
355 if (strcasecmp (signalMeaning, "Segmentation fault") == 0)
356 {
357 cntxt->bug_detected = BUG_NULL_POINTER;
358 GNUNET_MONKEY_EDB_get_expressions (edbCntxt,
359 cntxt->gdb_frames->file,
360 cntxt->gdb_frames->line, endScope,
361 &iterateExpressions, NULL);
362 ret = analyzeSegmentationFault (cntxt);
363 }
364 else if (strcasecmp (signalMeaning, "Aborted") == 0)
365 {
366 cntxt->bug_detected = BUG_CUSTOM;
367 GNUNET_MONKEY_EDB_get_sub_expressions (edbCntxt,
368 cntxt->gdb_frames->file,
369 cntxt->gdb_frames->line, endScope,
370 &iterateExpressions, NULL);
371 ret = analyzeCustomFault (cntxt);
372 }
373
374 GNUNET_MONKEY_EDB_disconnect (edbCntxt);
375 mi_disconnect (cntxt->gdb_handle);
376 return ret;
377}
378
379
380int
381GNUNET_MONKEY_ACTION_rerun_with_valgrind (struct GNUNET_MONKEY_ACTION_Context
382 *cntxt)
383{
384 char *valgrindCommand;
385 FILE *valgrindPipe;
386
387 GNUNET_asprintf(&cntxt->valgrind_output_tmp_file_name, "%d", rand());
388 cntxt->debug_mode = DEBUG_MODE_VALGRIND;
389 GNUNET_asprintf (&valgrindCommand, "valgrind --leak-check=yes --log-file=%s %s",
390 cntxt->valgrind_output_tmp_file_name, cntxt->binary_name);
391 valgrindPipe = popen (valgrindCommand, "r");
392 if (NULL == valgrindPipe)
393 {
394 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error in running Valgrind!\n");
395 GNUNET_free (valgrindCommand);
396 return GNUNET_NO;
397 }
398
399 pclose(valgrindPipe);
400 GNUNET_free(valgrindCommand);
401 return GNUNET_OK;
402}
403
404
405int
406GNUNET_MONKEY_ACTION_rerun_with_gdb (struct GNUNET_MONKEY_ACTION_Context
407 *cntxt)
408{
409 cntxt->debug_mode = DEBUG_MODE_GDB;
410 /* This is like a file-handle for fopen.
411 Here we have all the state of gdb "connection". */
412 if (NULL != cntxt->gdb_binary_path)
413 mi_set_gdb_exe (cntxt->gdb_binary_path);
414 int ret;
415
416 /* Connect to gdb child. */
417 cntxt->gdb_handle = mi_connect_local ();
418 if (!cntxt->gdb_handle)
419 {
420 printf ("Connect failed\n");
421 return GNUNET_NO;
422 }
423 printf ("Connected to gdb!\n");
424
425 /* Set all callbacks. */
426 mi_set_console_cb (cntxt->gdb_handle, cb_console, NULL);
427 mi_set_target_cb (cntxt->gdb_handle, cb_target, NULL);
428 mi_set_log_cb (cntxt->gdb_handle, cb_log, NULL);
429 mi_set_async_cb (cntxt->gdb_handle, cb_async, NULL);
430 mi_set_to_gdb_cb (cntxt->gdb_handle, cb_to, NULL);
431 mi_set_from_gdb_cb (cntxt->gdb_handle, cb_from, NULL);
432
433 /* Set the name of the child and the command line arguments. */
434 if (!gmi_set_exec (cntxt->gdb_handle, cntxt->binary_name, NULL))
435 {
436 printf ("Error setting exec y args\n");
437 mi_disconnect (cntxt->gdb_handle);
438 return GNUNET_NO;
439 }
440
441 /* Tell gdb to attach the child to a terminal. */
442 if (!gmi_target_terminal (cntxt->gdb_handle, ttyname (STDIN_FILENO)))
443 {
444 printf ("Error selecting target terminal\n");
445 mi_disconnect (cntxt->gdb_handle);
446 return GNUNET_NO;
447 }
448
449 if ((NULL != cntxt->inspect_expression) && (NULL != cntxt->inspect_function))
450 {
451 /* Setting a breakpoint at the function containing the expression to inspect */
452 mi_bkpt *bp = gmi_break_insert_full(cntxt->gdb_handle, 0, 0, NULL, -1, -1, cntxt->inspect_function);
453 if (NULL == bp)
454 {
455 printf("Error setting breakpoint at function:%s\n", cntxt->inspect_function);
456 mi_disconnect(cntxt->gdb_handle);
457 return GNUNET_NO;
458 }
459 mi_free_bkpt(bp);
460 }
461
462 /* Run the program. */
463 if (!gmi_exec_run (cntxt->gdb_handle))
464 {
465 printf ("Error in run!\n");
466 mi_disconnect (cntxt->gdb_handle);
467 return GNUNET_NO;
468 }
469 /* Here we should be stopped when the program crashes */
470 ret = wait_for_stop (cntxt);
471 if (ret == GDB_STATE_ERROR)
472 mi_disconnect (cntxt->gdb_handle);
473
474 return ret;
475}
476
477
478static int
479getExpressionListSize(struct Expression *head)
480{
481 int size, count = 0;
482 struct Expression *tmp = head;
483
484 while (NULL != tmp) {
485 count++;
486 tmp = tmp->next;
487 }
488 /* Since the faulty expression is the longest in the expression list */
489 size = count * strlen(faultyExpression->expressionSyntax) * sizeof(char);
490 return size;
491}
492
493
494static const char *
495expressionListToString (struct Expression *head)
496{
497 char *string = GNUNET_malloc (getExpressionListSize(head));
498 char *strTmp;
499 struct Expression *tmp = head;
500
501 GNUNET_asprintf (&strTmp, "%s = %s\n", tmp->expressionSyntax, NULL == tmp->expressionValue ? "Not evaluated" : tmp->expressionValue);
502 strcpy (string, strTmp);
503 GNUNET_free (strTmp);
504 tmp = tmp->next;
505
506 while (NULL != tmp)
507 {
508 GNUNET_asprintf (&strTmp, "%s = %s\n", tmp->expressionSyntax, NULL == tmp->expressionValue ? "Not evaluated" : tmp->expressionValue);
509 strcat (string, strTmp);
510 GNUNET_free (strTmp);
511 tmp = tmp->next;
512 }
513 return string;
514}
515
516#if 0
517static int
518getWatchInfoListSize(struct WatchInfo *head)
519{
520 int count = 0;
521 int largestStr = 0;
522 struct WatchInfo *tmp = head;
523
524 while (NULL != tmp) {
525 if (largestStr < strlen(tmp->value))
526 largestStr = strlen(tmp->value);
527 tmp = tmp->next;
528 count++;
529 }
530
531 return count * largestStr;
532}
533
534static const char*
535watchInfoListToString(struct WatchInfo *head)
536{
537 char *string = GNUNET_malloc(getWatchInfoListSize(head));
538 char *strTmp;
539 struct WatchInfo *tmp = head;
540
541 GNUNET_asprintf (&strTmp, "%s\t \t%s\n", tmp->hitNumber, tmp->value);
542 strcpy (string, strTmp);
543 GNUNET_free (strTmp);
544 tmp = tmp->next;
545
546 while (NULL != tmp) {
547 GNUNET_asprintf (&strTmp, "%s\t \t%s\n", tmp->hitNumber, tmp->value);
548 strcat (string, strTmp);
549 GNUNET_free(strTmp);
550 tmp = tmp->next;
551 }
552
553 return string;
554}
555#endif
556
557static const char* getValgrindOutput(struct GNUNET_MONKEY_ACTION_Context *cntxt)
558{
559 char* valgrindOutput;
560 int size;
561 FILE *valgrindFile = fopen(cntxt->valgrind_output_tmp_file_name, "r");
562 fseek(valgrindFile, 0L, SEEK_END);
563 size = ftell(valgrindFile);
564 fseek(valgrindFile, 0L, SEEK_SET);
565
566 valgrindOutput = GNUNET_malloc(size);
567 fread(valgrindOutput, size - 1, 1, valgrindFile);
568 fclose(valgrindFile);
569 return valgrindOutput;
570}
571
572
573int
574GNUNET_MONKEY_ACTION_format_report (struct GNUNET_MONKEY_ACTION_Context
575 *cntxt)
576{
577 switch (cntxt->debug_mode)
578 {
579 case DEBUG_MODE_GDB:
580 if (cntxt->bug_detected == BUG_NULL_POINTER)
581 {
582 GNUNET_asprintf (&(cntxt->debug_report),
583 "Bug detected in file:%s\nfunction:%s\nline:%d\nreason:%s\nreceived signal:%s\n%s\n Details:\n Expression:%s is NULL\n",
584 cntxt->gdb_frames->file, cntxt->gdb_frames->func,
585 cntxt->gdb_frames->line,
586 mi_reason_enum_to_str (cntxt->gdb_stop_reason->
587 reason),
588 cntxt->gdb_stop_reason->signal_name,
589 cntxt->gdb_stop_reason->signal_meaning,
590 cntxt->gdb_null_variable);
591 }
592 else if (cntxt->bug_detected == BUG_CUSTOM)
593 {
594 if (NULL == cntxt->inspect_expression)
595 {
596 /* Assertion Failure */
597 const char *expToString = expressionListToString(expressionListHead);
598 GNUNET_asprintf (&(cntxt->debug_report),
599 "Bug detected in file:%s\nfunction:%s\nline:%d\nreceived signal:%s\n%s\nDetails:\nAssertion Failure\nExpression evaluation:\n%s\n",
600 cntxt->gdb_frames->file,
601 cntxt->gdb_frames->func,
602 cntxt->gdb_frames->line,
603 cntxt->gdb_stop_reason->signal_name,
604 cntxt->gdb_stop_reason->signal_meaning,
605 expToString);
606 }
607 else
608 {
609 /* Inspection of user-defined expression */
610 /*
611 GNUNET_asprintf(&(cntxt->debug_report),
612 "Inspection of expression: %s in function: %s, file:%s\nHit Number: \t \tValue:\n%s",
613 cntxt->inspect_expression, cntxt->inspect_function, cntxt->binary_name, watchInfoListToString(watchInfoListHead));
614 */
615 }
616 }
617 break;
618 case DEBUG_MODE_VALGRIND:
619 GNUNET_asprintf (&(cntxt->debug_report),
620 "Bug detected in file:%s\nfunction:%s\nline:%d\nreceived signal:%s\n%s\n Details:\n Memory Check from Valgrind:\n%s",
621 cntxt->gdb_frames->file, cntxt->gdb_frames->func,
622 cntxt->gdb_frames->line,
623 cntxt->gdb_stop_reason->signal_name,
624 cntxt->gdb_stop_reason->signal_meaning,
625 getValgrindOutput(cntxt));
626 break;
627 default:
628 break;
629 }
630
631 cntxt->debug_mode = DEBUG_MODE_REPORT_READY;
632 return GNUNET_OK;
633}
634
635
636int
637GNUNET_MONKEY_ACTION_delete_context(struct GNUNET_MONKEY_ACTION_Context *cntxt)
638{
639 if (NULL != cntxt->debug_report)
640 GNUNET_free(cntxt->debug_report);
641 if (NULL != cntxt->valgrind_output_tmp_file_name) {
642 remove(cntxt->valgrind_output_tmp_file_name);
643 GNUNET_free(cntxt->valgrind_output_tmp_file_name);
644 }
645
646 GNUNET_free(cntxt);
647 return GNUNET_OK;
648}
649
650
651int
652GNUNET_MONKEY_ACTION_check_bug_redundancy ()
653{
654 return GNUNET_OK;
655}
diff --git a/src/monkey/bug_assertion_failure.c b/src/monkey/bug_assertion_failure.c
deleted file mode 100644
index 416fd6fe3..000000000
--- a/src/monkey/bug_assertion_failure.c
+++ /dev/null
@@ -1,15 +0,0 @@
1#include <stdio.h>
2#include <assert.h>
3
4void assertionFailure()
5{
6 int x = 5;
7 printf("Assertion Failure Now!\n");
8 assert(x < 4);
9}
10
11int main(int argc, char *argv[])
12{
13 assertionFailure();
14 return 0;
15}
diff --git a/src/monkey/bug_bad_memory_access.c b/src/monkey/bug_bad_memory_access.c
deleted file mode 100644
index 54e50ade0..000000000
--- a/src/monkey/bug_bad_memory_access.c
+++ /dev/null
@@ -1,16 +0,0 @@
1#include <stdio.h>
2#include <string.h>
3
4
5void badMemoryAccess()
6{
7 int *p = (int*) 0x4252352;
8 printf("Bad memory access now!\n");
9 *p = 5;
10}
11
12int main(int argc, char *argv[])
13{
14 badMemoryAccess();
15 return 0;
16}
diff --git a/src/monkey/bug_crypto_crc.c b/src/monkey/bug_crypto_crc.c
deleted file mode 100644
index f252785fe..000000000
--- a/src/monkey/bug_crypto_crc.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19
20 For the actual CRC code:
21 Copyright abandoned; this code is in the public domain.
22 Provided to GNUnet by peter@horizon.com
23*/
24
25/**
26 * @file monkey/bug_crypto_crc.c
27 * @brief implementation of CRC32 (this code has been copied from GNUnet util source directory, and modified to be Seaspider friendly)
28 * @author Christian Grothoff, Safey A.Halim
29 */
30
31#include <assert.h>
32#include <stdlib.h>
33#include <stdio.h>
34#include <stdint.h>
35
36#define Z_NULL 0
37
38
39#define POLYNOMIAL (unsigned long)0xedb88320
40static unsigned long crc_table[256];
41
42/*
43 * This routine writes each crc_table entry exactly once,
44 * with the ccorrect final value. Thus, it is safe to call
45 * even on a table that someone else is using concurrently.
46 */
47static void
48crc_init ()
49{
50 static int once;
51 unsigned int i, j;
52 unsigned long h = 1;
53
54 if (once)
55 return;
56 once = 1;
57 crc_table[0] = 0;
58 for (i = 128; i; i >>= 1)
59 {
60 h = (h >> 1) ^ ((h & 1) ? POLYNOMIAL : 0);
61 /* h is now crc_table[i] */
62 for (j = 0; j < 256; j += 2 * i)
63 crc_table[i + j] = crc_table[j] ^ h;
64 }
65}
66
67/*
68 * This computes the standard preset and inverted CRC, as used
69 * by most networking standards. Start by passing in an initial
70 * chaining value of 0, and then pass in the return value from the
71 * previous crc32() call. The final return value is the CRC.
72 * Note that this is a little-endian CRC, which is best used with
73 * data transmitted lsbit-first, and it should, itself, be appended
74 * to data in little-endian byte and bit order to preserve the
75 * property of detecting all burst errors of length 32 bits or less.
76 */
77static unsigned long
78crc_go (unsigned long crc, const char *buf, size_t len)
79{
80 crc_init ();
81 assert (crc_table[255] != 0);
82 crc ^= 0xffffffff;
83 while (len--)
84 crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
85 return crc ^ 0xffffffff;
86}
87
88
89/**
90 * Compute the CRC32 checksum for the first len bytes of the buffer.
91 *
92 * @param buf the data over which we're taking the CRC
93 * @param len the length of the buffer
94 * @return the resulting CRC32 checksum
95 */
96int32_t
97crc32_n (const void *buf, size_t len)
98{
99 unsigned long crc;
100 crc = crc_go (0L, Z_NULL, 0);
101 crc = crc_go (crc, (char *) buf, len);
102 return crc;
103}
104
105
106int main ()
107{
108 char buf[1024];
109 int i;
110 for (i = 0; i < 1024; i++)
111 {
112 buf[i] = (char) i;
113 }
114 for (i = 0; i < 1024; i++)
115 {
116 printf("%d\n", crc32_n (&buf[i], 1024 - i));
117 }
118 return 0;
119}
120
121/* end of bug_crypto_crc.c */
diff --git a/src/monkey/bug_null_pointer_exception.c b/src/monkey/bug_null_pointer_exception.c
deleted file mode 100644
index 4accd65af..000000000
--- a/src/monkey/bug_null_pointer_exception.c
+++ /dev/null
@@ -1,21 +0,0 @@
1#include <stdio.h>
2#include <string.h>
3
4
5struct CrashStruct {
6 const char *crashValue;
7};
8
9void crashFunction()
10{
11 struct CrashStruct *crashStruct;
12 crashStruct = NULL;
13 printf("Now the program will crash!\n");
14 crashStruct->crashValue = "hello!";
15}
16
17int main(int argc, char *argv[])
18{
19 crashFunction();
20 return 0;
21}
diff --git a/src/monkey/edb_api.c b/src/monkey/edb_api.c
deleted file mode 100644
index 296d7c838..000000000
--- a/src/monkey/edb_api.c
+++ /dev/null
@@ -1,194 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file monkey/edb_api.c
23 * @brief Monkey API for accessing the Expression Database (edb)
24 */
25
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_monkey_edb.h"
29#include <sqlite3.h>
30
31
32/**
33 * Context for Database connection and Expressions
34 */
35struct GNUNET_MONKEY_EDB_Context
36{
37 /**
38 * Database connection
39 */
40 sqlite3 *db_handle;
41};
42
43
44/**
45 * Establish a connection to the Expression Database
46 *
47 * @param db_file_name path the Expression Database file
48 * @return context to use for Accessing the Expression Database, NULL on error
49 */
50struct GNUNET_MONKEY_EDB_Context *
51GNUNET_MONKEY_EDB_connect (const char *db_file_name)
52{
53 int err;
54 struct GNUNET_MONKEY_EDB_Context *ctxt =
55 GNUNET_malloc (sizeof (struct GNUNET_MONKEY_EDB_Context));
56
57 err = sqlite3_open (db_file_name, &ctxt->db_handle);
58 if (err)
59 {
60 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
61 "Cannot open Expression Database. `%s'\n",
62 sqlite3_errmsg (ctxt->db_handle));
63 return NULL;
64 }
65 return ctxt;
66}
67
68
69/**
70 * Disconnect from Database, and cleanup resources
71 *
72 * @param context context containing the Expression Database handle
73 * @return GNUNET_OK on success, GNUNET_NO on failure
74 */
75int
76GNUNET_MONKEY_EDB_disconnect (struct GNUNET_MONKEY_EDB_Context *cntxt)
77{
78 sqlite3_close (cntxt->db_handle);
79 GNUNET_free (cntxt);
80 return GNUNET_OK;
81}
82
83
84/**
85 * Return the line number of the end-of-scope for the expression indicated by start_line_no
86 *
87 * @param cntxt context containing the Expression Database handle
88 * @param file_name path to the file in which the expression in question exists
89 * @param start_line_no expression's line
90 * @param iter callback function, iterator for values returned from the Database
91 * @param iter_cls closure for the expression iterator, will contain the scope-end line number
92 * @return GNUNET_OK on success, GNUNET_NO on failure
93 */
94int
95GNUNET_MONKEY_EDB_get_expression_scope_end(struct GNUNET_MONKEY_EDB_Context *cntxt,
96 const char *file_name, int start_line_no,
97 GNUNET_MONKEY_ExpressionIterator iter,
98 void *iter_cls)
99{
100 int err;
101 char *errMsg;
102 char *query;
103
104 if (asprintf(&query, "select end_lineno from Expression where file_name LIKE \'%%/%s\' and start_lineno = %d", file_name, start_line_no) == -1) {
105 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Memory allocation problem occurred during creating database query!\n");
106 return GNUNET_NO;
107 }
108
109 err = sqlite3_exec(cntxt->db_handle, query, iter, iter_cls, &errMsg);
110 if (err) {
111 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
112 "Error occurred while executing Database query. `%s'",
113 errMsg);
114 return GNUNET_NO;
115 }
116 return GNUNET_OK;
117}
118
119
120/**
121 * Run an SQLite query to retrieve those expressions that are previous to
122 * given expression and are in the same scope of the given expression
123 *
124 * @param cntxt context containing the Expression Database handle
125 * @param file_name path to the file in which the expression in question exists
126 * @param start_line_no expression beginning line
127 * @param end_line_no line number for the expression's scope end
128 * @param iter callback function, iterator for expressions returned from the Database
129 * @param iter_cls closure for the expression iterator
130 * @return GNUNET_OK success, GNUNET_NO failure
131 */
132int
133GNUNET_MONKEY_EDB_get_expressions (struct GNUNET_MONKEY_EDB_Context *cntxt,
134 const char *file_name, int start_line_no,
135 int end_line_no,
136 GNUNET_MONKEY_ExpressionIterator iter,
137 void *iter_cls)
138{
139 int err;
140 char *errMsg;
141 char *query;
142 if (asprintf
143 (&query,
144 "select expr_syntax, start_lineno from Expression where file_name LIKE \'%%/%s\' and start_lineno <= %d and end_lineno = %d",
145 file_name, start_line_no, end_line_no) == -1)
146 {
147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148 "Memory allocation problem occurred!\n");
149 return GNUNET_NO;
150 }
151
152 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
153 if (err)
154 {
155 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
156 "Error occurred while executing Database query. `%s'",
157 errMsg);
158 return GNUNET_NO;
159 }
160 return GNUNET_OK;
161}
162
163
164int
165GNUNET_MONKEY_EDB_get_sub_expressions (struct GNUNET_MONKEY_EDB_Context *cntxt,
166 const char *file_name, int start_line_no,
167 int end_line_no,
168 GNUNET_MONKEY_ExpressionIterator iter,
169 void *iter_cls)
170{
171 int err;
172 char *errMsg;
173 char *query;
174 if (asprintf
175 (&query,
176 "select expr_syntax, start_lineno from Expression where file_name LIKE \'%%/%s\' and start_lineno = %d and end_lineno = %d",
177 file_name, start_line_no, end_line_no) == -1)
178 {
179 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
180 "Memory allocation problem occurred!\n");
181 return GNUNET_NO;
182 }
183
184 err = sqlite3_exec (cntxt->db_handle, query, iter, iter_cls, &errMsg);
185 if (err)
186 {
187 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
188 "Error occurred while executing Database query. `%s'",
189 errMsg);
190 return GNUNET_NO;
191 }
192 return GNUNET_OK;
193}
194
diff --git a/src/monkey/gdbmi.h b/src/monkey/gdbmi.h
deleted file mode 100644
index c03d09b61..000000000
--- a/src/monkey/gdbmi.h
+++ /dev/null
@@ -1,716 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2009 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Comments:
7 Main header for libmigdb.
8
9***************************************************************************/
10
11#ifndef GDBMI_H
12#define GDBMI_H
13
14#ifdef __cplusplus
15extern "C"
16{
17#if 0 /* keep Emacsens' auto-indent happy */
18}
19#endif
20#endif
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h> /* pid_t */
25
26#define MI_OK 0
27#define MI_OUT_OF_MEMORY 1
28#define MI_PIPE_CREATE 2
29#define MI_FORK 3
30#define MI_DEBUGGER_RUN 4
31#define MI_PARSER 5
32#define MI_UNKNOWN_ASYNC 6
33#define MI_UNKNOWN_RESULT 7
34#define MI_FROM_GDB 8
35#define MI_GDB_TIME_OUT 9
36#define MI_GDB_DIED 10
37#define MI_MISSING_XTERM 11
38#define MI_CREATE_TEMPORAL 12
39#define MI_MISSING_GDB 13
40#define MI_LAST_ERROR 13
41
42#define MI_R_NONE 0 /* We are no waiting any response. */
43#define MI_R_SKIP 1 /* We want to discard it. */
44#define MI_R_FE_AND_S 2 /* Wait for done. */
45#define MI_R_E_ARGS 3
46
47enum mi_val_type { t_const, t_tuple, t_list };
48
49/* Types and subtypes. */
50/* Type. */
51#define MI_T_OUT_OF_BAND 0
52#define MI_T_RESULT_RECORD 1
53/* Out of band subtypes. */
54#define MI_ST_ASYNC 0
55#define MI_ST_STREAM 1
56/* Async sub-subtypes. */
57#define MI_SST_EXEC 0
58#define MI_SST_STATUS 1
59#define MI_SST_NOTIFY 2
60/* Stream sub-subtypes. */
61#define MI_SST_CONSOLE 3
62#define MI_SST_TARGET 4
63#define MI_SST_LOG 5
64/* Classes. */
65/* Async classes. */
66#define MI_CL_UNKNOWN 0
67#define MI_CL_STOPPED 1
68#define MI_CL_DOWNLOAD 2
69/* Result classes. */
70#define MI_CL_DONE 2
71#define MI_CL_RUNNING 3
72#define MI_CL_CONNECTED 4
73#define MI_CL_ERROR 5
74#define MI_CL_EXIT 6
75
76#define MI_DEFAULT_TIME_OUT 10
77
78#define MI_DIS_ASM 0
79#define MI_DIS_SRC_ASM 1
80
81/* Implemented workaround for gdb bugs that we can dis/enable. */
82/* At least gdb<=6.1.1 fails to find a source file with absolute path if the
83 name is for a psym instead of a sym. psym==partially loaded symbol table. */
84#define MI_PSYM_SEARCH 0
85
86#define MI_VERSION_STR "0.8.12"
87#define MI_VERSION_MAJOR 0
88#define MI_VERSION_MIDDLE 8
89#define MI_VERSION_MINOR 12
90
91struct mi_results_struct
92{
93 char *var; /* Result name or NULL if just a value. */
94 enum mi_val_type type;
95 union
96 {
97 char *cstr;
98 struct mi_results_struct *rs;
99 } v;
100 struct mi_results_struct *next;
101};
102typedef struct mi_results_struct mi_results;
103
104struct mi_output_struct
105{
106 /* Type of output. */
107 char type;
108 char stype;
109 char sstype;
110 char tclass;
111 /* Content. */
112 mi_results *c;
113 /* Always modeled as a list. */
114 struct mi_output_struct *next;
115};
116typedef struct mi_output_struct mi_output;
117
118typedef void (*stream_cb)(const char *, void *);
119typedef void (*async_cb)(mi_output *o, void *);
120typedef int (*tm_cb)(void *);
121
122/* Values of this structure shouldn't be manipulated by the user. */
123struct mi_h_struct
124{
125 /* Pipes connected to gdb. */
126 int to_gdb[2];
127 int from_gdb[2];
128 /* Streams for the pipes. */
129 FILE *to, *from;
130 /* PID of child gdb. */
131 pid_t pid;
132 char died;
133 /* Which rensponse we are waiting for. */
134 /*int response;*/
135 /* The line we are reading. */
136 char *line;
137 int llen, lread;
138 /* Parsed output. */
139 mi_output *po, *last;
140 /* Tunneled streams callbacks. */
141 stream_cb console;
142 void *console_data;
143 stream_cb target;
144 void *target_data;
145 stream_cb log;
146 void *log_data;
147 /* Async responses callback. */
148 async_cb async;
149 void *async_data;
150 /* Callbacks to get echo of gdb dialog. */
151 stream_cb to_gdb_echo;
152 void *to_gdb_echo_data;
153 stream_cb from_gdb_echo;
154 void *from_gdb_echo_data;
155 /* Time out */
156 tm_cb time_out_cb;
157 void *time_out_cb_data;
158 int time_out;
159 /* Ugly workaround for some of the show responses :-( */
160 int catch_console;
161 char *catched_console;
162 /* MI version, currently unknown but the user can force v2 */
163 unsigned version;
164};
165typedef struct mi_h_struct mi_h;
166
167#define MI_TO(a) ((a)->to_gdb[1])
168
169enum mi_bkp_type { t_unknown=0, t_breakpoint=1, t_hw=2 };
170enum mi_bkp_disp { d_unknown=0, d_keep=1, d_del=2 };
171enum mi_bkp_mode { m_file_line=0, m_function=1, m_file_function=2, m_address=3 };
172
173struct mi_bkpt_struct
174{
175 int number;
176 enum mi_bkp_type type;
177 enum mi_bkp_disp disp; /* keep or del if temporal */
178 char enabled;
179 void *addr;
180 char *func;
181 char *file;
182 int line;
183 int ignore;
184 int times;
185
186 /* For the user: */
187 char *cond;
188 char *file_abs;
189 int thread;
190 enum mi_bkp_mode mode;
191 struct mi_bkpt_struct *next;
192};
193typedef struct mi_bkpt_struct mi_bkpt;
194
195enum mi_wp_mode { wm_unknown=0, wm_write=1, wm_read=2, wm_rw=3 };
196
197struct mi_wp_struct
198{
199 int number;
200 char *exp;
201 enum mi_wp_mode mode;
202
203 /* For the user: */
204 struct mi_wp_struct *next;
205 char enabled;
206};
207typedef struct mi_wp_struct mi_wp;
208
209struct mi_frames_struct
210{
211 int level; /* The frame number, 0 being the topmost frame, i.e. the innermost
212 function. */
213 void *addr; /* The `$pc' value for that frame. */
214 char *func; /* Function name. */
215 char *file; /* File name of the source file where the function lives. */
216 char *from;
217 int line; /* Line number corresponding to the `$pc'. */
218 /* When arguments are available: */
219 mi_results *args;
220 int thread_id;
221 /* When more than one is provided: */
222 struct mi_frames_struct *next;
223};
224typedef struct mi_frames_struct mi_frames;
225
226struct mi_aux_term_struct
227{
228 pid_t pid;
229 char *tty;
230};
231typedef struct mi_aux_term_struct mi_aux_term;
232
233struct mi_pty_struct
234{
235 char *slave;
236 int master;
237};
238typedef struct mi_pty_struct mi_pty;
239
240enum mi_gvar_fmt { fm_natural=0, fm_binary=1, fm_decimal=2, fm_hexadecimal=3,
241 fm_octal=4,
242 /* Only for registers format: */
243 fm_raw=5 };
244enum mi_gvar_lang { lg_unknown=0, lg_c, lg_cpp, lg_java };
245
246#define MI_ATTR_DONT_KNOW 0
247#define MI_ATTR_NONEDITABLE 1
248#define MI_ATTR_EDITABLE 2
249
250struct mi_gvar_struct
251{
252 char *name;
253 int numchild;
254 char *type;
255 enum mi_gvar_fmt format;
256 enum mi_gvar_lang lang;
257 char *exp;
258 int attr;
259
260 /* MI v2 fills it, not yet implemented here. */
261 /* Use gmi_var_evaluate_expression. */
262 char *value;
263
264 /* Pointer to the parent. NULL if none. */
265 struct mi_gvar_struct *parent;
266 /* List containing the children.
267 Filled by gmi_var_list_children.
268 NULL if numchild==0 or not yet filled. */
269 struct mi_gvar_struct *child;
270 /* Next var in the list. */
271 struct mi_gvar_struct *next;
272
273 /* For the user: */
274 char opened; /* We will show its children. 1 when we fill "child" */
275 char changed; /* Needs to be updated. 0 when created. */
276 int vischild; /* How many items visible. numchild when we fill "child" */
277 int depth; /* How deep is this var. */
278 char ispointer;
279};
280typedef struct mi_gvar_struct mi_gvar;
281
282struct mi_gvar_chg_struct
283{
284 char *name;
285 int in_scope; /* if true the other fields apply. */
286 char *new_type; /* NULL if type_changed==false */
287 int new_num_children; /* only when new_type!=NULL */
288
289 struct mi_gvar_chg_struct *next;
290};
291typedef struct mi_gvar_chg_struct mi_gvar_chg;
292
293
294/* A list of assembler instructions. */
295struct mi_asm_insn_struct
296{
297 void *addr;
298 char *func;
299 unsigned offset;
300 char *inst;
301
302 struct mi_asm_insn_struct *next;
303};
304typedef struct mi_asm_insn_struct mi_asm_insn;
305
306/* A list of source lines containing assembler instructions. */
307struct mi_asm_insns_struct
308{
309 char *file;
310 int line;
311 mi_asm_insn *ins;
312
313 struct mi_asm_insns_struct *next;
314};
315typedef struct mi_asm_insns_struct mi_asm_insns;
316
317/* Changed register. */
318struct mi_chg_reg_struct
319{
320 int reg;
321 char *val;
322 char *name;
323 char updated;
324
325 struct mi_chg_reg_struct *next;
326};
327typedef struct mi_chg_reg_struct mi_chg_reg;
328
329/*
330 Examining gdb sources and looking at docs I can see the following "stop"
331reasons:
332
333Breakpoints:
334a) breakpoint-hit (bkptno) + frame
335Also: without reason for temporal breakpoints.
336
337Watchpoints:
338b) watchpoint-trigger (wpt={number,exp};value={old,new}) + frame
339c) read-watchpoint-trigger (hw-rwpt{number,exp};value={value}) + frame
340d) access-watchpoint-trigger (hw-awpt{number,exp};value={[old,]new}) + frame
341e) watchpoint-scope (wpnum) + frame
342
343Movement:
344f) function-finished ([gdb-result-var,return-value]) + frame
345g) location-reached + frame
346h) end-stepping-range + frame
347
348Exit:
349i) exited-signalled (signal-name,signal-meaning)
350j) exited (exit-code)
351k) exited-normally
352
353Signal:
354l) signal-received (signal-name,signal-meaning) + frame
355
356Plus: thread-id
357*/
358enum mi_stop_reason
359{
360 sr_unknown=0,
361 sr_bkpt_hit,
362 sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
363 sr_function_finished, sr_location_reached, sr_end_stepping_range,
364 sr_exited_signalled, sr_exited, sr_exited_normally,
365 sr_signal_received
366};
367
368struct mi_stop_struct
369{
370 enum mi_stop_reason reason; /* If more than one reason just the last. */
371 /* Flags indicating if non-pointer fields are filled. */
372 char have_thread_id;
373 char have_bkptno;
374 char have_exit_code;
375 char have_wpno;
376 /* Where stopped. Doesn't exist for sr_exited*. */
377 int thread_id;
378 mi_frames *frame;
379 /* sr_bkpt_hit */
380 int bkptno;
381 /* sr_*wp_* no scope */
382 mi_wp *wp;
383 char *wp_old;
384 char *wp_val;
385 /* sr_wp_scope */
386 int wpno;
387 /* sr_function_finished. Not for void func. */
388 char *gdb_result_var;
389 char *return_value;
390 /* sr_exited_signalled, sr_signal_received */
391 char *signal_name;
392 char *signal_meaning;
393 /* sr_exited */
394 int exit_code;
395};
396typedef struct mi_stop_struct mi_stop;
397
398/* Variable containing the last error. */
399extern int mi_error;
400extern char *mi_error_from_gdb;
401const char *mi_get_error_str();
402
403/* Indicate the name of gdb exe. Default is /usr/bin/gdb */
404void mi_set_gdb_exe(const char *name);
405const char *mi_get_gdb_exe();
406/* Indicate the name of a file containing commands to send at start-up */
407void mi_set_gdb_start(const char *name);
408const char *mi_get_gdb_start();
409/* Indicate the name of a file containing commands to send after connection */
410void mi_set_gdb_conn(const char *name);
411const char *mi_get_gdb_conn();
412void mi_send_target_commands(mi_h *h);
413/* Connect to a local copy of gdb. */
414mi_h *mi_connect_local();
415/* Close connection. You should ask gdb to quit first. */
416void mi_disconnect(mi_h *h);
417/* Force MI version. */
418#define MI_VERSION2U(maj,mid,min) (maj*0x1000000+mid*0x10000+min)
419void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
420 unsigned vMinor);
421void mi_set_workaround(unsigned wa, int enable);
422int mi_get_workaround(unsigned wa);
423/* Parse gdb output. */
424mi_output *mi_parse_gdb_output(const char *str);
425/* Functions to set/get the tunneled streams callbacks. */
426void mi_set_console_cb(mi_h *h, stream_cb cb, void *data);
427void mi_set_target_cb(mi_h *h, stream_cb cb, void *data);
428void mi_set_log_cb(mi_h *h, stream_cb cb, void *data);
429stream_cb mi_get_console_cb(mi_h *h, void **data);
430stream_cb mi_get_target_cb(mi_h *h, void **data);
431stream_cb mi_get_log_cb(mi_h *h, void **data);
432/* The callback to deal with async events. */
433void mi_set_async_cb(mi_h *h, async_cb cb, void *data);
434async_cb mi_get_async_cb(mi_h *h, void **data);
435/* Time out in gdb responses. */
436void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data);
437tm_cb mi_get_time_out_cb(mi_h *h, void **data);
438void mi_set_time_out(mi_h *h, int to);
439int mi_get_time_out(mi_h *h);
440/* Callbacks to "see" the dialog with gdb. */
441void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data);
442void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data);
443stream_cb mi_get_to_gdb_cb(mi_h *h, void **data);
444stream_cb mi_get_from_gdb_cb(mi_h *h, void **data);
445/* Sends a message to gdb. */
446int mi_send(mi_h *h, const char *format, ...);
447/* Wait until gdb sends a response. */
448mi_output *mi_get_response_blk(mi_h *h);
449/* Check if gdb sent a complete response. Use with mi_retire_response. */
450int mi_get_response(mi_h *h);
451/* Get the last response. Use with mi_get_response. */
452mi_output *mi_retire_response(mi_h *h);
453/* Look for a result record in gdb output. */
454mi_output *mi_get_rrecord(mi_output *r);
455/* Look if the output contains an async stop.
456 If that's the case return the reason for the stop.
457 If the output contains an error the description is returned in reason. */
458int mi_get_async_stop_reason(mi_output *r, char **reason);
459mi_stop *mi_get_stopped(mi_results *r);
460mi_frames *mi_get_async_frame(mi_output *r);
461/* Wait until gdb sends a response.
462 Then check if the response is of the desired type. */
463int mi_res_simple_exit(mi_h *h);
464int mi_res_simple_done(mi_h *h);
465int mi_res_simple_running(mi_h *h);
466int mi_res_simple_connected(mi_h *h);
467/* It additionally extracts an specified variable. */
468mi_results *mi_res_done_var(mi_h *h, const char *var);
469/* Extract a frames list from the response. */
470mi_frames *mi_res_frames_array(mi_h *h, const char *var);
471mi_frames *mi_res_frames_list(mi_h *h);
472mi_frames *mi_parse_frame(mi_results *c);
473mi_frames *mi_res_frame(mi_h *h);
474/* Create an auxiliar terminal using xterm. */
475mi_aux_term *gmi_start_xterm();
476/* Indicate the name of xterm exe. Default is /usr/bin/X11/xterm */
477void mi_set_xterm_exe(const char *name);
478const char *mi_get_xterm_exe();
479/* Kill the auxiliar terminal and release the structure. */
480void gmi_end_aux_term(mi_aux_term *t);
481/* Look for a free Linux VT for the child. */
482mi_aux_term *gmi_look_for_free_vt();
483/* Look for a free and usable Linux VT. */
484int mi_look_for_free_vt();
485/* Close master and release the structure. */
486void gmi_end_pty(mi_pty *p);
487/* Look for a free pseudo terminal. */
488mi_pty *gmi_look_for_free_pty();
489/* Extract a list of thread IDs from response. */
490int mi_res_thread_ids(mi_h *h, int **list);
491int mi_get_thread_ids(mi_output *res, int **list);
492/* A variable response. */
493mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression);
494enum mi_gvar_fmt mi_format_str_to_enum(const char *format);
495const char *mi_format_enum_to_str(enum mi_gvar_fmt format);
496char mi_format_enum_to_char(enum mi_gvar_fmt format);
497enum mi_gvar_lang mi_lang_str_to_enum(const char *lang);
498const char *mi_lang_enum_to_str(enum mi_gvar_lang lang);
499int mi_res_changelist(mi_h *h, mi_gvar_chg **changed);
500int mi_res_children(mi_h *h, mi_gvar *v);
501mi_bkpt *mi_res_bkpt(mi_h *h);
502mi_wp *mi_res_wp(mi_h *h);
503char *mi_res_value(mi_h *h);
504mi_stop *mi_res_stop(mi_h *h);
505enum mi_stop_reason mi_reason_str_to_enum(const char *s);
506const char *mi_reason_enum_to_str(enum mi_stop_reason r);
507int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
508 unsigned long *addr);
509mi_asm_insns *mi_get_asm_insns(mi_h *h);
510/* Starting point of the program. */
511void mi_set_main_func(const char *name);
512const char *mi_get_main_func();
513mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many);
514int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l);
515mi_chg_reg *mi_get_list_changed_regs(mi_h *h);
516int mi_get_reg_values(mi_h *h, mi_chg_reg *l);
517mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many);
518int gmi_target_download(mi_h *h);
519
520/* Allocation functions: */
521void *mi_calloc(size_t count, size_t sz);
522void *mi_calloc1(size_t sz);
523char *mi_malloc(size_t sz);
524mi_results *mi_alloc_results(void);
525mi_output *mi_alloc_output(void);
526mi_frames *mi_alloc_frames(void);
527mi_gvar *mi_alloc_gvar(void);
528mi_gvar_chg *mi_alloc_gvar_chg(void);
529mi_bkpt *mi_alloc_bkpt(void);
530mi_wp *mi_alloc_wp(void);
531mi_stop *mi_alloc_stop(void);
532mi_asm_insns *mi_alloc_asm_insns(void);
533mi_asm_insn *mi_alloc_asm_insn(void);
534mi_chg_reg *mi_alloc_chg_reg(void);
535void mi_free_output(mi_output *r);
536void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r);
537void mi_free_frames(mi_frames *f);
538void mi_free_aux_term(mi_aux_term *t);
539void mi_free_results(mi_results *r);
540void mi_free_results_but(mi_results *r, mi_results *no);
541void mi_free_gvar(mi_gvar *v);
542void mi_free_gvar_chg(mi_gvar_chg *p);
543void mi_free_wp(mi_wp *wp);
544void mi_free_stop(mi_stop *s);
545void mi_free_asm_insns(mi_asm_insns *i);
546void mi_free_asm_insn(mi_asm_insn *i);
547void mi_free_charp_list(char **l);
548void mi_free_chg_reg(mi_chg_reg *r);
549
550/* Porgram control: */
551/* Specify the executable and arguments for local debug. */
552int gmi_set_exec(mi_h *h, const char *file, const char *args);
553/* Start running the executable. Remote sessions starts running. */
554int gmi_exec_run(mi_h *h);
555/* Continue the execution after a "stop". */
556int gmi_exec_continue(mi_h *h);
557/* Indicate which terminal will use the target program. For local sessions. */
558int gmi_target_terminal(mi_h *h, const char *tty_name);
559/* Specify what's the local copy that have debug info. For remote sessions. */
560int gmi_file_symbol_file(mi_h *h, const char *file);
561/* Continue until function return, the return value is included in the async
562 response. */
563int gmi_exec_finish(mi_h *h);
564/* Stop the program using SIGINT. */
565int gmi_exec_interrupt(mi_h *h);
566/* Next line of code. */
567int gmi_exec_next(mi_h *h);
568/* Next count lines of code. */
569int gmi_exec_next_cnt(mi_h *h, int count);
570/* Next line of assembler code. */
571int gmi_exec_next_instruction(mi_h *h);
572/* Next line of code. Get inside functions. */
573int gmi_exec_step(mi_h *h);
574/* Next count lines of code. Get inside functions. */
575int gmi_exec_step_cnt(mi_h *h, int count);
576/* Next line of assembler code. Get inside calls. */
577int gmi_exec_step_instruction(mi_h *h);
578/* Execute until location is reached. If file is NULL then is until next line. */
579int gmi_exec_until(mi_h *h, const char *file, int line);
580int gmi_exec_until_addr(mi_h *h, void *addr);
581/* Return to previous frame inmediatly. */
582mi_frames *gmi_exec_return(mi_h *h);
583/* Just kill the program. Please read the notes in prg_control.c. */
584int gmi_exec_kill(mi_h *h);
585
586/* Target manipulation: */
587/* Connect to a remote gdbserver using the specified methode. */
588int gmi_target_select(mi_h *h, const char *type, const char *params);
589/* Attach to an already running process. */
590mi_frames *gmi_target_attach(mi_h *h, pid_t pid);
591/* Detach from an attached process. */
592int gmi_target_detach(mi_h *h);
593
594/* Miscellaneous commands: */
595/* Exit gdb killing the child is it is running. */
596void gmi_gdb_exit(mi_h *h);
597/* Send the version to the console. */
598int gmi_gdb_version(mi_h *h);
599/* Set a gdb variable. */
600int gmi_gdb_set(mi_h *h, const char *var, const char *val);
601/* Get a gdb variable. */
602char *gmi_gdb_show(mi_h *h, const char *var);
603
604/* Breakpoints manipulation: */
605/* Insert a breakpoint at file:line. */
606mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line);
607/* Insert a breakpoint, all available options. */
608mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
609 const char *cond, int count, int thread,
610 const char *where);
611mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
612 int temporary, int hard_assist,
613 const char *cond, int count, int thread);
614/* Remove a breakpoint. */
615int gmi_break_delete(mi_h *h, int number);
616/* Free the memory used for a breakpoint description. */
617void mi_free_bkpt(mi_bkpt *b);
618/* Modify the "ignore" count for a breakpoint. */
619int gmi_break_set_times(mi_h *h, int number, int count);
620/* Associate a condition with the breakpoint. */
621int gmi_break_set_condition(mi_h *h, int number, const char *condition);
622/* Enable or disable a breakpoint. */
623int gmi_break_state(mi_h *h, int number, int enable);
624/* Set a watchpoint. It doesn't work for remote targets! */
625mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp);
626
627/* Data Manipulation. */
628/* Evaluate an expression. Returns a parsed tree. */
629char *gmi_data_evaluate_expression(mi_h *h, const char *expression);
630/* Path for sources. */
631int gmi_dir(mi_h *h, const char *path);
632/* A very limited "data read memory" implementation. */
633int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
634 unsigned char *dest, int *na, int convAddr,
635 unsigned long *addr);
636mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
637 const char *end, int mode);
638mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
639 int lines, int mode);
640mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many);
641int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l);
642mi_chg_reg *gmi_data_list_changed_registers(mi_h *h);
643int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l);
644mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many);
645
646/* Stack manipulation. */
647/* List of frames. Arguments aren't filled. */
648mi_frames *gmi_stack_list_frames(mi_h *h);
649/* List of frames. Indicating a range. */
650mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to);
651/* List arguments. Only level and args filled. */
652mi_frames *gmi_stack_list_arguments(mi_h *h, int show);
653/* List arguments. Indicating a range. Only level and args filled. */
654mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to);
655/* Information about the current frame, including args. */
656mi_frames *gmi_stack_info_frame(mi_h *h);
657/* Stack info depth. error => -1 */
658int gmi_stack_info_depth_get(mi_h *h);
659/* Set stack info depth. error => -1 */
660int gmi_stack_info_depth(mi_h *h, int max_depth);
661/* Change current frame. */
662int gmi_stack_select_frame(mi_h *h, int framenum);
663/* List of local vars. */
664mi_results *gmi_stack_list_locals(mi_h *h, int show);
665
666/* Thread. */
667/* List available thread ids. */
668int gmi_thread_list_ids(mi_h *h, int **list);
669/* Select a thread. */
670mi_frames *gmi_thread_select(mi_h *h, int id);
671/* List available threads. */
672mi_frames *gmi_thread_list_all_threads(mi_h *h);
673
674/* Variable objects. */
675/* Create a variable object. */
676mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp);
677mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp);
678/* Create the variable and also fill the lang and attr fields. */
679mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp);
680/* Delete a variable object. Doesn't free the mi_gvar data. */
681int gmi_var_delete(mi_h *h, mi_gvar *var);
682/* Set the format used to represent the result. */
683int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format);
684/* Fill the format field with info from gdb. */
685int gmi_var_show_format(mi_h *h, mi_gvar *var);
686/* Fill the numchild field with info from gdb. */
687int gmi_var_info_num_children(mi_h *h, mi_gvar *var);
688/* Fill the type field with info from gdb. */
689int gmi_var_info_type(mi_h *h, mi_gvar *var);
690/* Fill the expression and lang fields with info from gdb.
691 Note that lang isn't filled during creation. */
692int gmi_var_info_expression(mi_h *h, mi_gvar *var);
693/* Fill the attr field with info from gdb.
694 Note that attr isn't filled during creation. */
695int gmi_var_show_attributes(mi_h *h, mi_gvar *var);
696/* Update variable. Use NULL for all.
697 Note that *changed can be NULL if none updated. */
698int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed);
699/* Change variable. Fills the value field. */
700int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression);
701/* Get current value for a variable. */
702int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var);
703/* List children. It ONLY returns the first level information. :-( */
704int gmi_var_list_children(mi_h *h, mi_gvar *var);
705
706
707
708
709#if 0 /* keep Emacsens' auto-indent happy */
710{
711#endif
712#ifdef __cplusplus
713}
714#endif
715
716#endif
diff --git a/src/monkey/gdbmi_alloc.c b/src/monkey/gdbmi_alloc.c
deleted file mode 100644
index 0fe6e14de..000000000
--- a/src/monkey/gdbmi_alloc.c
+++ /dev/null
@@ -1,308 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Allocator.
7 Comments:
8 Most alloc/free routines are here. Free routines must accept NULL
9pointers. Alloc functions must set mi_error. @<p>
10
11***************************************************************************/
12
13#include "gdbmi.h"
14
15void *mi_calloc(size_t count, size_t sz)
16{
17 void *res=calloc(count,sz);
18 if (!res)
19 mi_error=MI_OUT_OF_MEMORY;
20 return res;
21}
22
23void *mi_calloc1(size_t sz)
24{
25 return mi_calloc(1,sz);
26}
27
28char *mi_malloc(size_t sz)
29{
30 char *res=malloc(sz);
31 if (!res)
32 mi_error=MI_OUT_OF_MEMORY;
33 return res;
34}
35
36mi_results *mi_alloc_results(void)
37{
38 return (mi_results *)mi_calloc1(sizeof(mi_results));
39}
40
41mi_output *mi_alloc_output(void)
42{
43 return (mi_output *)mi_calloc1(sizeof(mi_output));
44}
45
46mi_frames *mi_alloc_frames(void)
47{
48 return (mi_frames *)mi_calloc1(sizeof(mi_frames));
49}
50
51mi_gvar *mi_alloc_gvar(void)
52{
53 return (mi_gvar *)mi_calloc1(sizeof(mi_gvar));
54}
55
56mi_gvar_chg *mi_alloc_gvar_chg(void)
57{
58 return (mi_gvar_chg *)mi_calloc1(sizeof(mi_gvar_chg));
59}
60
61mi_bkpt *mi_alloc_bkpt(void)
62{
63 mi_bkpt *b=(mi_bkpt *)mi_calloc1(sizeof(mi_bkpt));
64 if (b)
65 {
66 b->thread=-1;
67 b->ignore=-1;
68 }
69 return b;
70}
71
72mi_wp *mi_alloc_wp(void)
73{
74 return (mi_wp *)mi_calloc1(sizeof(mi_wp));
75}
76
77mi_stop *mi_alloc_stop(void)
78{
79 return (mi_stop *)mi_calloc1(sizeof(mi_stop));
80}
81
82mi_asm_insns *mi_alloc_asm_insns(void)
83{
84 return (mi_asm_insns *)mi_calloc1(sizeof(mi_asm_insns));
85}
86
87mi_asm_insn *mi_alloc_asm_insn(void)
88{
89 return (mi_asm_insn *)mi_calloc1(sizeof(mi_asm_insn));
90}
91
92mi_chg_reg *mi_alloc_chg_reg(void)
93{
94 return (mi_chg_reg *)mi_calloc1(sizeof(mi_chg_reg));
95}
96
97/*****************************************************************************
98 Free functions
99*****************************************************************************/
100
101void mi_free_frames(mi_frames *f)
102{
103 mi_frames *aux;
104
105 while (f)
106 {
107 free(f->func);
108 free(f->file);
109 free(f->from);
110 mi_free_results(f->args);
111 aux=f->next;
112 free(f);
113 f=aux;
114 }
115}
116
117void mi_free_bkpt(mi_bkpt *b)
118{
119 mi_bkpt *aux;
120
121 while (b)
122 {
123 free(b->func);
124 free(b->file);
125 free(b->file_abs);
126 free(b->cond);
127 aux=b->next;
128 free(b);
129 b=aux;
130 }
131}
132
133void mi_free_gvar(mi_gvar *v)
134{
135 mi_gvar *aux;
136
137 while (v)
138 {
139 free(v->name);
140 free(v->type);
141 free(v->exp);
142 free(v->value);
143 if (v->numchild && v->child)
144 mi_free_gvar(v->child);
145 aux=v->next;
146 free(v);
147 v=aux;
148 }
149}
150
151void mi_free_gvar_chg(mi_gvar_chg *p)
152{
153 mi_gvar_chg *aux;
154
155 while (p)
156 {
157 free(p->name);
158 free(p->new_type);
159 aux=p->next;
160 free(p);
161 p=aux;
162 }
163}
164
165void mi_free_results_but(mi_results *r, mi_results *no)
166{
167 mi_results *aux;
168
169 while (r)
170 {
171 if (r==no)
172 {
173 aux=r->next;
174 r->next=NULL;
175 r=aux;
176 }
177 else
178 {
179 free(r->var);
180 switch (r->type)
181 {
182 case t_const:
183 free(r->v.cstr);
184 break;
185 case t_tuple:
186 case t_list:
187 mi_free_results_but(r->v.rs,no);
188 break;
189 }
190 aux=r->next;
191 free(r);
192 r=aux;
193 }
194 }
195}
196
197void mi_free_results(mi_results *r)
198{
199 mi_free_results_but(r,NULL);
200}
201
202void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r)
203{
204 mi_output *aux;
205
206 while (r)
207 {
208 if (r==no)
209 {
210 aux=r->next;
211 r->next=NULL;
212 r=aux;
213 }
214 else
215 {
216 if (r->c)
217 mi_free_results_but(r->c,no_r);
218 aux=r->next;
219 free(r);
220 r=aux;
221 }
222 }
223}
224
225void mi_free_output(mi_output *r)
226{
227 mi_free_output_but(r,NULL,NULL);
228}
229
230void mi_free_stop(mi_stop *s)
231{
232 if (!s)
233 return;
234 mi_free_frames(s->frame);
235 mi_free_wp(s->wp);
236 free(s->wp_old);
237 free(s->wp_val);
238 free(s->gdb_result_var);
239 free(s->return_value);
240 free(s->signal_name);
241 free(s->signal_meaning);
242 free(s);
243}
244
245void mi_free_wp(mi_wp *wp)
246{
247 mi_wp *aux;
248 while (wp)
249 {
250 free(wp->exp);
251 aux=wp->next;
252 free(wp);
253 wp=aux;
254 }
255}
256
257void mi_free_asm_insns(mi_asm_insns *i)
258{
259 mi_asm_insns *aux;
260
261 while (i)
262 {
263 free(i->file);
264 mi_free_asm_insn(i->ins);
265 aux=i->next;
266 free(i);
267 i=aux;
268 }
269}
270
271void mi_free_asm_insn(mi_asm_insn *i)
272{
273 mi_asm_insn *aux;
274
275 while (i)
276 {
277 free(i->func);
278 free(i->inst);
279 aux=i->next;
280 free(i);
281 i=aux;
282 }
283}
284
285/*void mi_free_charp_list(char **l)
286{
287 char **c=l;
288 while (c)
289 {
290 free(*c);
291 c++;
292 }
293 free(l);
294}*/
295
296void mi_free_chg_reg(mi_chg_reg *r)
297{
298 mi_chg_reg *aux;
299 while (r)
300 {
301 free(r->val);
302 free(r->name);
303 aux=r->next;
304 free(r);
305 r=aux;
306 }
307}
308
diff --git a/src/monkey/gdbmi_breakpoint.c b/src/monkey/gdbmi_breakpoint.c
deleted file mode 100644
index f91cc3ea5..000000000
--- a/src/monkey/gdbmi_breakpoint.c
+++ /dev/null
@@ -1,265 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Breakpoint table commands.
7 Comments:
8 GDB/MI commands for the "Breakpoint Table Commands" section.
9 @<p>
10@<pre>
11gdb command: Implemented?
12
13-break-after Yes
14-break-condition Yes
15-break-delete Yes
16-break-disable Yes
17-break-enable Yes
18-break-info N.A. (info break NUMBER) (*)
19-break-insert Yes
20-break-list No (*)
21-break-watch Yes
22@</pre>
23
24(*) I think the program should keep track of the breakpoints, so it will
25be implemented when I have more time. @<p>
26
27***************************************************************************/
28
29#include "gdbmi.h"
30
31/* Low level versions. */
32
33void mi_break_insert_fl(mi_h *h, const char *file, int line)
34{
35 mi_send(h,"-break-insert %s:%d\n",file,line);
36}
37
38void mi_break_insert(mi_h *h, int temporary, int hard_assist,
39 const char *cond, int count, int thread,
40 const char *where)
41{
42 char s_count[32];
43 char s_thread[32];
44
45 if (count>=0)
46 snprintf(s_count,32,"%d",count);
47 if (thread>=0)
48 snprintf(s_thread,32,"%d",thread);
49 if (cond)
50 // Conditions may contain spaces, in fact, if they don't gdb will add
51 // them after parsing. Enclosing the expression with "" solves the
52 // problem.
53 mi_send(h,"-break-insert %s %s -c \"%s\" %s %s %s %s %s\n",
54 temporary ? "-t" : "",
55 hard_assist ? "-h" : "",
56 cond,
57 count>=0 ? "-i" : "", count>=0 ? s_count : "",
58 thread>=0 ? "-p" : "", thread>=0 ? s_thread : "",
59 where);
60 else
61 mi_send(h,"-break-insert %s %s %s %s %s %s %s\n",
62 temporary ? "-t" : "",
63 hard_assist ? "-h" : "",
64 count>=0 ? "-i" : "", count>=0 ? s_count : "",
65 thread>=0 ? "-p" : "", thread>=0 ? s_thread : "",
66 where);
67}
68
69void mi_break_insert_flf(mi_h *h, const char *file, int line, int temporary,
70 int hard_assist, const char *cond, int count,
71 int thread)
72{
73 char s_count[32];
74 char s_thread[32];
75
76 if (count>=0)
77 snprintf(s_count,32,"%d",count);
78 if (thread>=0)
79 snprintf(s_thread,32,"%d",thread);
80 mi_send(h,"-break-insert %s %s %s %s %s %s %s %s %s:%d\n",
81 temporary ? "-t" : "",
82 hard_assist ? "-h" : "",
83 cond ? "-c" : "", cond ? cond : "",
84 count>=0 ? "-i" : "", count>=0 ? s_count : "",
85 thread>=0 ? "-p" : "", thread>=0 ? s_thread : "",
86 file,line);
87}
88
89void mi_break_delete(mi_h *h, int number)
90{
91 mi_send(h,"-break-delete %d\n",number);
92}
93
94void mi_break_after(mi_h *h, int number, int count)
95{
96 mi_send(h,"-break-after %d %d\n",number,count);
97}
98
99void mi_break_condition(mi_h *h, int number, const char *condition)
100{
101 mi_send(h,"-break-condition %d %s\n",number,condition);
102}
103
104void mi_break_enable(mi_h *h, int number)
105{
106 mi_send(h,"-break-enable %d\n",number);
107}
108
109void mi_break_disable(mi_h *h, int number)
110{
111 mi_send(h,"-break-disable %d\n",number);
112}
113
114void mi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp)
115{
116 if (mode==wm_write)
117 mi_send(h,"-break-watch \"%s\"\n",exp);
118 else
119 mi_send(h,"-break-watch -%c \"%s\"\n",mode==wm_rw ? 'a' : 'r',exp);
120}
121
122/* High level versions. */
123
124/**[txh]********************************************************************
125
126 Description:
127 Insert a breakpoint at file:line.
128
129 Command: -break-insert file:line
130 Return: A new mi_bkpt structure with info about the breakpoint. NULL on
131error.
132
133***************************************************************************/
134
135mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line)
136{
137 mi_break_insert_fl(h,file,line);
138 return mi_res_bkpt(h);
139}
140
141/**[txh]********************************************************************
142
143 Description:
144 Insert a breakpoint, all available options.
145
146 Command: -break-insert
147 Return: A new mi_bkpt structure with info about the breakpoint. NULL on
148error.
149
150***************************************************************************/
151
152mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
153 const char *cond, int count, int thread,
154 const char *where)
155{
156 mi_break_insert(h,temporary,hard_assist,cond,count,thread,where);
157 return mi_res_bkpt(h);
158}
159
160/**[txh]********************************************************************
161
162 Description:
163 Insert a breakpoint, all available options.
164
165 Command: -break-insert [ops] file:line
166 Return: A new mi_bkpt structure with info about the breakpoint. NULL on
167error.
168
169***************************************************************************/
170
171mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
172 int temporary, int hard_assist,
173 const char *cond, int count, int thread)
174{
175 mi_break_insert_flf(h,file,line,temporary,hard_assist,cond,count,thread);
176 return mi_res_bkpt(h);
177}
178
179/**[txh]********************************************************************
180
181 Description:
182 Remove a breakpoint.
183
184 Command: -break-delete
185 Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
186console.
187
188***************************************************************************/
189
190int gmi_break_delete(mi_h *h, int number)
191{
192 mi_break_delete(h,number);
193 return mi_res_simple_done(h);
194}
195
196/**[txh]********************************************************************
197
198 Description:
199 Modify the "ignore" count for a breakpoint.
200
201 Command: -break-after
202 Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
203console.
204
205***************************************************************************/
206
207int gmi_break_set_times(mi_h *h, int number, int count)
208{
209 mi_break_after(h,number,count);
210 return mi_res_simple_done(h);
211}
212
213/**[txh]********************************************************************
214
215 Description:
216 Associate a condition with the breakpoint.
217
218 Command: -break-condition
219 Return: !=0 OK
220
221***************************************************************************/
222
223int gmi_break_set_condition(mi_h *h, int number, const char *condition)
224{
225 mi_break_condition(h,number,condition);
226 return mi_res_simple_done(h);
227}
228
229/**[txh]********************************************************************
230
231 Description:
232 Enable or disable a breakpoint.
233
234 Command: -break-enable + -break-disable
235 Return: !=0 OK. Note that gdb always says OK, but errors can be sent to the
236console.
237
238***************************************************************************/
239
240int gmi_break_state(mi_h *h, int number, int enable)
241{
242 if (enable)
243 mi_break_enable(h,number);
244 else
245 mi_break_disable(h,number);
246 return mi_res_simple_done(h);
247}
248
249/**[txh]********************************************************************
250
251 Description:
252 Set a watchpoint. It doesn't work for remote targets!
253
254 Command: -break-watch
255 Return: A new mi_wp structure with info about the watchpoint. NULL on
256error.
257
258***************************************************************************/
259
260mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp)
261{
262 mi_break_watch(h,mode,exp);
263 return mi_res_wp(h);
264}
265
diff --git a/src/monkey/gdbmi_connect.c b/src/monkey/gdbmi_connect.c
deleted file mode 100644
index 7ccae081a..000000000
--- a/src/monkey/gdbmi_connect.c
+++ /dev/null
@@ -1,885 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2009 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Connect.
7 Comments:
8 This module handles the dialog with gdb, including starting and stopping
9gdb.
10 @<p>
11
12GDB Bug workaround for "file -readnow": I tried to workaround a bug using
13it but looks like this option also have bugs!!!! so I have to use the
14command line option --readnow.
15It also have a bug!!!! when the binary is changed and gdb must reload it
16this option is ignored. So it looks like we have no solution but 3 gdb bugs
17in a row.
18
19***************************************************************************/
20
21#include "platform.h"
22#include <sys/types.h>
23#include <unistd.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <sys/wait.h>
27#include <fcntl.h>
28#include <string.h>
29#include <stdarg.h>
30#include <limits.h>
31#include <errno.h>
32#include <signal.h>
33#include <sys/stat.h>
34#include <sys/time.h>
35
36#include "gdbmi.h"
37#ifndef _GNU_SOURCE
38#define _GNU_SOURCE
39#endif
40
41#ifndef TEMP_FAILURE_RETRY
42 #define TEMP_FAILURE_RETRY(a) (a)
43#endif
44
45int mi_error=MI_OK;
46char *mi_error_from_gdb=NULL;
47static char *gdb_exe=NULL;
48static char *xterm_exe=NULL;
49static char *gdb_start=NULL;
50static char *gdb_conn=NULL;
51static char *main_func=NULL;
52static char disable_psym_search_workaround=0;
53
54mi_h *mi_alloc_h()
55{
56 mi_h *h=(mi_h *)calloc(1,sizeof(mi_h));
57 if (!h)
58 {
59 mi_error=MI_OUT_OF_MEMORY;
60 return NULL;
61 }
62 h->to_gdb[0]=h->to_gdb[1]=h->from_gdb[0]=h->from_gdb[1]=-1;
63 h->pid=-1;
64 return h;
65}
66
67int mi_check_running_pid(pid_t pid)
68{
69 int status;
70
71 if (pid<=0)
72 return 0;
73 /* If waitpid returns the number of our child means it communicated
74 to as a termination status. */
75 if (waitpid(pid,&status,WNOHANG)==pid)
76 {
77 pid=0;
78 return 0;
79 }
80 return 1;
81}
82
83int mi_check_running(mi_h *h)
84{
85 return !h->died && mi_check_running_pid(h->pid);
86}
87
88void mi_kill_child(pid_t pid)
89{
90 kill(pid,SIGTERM);
91 usleep(100000);
92 if (mi_check_running_pid(pid))
93 {
94 int status;
95 kill(pid,SIGKILL);
96 waitpid(pid,&status,0);
97 }
98}
99
100void mi_free_h(mi_h **handle)
101{
102 mi_h *h=*handle;
103 if (h->to_gdb[0]>=0)
104 close(h->to_gdb[0]);
105 if (h->to)
106 fclose(h->to);
107 else if (h->to_gdb[1]>=0)
108 close(h->to_gdb[1]);
109 if (h->from)
110 fclose(h->from);
111 else if (h->from_gdb[0]>=0)
112 close(h->from_gdb[0]);
113 if (h->from_gdb[1]>=0)
114 close(h->from_gdb[1]);
115 if (mi_check_running(h))
116 {/* GDB is running! */
117 mi_kill_child(h->pid);
118 }
119 if (h->line)
120 free(h->line);
121 mi_free_output(h->po);
122 free(h->catched_console);
123 free(h);
124 *handle=NULL;
125}
126
127void mi_set_nonblk(int h)
128{
129 int flf;
130 flf=fcntl(h,F_GETFL,0);
131 flf=flf | O_NONBLOCK;
132 fcntl(h,F_SETFL,flf);
133}
134
135int mi_getline(mi_h *h)
136{
137 char c;
138
139 while (read(h->from_gdb[0],&c,1)==1)
140 {
141 if (h->lread>=h->llen)
142 {
143 h->llen=h->lread+128;
144 h->line=(char *)realloc(h->line,h->llen);
145 if (!h->line)
146 {
147 h->llen=0;
148 h->lread=0;
149 return -1;
150 }
151 }
152 if (c=='\n')
153 {
154 int ret=h->lread;
155 h->line[ret]=0;
156 h->lread=0;
157 return ret;
158 }
159 h->line[h->lread]=c;
160 h->lread++;
161 }
162 return 0;
163}
164
165char *get_cstr(mi_output *o)
166{
167 if (!o->c || o->c->type!=t_const)
168 return NULL;
169 return o->c->v.cstr;
170}
171
172int mi_get_response(mi_h *h)
173{
174 int l=mi_getline(h);
175 if (!l)
176 return 0;
177
178 if (h->from_gdb_echo)
179 h->from_gdb_echo(h->line,h->from_gdb_echo_data);
180 if (strncmp(h->line,"(gdb)",5)==0)
181 {/* End of response. */
182 return 1;
183 }
184 else
185 {/* Add to the response. */
186 mi_output *o;
187 int add=1, is_exit=0;
188 o=mi_parse_gdb_output(h->line);
189
190 if (!o)
191 return 0;
192 /* Tunneled streams callbacks. */
193 if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_STREAM)
194 {
195 char *aux;
196 add=0;
197 switch (o->sstype)
198 {
199 case MI_SST_CONSOLE:
200 aux=get_cstr(o);
201 if (h->console)
202 h->console(aux,h->console_data);
203 if (h->catch_console && aux)
204 {
205 h->catch_console--;
206 if (!h->catch_console)
207 {
208 free(h->catched_console);
209 h->catched_console=strdup(aux);
210 }
211 }
212 break;
213 case MI_SST_TARGET:
214 /* This one seems to be useless. */
215 if (h->target)
216 h->target(get_cstr(o),h->target_data);
217 break;
218 case MI_SST_LOG:
219 if (h->log)
220 h->log(get_cstr(o),h->log_data);
221 break;
222 }
223 }
224 else if (o->type==MI_T_OUT_OF_BAND && o->stype==MI_ST_ASYNC)
225 {
226 if (h->async)
227 h->async(o,h->async_data);
228 }
229 else if (o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_ERROR)
230 {/* Error from gdb, record it. */
231 mi_error=MI_FROM_GDB;
232 free(mi_error_from_gdb);
233 mi_error_from_gdb=NULL;
234 if (o->c && strcmp(o->c->var,"msg")==0 && o->c->type==t_const)
235 mi_error_from_gdb=strdup(o->c->v.cstr);
236 }
237 is_exit=(o->type==MI_T_RESULT_RECORD && o->tclass==MI_CL_EXIT);
238 /* Add to the list of responses. */
239 if (add)
240 {
241 if (h->last)
242 h->last->next=o;
243 else
244 h->po=o;
245 h->last=o;
246 }
247 else
248 mi_free_output(o);
249 /* Exit RR means gdb exited, we won't get a new prompt ;-) */
250 if (is_exit)
251 return 1;
252 }
253
254 return 0;
255}
256
257mi_output *mi_retire_response(mi_h *h)
258{
259 mi_output *ret=h->po;
260 h->po=h->last=NULL;
261 return ret;
262}
263
264mi_output *mi_get_response_blk(mi_h *h)
265{
266 int r;
267 /* Sometimes gdb dies. */
268 if (!mi_check_running(h))
269 {
270 h->died=1;
271 mi_error=MI_GDB_DIED;
272 return NULL;
273 }
274 do
275 {
276 /*
277 That's a must. If we just keep trying to read and failing things
278 become really sloooowwww. Instead we try and if it fails we wait
279 until something is available.
280 TODO: Implement something with the time out, a callback to ask the
281 application is we have to wait or not could be a good thing.
282 */
283 fd_set set;
284 struct timeval timeout;
285 int ret;
286
287 r=mi_get_response(h);
288 if (r)
289 return mi_retire_response(h);
290
291 FD_ZERO(&set);
292 FD_SET(h->from_gdb[0],&set);
293 timeout.tv_sec=h->time_out;
294 timeout.tv_usec=0;
295 ret=TEMP_FAILURE_RETRY(select(FD_SETSIZE,&set,NULL,NULL,&timeout));
296 if (!ret)
297 {
298 if (!mi_check_running(h))
299 {
300 h->died=1;
301 mi_error=MI_GDB_DIED;
302 return NULL;
303 }
304 if (h->time_out_cb)
305 ret=h->time_out_cb(h->time_out_cb_data);
306 if (!ret)
307 {
308 mi_error=MI_GDB_TIME_OUT;
309 return NULL;
310 }
311 }
312 }
313 while (!r);
314
315 return NULL;
316}
317
318void mi_send_commands(mi_h *h, const char *file)
319{
320 FILE *f;
321 char b[PATH_MAX];
322
323 //printf("File: %s\n",file);
324 if (!file)
325 return;
326 f=fopen(file,"rt");
327 if (!f)
328 return;
329 while (!feof(f))
330 {
331 if (fgets(b,PATH_MAX,f))
332 {
333 //printf("Send: %s\n",b);
334 mi_send (h, "%s", b);
335 mi_res_simple_done(h);
336 }
337 }
338 fclose(f);
339}
340
341void mi_send_target_commands(mi_h *h)
342{
343 mi_send_commands(h,gdb_conn);
344}
345
346/**[txh]********************************************************************
347
348 Description:
349 Connect to a local copy of gdb. Note that the mi_h structure is something
350similar to a "FILE *" for stdio.
351
352 Return: A new mi_h structure or NULL on error.
353
354***************************************************************************/
355
356mi_h *mi_connect_local()
357{
358 mi_h *h;
359 const char *gdb=mi_get_gdb_exe();
360
361 /* Start without error. */
362 mi_error=MI_OK;
363 /* Verify we have a GDB binary. */
364 if (access(gdb,X_OK))
365 {
366 mi_error=MI_MISSING_GDB;
367 return NULL;
368 }
369 /* Alloc the handle structure. */
370 h=mi_alloc_h();
371 if (!h)
372 return h;
373 h->time_out=MI_DEFAULT_TIME_OUT;
374 /* Create the pipes to connect with the child. */
375 if (pipe(h->to_gdb) || pipe(h->from_gdb))
376 {
377 mi_error=MI_PIPE_CREATE;
378 mi_free_h(&h);
379 return NULL;
380 }
381 mi_set_nonblk(h->to_gdb[1]);
382 mi_set_nonblk(h->from_gdb[0]);
383 /* Associate streams to the file handles. */
384 h->to=fdopen(h->to_gdb[1],"w");
385 h->from=fdopen(h->from_gdb[0],"r");
386 if (!h->to || !h->from)
387 {
388 mi_error=MI_PIPE_CREATE;
389 mi_free_h(&h);
390 return NULL;
391 }
392 /* Create the child. */
393 h->pid=fork();
394 if (h->pid==0)
395 {/* We are the child. */
396 char *argv[5];
397 /* Connect stdin/out to the pipes. */
398 dup2(h->to_gdb[0],STDIN_FILENO);
399 dup2(h->from_gdb[1],STDOUT_FILENO);
400 /* Pass the control to gdb. */
401 argv[0]=(char *)gdb; /* Is that OK? */
402 argv[1]="--interpreter=mi";
403 argv[2]="--quiet";
404 argv[3]=disable_psym_search_workaround ? 0 : "--readnow";
405 argv[4]=0;
406 execvp(argv[0],argv);
407 /* We get here only if exec failed. */
408 _exit(127);
409 }
410 /* We are the parent. */
411 if (h->pid==-1)
412 {/* Fork failed. */
413 mi_error=MI_FORK;
414 mi_free_h(&h);
415 return NULL;
416 }
417 if (!mi_check_running(h))
418 {
419 mi_error=MI_DEBUGGER_RUN;
420 mi_free_h(&h);
421 return NULL;
422 }
423 /* Wait for the prompt. */
424 mi_get_response_blk(h);
425 /* Send the start-up commands */
426 mi_send_commands(h,gdb_start);
427
428 return h;
429}
430
431/**[txh]********************************************************************
432
433 Description:
434 Close connection. You should ask gdb to quit first gmi_gdb_exit.
435
436***************************************************************************/
437
438void mi_disconnect(mi_h *h)
439{
440 mi_free_h(&h);
441 free(mi_error_from_gdb);
442 mi_error_from_gdb=NULL;
443}
444
445void mi_set_console_cb(mi_h *h, stream_cb cb, void *data)
446{
447 h->console=cb;
448 h->console_data=data;
449}
450
451void mi_set_target_cb(mi_h *h, stream_cb cb, void *data)
452{
453 h->target=cb;
454 h->target_data=data;
455}
456
457void mi_set_log_cb(mi_h *h, stream_cb cb, void *data)
458{
459 h->log=cb;
460 h->log_data=data;
461}
462
463stream_cb mi_get_console_cb(mi_h *h, void **data)
464{
465 if (data)
466 *data=h->console_data;
467 return h->console;
468}
469
470stream_cb mi_get_target_cb(mi_h *h, void **data)
471{
472 if (data)
473 *data=h->target_data;
474 return h->target;
475}
476
477stream_cb mi_get_log_cb(mi_h *h, void **data)
478{
479 if (data)
480 *data=h->log_data;
481 return h->log;
482}
483
484void mi_set_async_cb(mi_h *h, async_cb cb, void *data)
485{
486 h->async=cb;
487 h->async_data=data;
488}
489
490async_cb mi_get_async_cb(mi_h *h, void **data)
491{
492 if (data)
493 *data=h->async_data;
494 return h->async;
495}
496
497void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data)
498{
499 h->to_gdb_echo=cb;
500 h->to_gdb_echo_data=data;
501}
502
503void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data)
504{
505 h->from_gdb_echo=cb;
506 h->from_gdb_echo_data=data;
507}
508
509stream_cb mi_get_to_gdb_cb(mi_h *h, void **data)
510{
511 if (data)
512 *data=h->to_gdb_echo_data;
513 return h->to_gdb_echo;
514}
515
516stream_cb mi_get_from_gdb_cb(mi_h *h, void **data)
517{
518 if (data)
519 *data=h->from_gdb_echo_data;
520 return h->from_gdb_echo;
521}
522
523void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data)
524{
525 h->time_out_cb=cb;
526 h->time_out_cb_data=data;
527}
528
529tm_cb mi_get_time_out_cb(mi_h *h, void **data)
530{
531 if (data)
532 *data=h->time_out_cb_data;
533 return h->time_out_cb;
534}
535
536void mi_set_time_out(mi_h *h, int to)
537{
538 h->time_out=to;
539}
540
541int mi_get_time_out(mi_h *h)
542{
543 return h->time_out;
544}
545
546int mi_send(mi_h *h, const char *format, ...)
547{
548 int ret;
549 char *str;
550 va_list argptr;
551
552 if (h->died)
553 return 0;
554
555 va_start(argptr,format);
556 ret=vasprintf(&str,format,argptr);
557 va_end(argptr);
558 if (-1 != ret)
559 {
560 fputs(str,h->to);
561 fflush(h->to);
562 if (h->to_gdb_echo)
563 h->to_gdb_echo(str,h->to_gdb_echo_data);
564 free(str);
565 }
566 else
567 {
568 abort ();
569 }
570
571 return ret;
572}
573
574void mi_clean_up_globals()
575{
576 free(gdb_exe);
577 gdb_exe=NULL;
578 free(xterm_exe);
579 xterm_exe=NULL;
580 free(gdb_start);
581 gdb_start=NULL;
582 free(gdb_conn);
583 gdb_conn=NULL;
584 free(main_func);
585 main_func=NULL;
586}
587
588void mi_register_exit()
589{
590 static int registered=0;
591 if (!registered)
592 {
593 registered=1;
594 atexit(mi_clean_up_globals);
595 }
596}
597
598void mi_set_gdb_exe(const char *name)
599{
600 free(gdb_exe);
601 gdb_exe=name ? strdup(name) : NULL;
602 mi_register_exit();
603}
604
605void mi_set_gdb_start(const char *name)
606{
607 free(gdb_start);
608 gdb_start=name ? strdup(name) : NULL;
609 mi_register_exit();
610}
611
612void mi_set_gdb_conn(const char *name)
613{
614 free(gdb_conn);
615 gdb_conn=name ? strdup(name) : NULL;
616 mi_register_exit();
617}
618
619static
620char *mi_search_in_path(const char *file)
621{
622 char *path, *pt, *r;
623 char test[PATH_MAX];
624 struct stat st;
625
626 path=getenv("PATH");
627 if (!path)
628 return NULL;
629 pt=strdup(path);
630 r=strtok(pt,PATH_SEPARATOR_STR);
631 while (r)
632 {
633 strcpy(test,r);
634 strcat(test,"/");
635 strcat(test,file);
636 if (stat(test,&st)==0 && S_ISREG(st.st_mode))
637 {
638 free(pt);
639 return strdup(test);
640 }
641 r=strtok(NULL,PATH_SEPARATOR_STR);
642 }
643 free(pt);
644 return NULL;
645}
646
647const char *mi_get_gdb_exe()
648{
649 if (!gdb_exe)
650 {/* Look for gdb in path */
651 gdb_exe=mi_search_in_path("gdb");
652 if (!gdb_exe)
653 return "/usr/bin/gdb";
654 }
655 return gdb_exe;
656}
657
658const char *mi_get_gdb_start()
659{
660 return gdb_start;
661}
662
663const char *mi_get_gdb_conn()
664{
665 return gdb_conn;
666}
667
668void mi_set_xterm_exe(const char *name)
669{
670 free(xterm_exe);
671 xterm_exe=name ? strdup(name) : NULL;
672 mi_register_exit();
673}
674
675const char *mi_get_xterm_exe()
676{
677 if (!xterm_exe)
678 {/* Look for xterm in path */
679 xterm_exe=mi_search_in_path("xterm");
680 if (!xterm_exe)
681 return "/usr/bin/X11/xterm";
682 }
683 return xterm_exe;
684}
685
686void mi_set_main_func(const char *name)
687{
688 free(main_func);
689 main_func=name ? strdup(name) : NULL;
690 mi_register_exit();
691}
692
693const char *mi_get_main_func()
694{
695 if (main_func)
696 return main_func;
697 return "main";
698}
699
700/**[txh]********************************************************************
701
702 Description:
703 Opens a new xterm to be used by the child process to debug.
704
705 Return: A new mi_aux_term structure, you can use gmi_end_aux_term to
706release it.
707
708***************************************************************************/
709
710mi_aux_term *gmi_start_xterm()
711{
712 char nsh[14]="/tmp/shXXXXXX";
713 char ntt[14]="/tmp/ttXXXXXX";
714 const char *xterm;
715 struct stat st;
716 int hsh, htt=-1;
717 mi_aux_term *res=NULL;
718 FILE *f;
719 pid_t pid;
720 char buf[PATH_MAX];
721
722 /* Verify we have an X terminal. */
723 xterm=mi_get_xterm_exe();
724 if (access(xterm,X_OK))
725 {
726 mi_error=MI_MISSING_XTERM;
727 return NULL;
728 }
729
730 /* Create 2 temporals. */
731 hsh=mkstemp(nsh);
732 if (hsh==-1)
733 {
734 mi_error=MI_CREATE_TEMPORAL;
735 return NULL;
736 }
737 htt=mkstemp(ntt);
738 if (htt==-1)
739 {
740 close(hsh);
741 unlink(nsh);
742 mi_error=MI_CREATE_TEMPORAL;
743 return NULL;
744 }
745 close(htt);
746 /* Create the script. */
747 f=fdopen(hsh,"w");
748 if (!f)
749 {
750 close(hsh);
751 unlink(nsh);
752 unlink(ntt);
753 mi_error=MI_CREATE_TEMPORAL;
754 return NULL;
755 }
756 fprintf(f,"#!/bin/sh\n");
757 fprintf(f,"tty > %s\n",ntt);
758 fprintf(f,"rm %s\n",nsh);
759 fprintf(f,"sleep 365d\n");
760 fclose(f);
761 /* Spawn xterm. */
762 /* Create the child. */
763 pid=fork();
764 if (pid==0)
765 {/* We are the child. */
766 char *argv[5];
767 /* Pass the control to gdb. */
768 argv[0]=(char *)mi_get_xterm_exe(); /* Is that ok? */
769 argv[1]="-e";
770 argv[2]="/bin/sh";
771 argv[3]=nsh;
772 argv[4]=0;
773 execvp(argv[0],argv);
774 /* We get here only if exec failed. */
775 unlink(nsh);
776 unlink(ntt);
777 _exit(127);
778 }
779 /* We are the parent. */
780 if (pid==-1)
781 {/* Fork failed. */
782 unlink(nsh);
783 unlink(ntt);
784 mi_error=MI_FORK;
785 return NULL;
786 }
787 /* Wait until the shell is deleted. */
788 while (stat(nsh,&st)==0)
789 usleep(1000);
790 /* Try to read the tty name. */
791 f=fopen(ntt,"rt");
792 if (f)
793 {
794 if (fgets(buf,PATH_MAX,f))
795 {
796 char *s; /* Strip the \n. */
797 for (s=buf; *s && *s!='\n'; s++);
798 *s=0;
799 res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
800 if (res)
801 {
802 res->pid=pid;
803 res->tty=strdup(buf);
804 }
805 }
806 fclose(f);
807 }
808 unlink(ntt);
809 return res;
810}
811
812void mi_free_aux_term(mi_aux_term *t)
813{
814 if (!t)
815 return;
816 free(t->tty);
817 free(t);
818}
819
820/**[txh]********************************************************************
821
822 Description:
823 Closes the auxiliar terminal and releases the allocated memory.
824
825***************************************************************************/
826
827void gmi_end_aux_term(mi_aux_term *t)
828{
829 if (!t)
830 return;
831 if (t->pid!=-1 && mi_check_running_pid(t->pid))
832 mi_kill_child(t->pid);
833 mi_free_aux_term(t);
834}
835
836/**[txh]********************************************************************
837
838 Description:
839 Forces the MI version. Currently the library can't detect it so you must
840force it manually. GDB 5.x implemented MI v1 and 6.x v2.
841
842***************************************************************************/
843
844void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
845 unsigned vMinor)
846{
847 h->version=MI_VERSION2U(vMajor,vMiddle,vMinor);
848}
849
850/**[txh]********************************************************************
851
852 Description:
853 Dis/Enables the workaround for a bug in gdb.
854
855***************************************************************************/
856
857void mi_set_workaround(unsigned wa, int enable)
858{
859 switch (wa)
860 {
861 case MI_PSYM_SEARCH:
862 disable_psym_search_workaround=enable ? 0 : 1;
863 break;
864 }
865}
866
867/**[txh]********************************************************************
868
869 Description:
870 Finds if the workaround for a bug in gdb is enabled.
871
872 Return: !=0 if enabled.
873
874***************************************************************************/
875
876int mi_get_workaround(unsigned wa)
877{
878 switch (wa)
879 {
880 case MI_PSYM_SEARCH:
881 return disable_psym_search_workaround==0;
882 }
883 return 0;
884}
885
diff --git a/src/monkey/gdbmi_data_man.c b/src/monkey/gdbmi_data_man.c
deleted file mode 100644
index 06e137720..000000000
--- a/src/monkey/gdbmi_data_man.c
+++ /dev/null
@@ -1,243 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Data manipulation.
7 Comments:
8 GDB/MI commands for the "Data manipulation" section.
9
10 @<p>
11
12@<pre>
13gdb command: Implemented?
14
15-data-disassemble Yes
16-data-evaluate-expression Yes
17-data-list-changed-registers No
18-data-list-register-names Yes
19-data-list-register-values No
20-data-read-memory No
21-display-delete N.A. (delete display)
22-display-disable N.A. (disable display)
23-display-enable N.A. (enable display)
24-display-insert N.A. (display)
25-display-list N.A. (info display)
26-environment-cd No
27-environment-directory Yes, MI v1 implementation
28-environment-path No
29@</pre>
30
31Notes: @<p>
32
331) -display* aren't implemented. You can use CLI command display, but the
34results are sent to the console. So it looks like the best is to manually
35use -data-evaluate-expression to emulate it. @<p>
36
372) GDB bug mi/1770: Affects gdb<=6.2, when you ask for the names of the
38registers you get it plus the name of the "pseudo-registers", but if you
39try to get the value of a pseudo-register you get an error saying the
40register number is invalid. I reported to gdb-patches@sources.redhat.com
41on 2004/08/25 and as I didn't get any answer I filled a bug report on
422004/09/02. The patch to fix this annoying bug is:
43
44Index: gdb/mi/mi-main.c
45===================================================================
46RCS file: /cvs/src/src/gdb/mi/mi-main.c,v
47retrieving revision 1.64
48diff -u -r1.64 mi-main.c
49--- gdb/mi/mi-main.c 3 Aug 2004 00:57:27 -0000 1.64
50+++ gdb/mi/mi-main.c 25 Aug 2004 14:12:50 -0000
51@@ -423,7 +423,7 @@
52 case, some entries of REGISTER_NAME will change depending upon
53 the particular processor being debugged.
54
55- numregs = NUM_REGS;
56+ numregs = NUM_REGS + NUM_PSEUDO_REGS;
57
58 if (argc == 0)
59 {
60----
61
62Note I had to remove an end of comment in the patch to include it here.
63This bug forced me to create another set of functions. The only way is to
64first get the values and then the names.
65Fixed by Changelog entry:
66
672004-09-12 Salvador E. Tropea <set@users.sf.net>
68 Andrew Cagney <cagney@gnu.org>
69
70 * mi/mi-main.c (mi_cmd_data_list_changed_registers)
71 (mi_cmd_data_list_register_values)
72 (mi_cmd_data_write_register_values): Include the PSEUDO_REGS in
73 the register number computation.
74
75***************************************************************************/
76
77#include "gdbmi.h"
78
79/* Low level versions. */
80
81void mi_data_evaluate_expression(mi_h *h, const char *expression)
82{
83 mi_send(h,"-data-evaluate-expression \"%s\"\n",expression);
84}
85
86void mi_dir(mi_h *h, const char *path)
87{
88 if (h->version>=MI_VERSION2U(2,0,0))
89 {// MI v2
90 if (path)
91 mi_send(h,"-environment-directory \"%s\"\n",path);
92 else
93 mi_send(h,"-environment-directory -r\n");
94 }
95 else
96 {
97 mi_send(h,"-environment-directory %s\n",path ? path : "");
98 }
99}
100
101void mi_data_read_memory_hx(mi_h *h, const char *exp, unsigned ws,
102 unsigned c, int convAddr)
103{
104 if (convAddr)
105 mi_send(h,"-data-read-memory \"&%s\" x %d 1 %d\n",exp,ws,c);
106 else
107 mi_send(h,"-data-read-memory \"%s\" x %d 1 %d\n",exp,ws,c);
108}
109
110void mi_data_disassemble_se(mi_h *h, const char *start, const char *end,
111 int mode)
112{
113 mi_send(h,"-data-disassemble -s \"%s\" -e \"%s\" -- %d\n",start,end,mode);
114}
115
116void mi_data_disassemble_fl(mi_h *h, const char *file, int line, int lines,
117 int mode)
118{
119 mi_send(h,"-data-disassemble -f \"%s\" -l %d -n %d -- %d\n",file,line,lines,
120 mode);
121}
122
123void mi_data_list_register_names(mi_h *h)
124{
125 mi_send(h,"-data-list-register-names\n");
126}
127
128void mi_data_list_register_names_l(mi_h *h, mi_chg_reg *l)
129{
130 mi_send(h,"-data-list-register-names ");
131 while (l)
132 {
133 mi_send(h,"%d ",l->reg);
134 l=l->next;
135 }
136 mi_send(h,"\n");
137}
138
139void mi_data_list_changed_registers(mi_h *h)
140{
141 mi_send(h,"-data-list-changed-registers\n");
142}
143
144void mi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l)
145{
146 mi_send(h,"-data-list-register-values %c ",mi_format_enum_to_char(fmt));
147 while (l)
148 {
149 mi_send(h,"%d ",l->reg);
150 l=l->next;
151 }
152 mi_send(h,"\n");
153}
154
155/* High level versions. */
156
157/**[txh]********************************************************************
158
159 Description:
160 Evaluate an expression. Returns a parsed tree.
161
162 Command: -data-evaluate-expression
163 Return: The resulting value (as plain text) or NULL on error.
164
165***************************************************************************/
166
167char *gmi_data_evaluate_expression(mi_h *h, const char *expression)
168{
169 mi_data_evaluate_expression(h,expression);
170 return mi_res_value(h);
171}
172
173/**[txh]********************************************************************
174
175 Description:
176 Path for sources. You must use it to indicate where are the sources for
177the program to debug. Only the MI v1 implementation is available.
178
179 Command: -environment-directory
180 Return: !=0 OK
181
182***************************************************************************/
183
184int gmi_dir(mi_h *h, const char *path)
185{
186 mi_dir(h,path);
187 return mi_res_simple_done(h);
188}
189
190int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
191 unsigned char *dest, int *na, int convAddr,
192 unsigned long *addr)
193{
194 mi_data_read_memory_hx(h,exp,1,size,convAddr);
195 return mi_get_read_memory(h,dest,1,na,addr);
196}
197
198mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
199 const char *end, int mode)
200{
201 mi_data_disassemble_se(h,start,end,mode);
202 return mi_get_asm_insns(h);
203}
204
205mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
206 int lines, int mode)
207{
208 mi_data_disassemble_fl(h,file,line,lines,mode);
209 return mi_get_asm_insns(h);
210}
211
212// Affected by gdb bug mi/1770
213mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many)
214{
215 mi_data_list_register_names(h);
216 return mi_get_list_registers(h,how_many);
217}
218
219int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l)
220{
221 mi_data_list_register_names_l(h,l);
222 return mi_get_list_registers_l(h,l);
223}
224
225mi_chg_reg *gmi_data_list_changed_registers(mi_h *h)
226{
227 mi_error=MI_OK;
228 mi_data_list_changed_registers(h);
229 return mi_get_list_changed_regs(h);
230}
231
232int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l)
233{
234 mi_data_list_register_values(h,fmt,l);
235 return mi_get_reg_values(h,l);
236}
237
238mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many)
239{
240 mi_data_list_register_values(h,fmt,NULL);
241 return mi_get_reg_values_l(h,how_many);
242}
243
diff --git a/src/monkey/gdbmi_error.c b/src/monkey/gdbmi_error.c
deleted file mode 100644
index abb20f61e..000000000
--- a/src/monkey/gdbmi_error.c
+++ /dev/null
@@ -1,38 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Error.
7 Comment:
8 Translates error numbers into messages.
9
10***************************************************************************/
11
12#include "gdbmi.h"
13
14static
15const char *error_strs[]=
16{
17 "Ok",
18 "Out of memory",
19 "Pipe creation",
20 "Fork failed",
21 "GDB not running",
22 "Parser failed",
23 "Unknown asyn response",
24 "Unknown result response",
25 "Error from gdb",
26 "Time out in gdb response",
27 "GDB suddenly died",
28 "Can't execute X terminal",
29 "Failed to create temporal",
30 "Can't execute the debugger"
31};
32
33const char *mi_get_error_str()
34{
35 if (mi_error<0 || mi_error>MI_LAST_ERROR)
36 return "Unknown";
37 return error_strs[mi_error];
38}
diff --git a/src/monkey/gdbmi_get_free_pty.c b/src/monkey/gdbmi_get_free_pty.c
deleted file mode 100644
index 4274c7826..000000000
--- a/src/monkey/gdbmi_get_free_pty.c
+++ /dev/null
@@ -1,132 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: pseudo terminal
7 Comments:
8 Helper to find a free pseudo terminal. Use this if you need to manage
9 input *and* output to the target process. If you just need output then
10 define a handler for target output stream records (assuming that this
11 is working for your particular version of gdb).
12 Usage:
13
14 mi_pty *pty = gmi_look_for_free_pty();
15 if (pty) gmi_target_terminal(mih, pty->slave);
16 ...
17 * reading from pty->master will get stdout from target *
18 * writing to pty->master will send to target stdin *
19
20 Note: Contributed by Greg Watson (gwatson lanl gov)
21
22***************************************************************************/
23
24#define _GNU_SOURCE
25#include <string.h>
26#include <stdio.h>
27#include <unistd.h>
28#include <fcntl.h>
29#include <sys/ioctl.h>
30
31#include "gdbmi.h"
32
33/**[txh]********************************************************************
34
35 Description:
36 Look for a free and usable pseudo terminal. Low level, use
37 gmi_look_for_free_pty().
38
39 Return: A file descriptor connected to the master pty and the name of the slave device, or <0 on error.
40
41***************************************************************************/
42
43#ifdef __APPLE__
44
45#include <util.h>
46
47int mi_look_for_free_pty(int *master, char **slave)
48{
49 int fdmaster;
50 int fdslave;
51 static char name[BUFSIZ];
52
53 if (openpty(&fdmaster,&fdslave,name,NULL,NULL)<0)
54 return -1;
55
56 (void)close(fdslave); /* this will be reopened by gdb */
57 *master=fdmaster;
58 *slave =name;
59
60 return 0;
61}
62
63#elif defined(__linux__)
64
65int mi_look_for_free_pty(int *master, char **slave)
66{
67 if ((*master=open("/dev/ptmx",O_RDWR))<0)
68 return -1;
69 if (grantpt(*master)<0 || unlockpt(*master)<0)
70 return -1;
71 *slave = ptsname(*master);
72
73 return 0;
74}
75
76#else /* undefined o/s */
77
78int mi_look_for_free_pty(int *master, char **slave)
79{
80 return -1;
81}
82#endif
83
84/**[txh]********************************************************************
85
86 Description:
87 Look for a free and usable pseudo terminal to be used by the child.
88
89 Return: A new mi_pty structure, you can use gmi_end_pty to
90release it.
91
92***************************************************************************/
93
94mi_pty *gmi_look_for_free_pty()
95{
96 int master;
97 char *slave;
98 int pty=mi_look_for_free_pty(&master,&slave);
99 mi_pty *res;
100
101 if (pty<0)
102 return NULL;
103 res=(mi_pty *)malloc(sizeof(mi_pty));
104 if (!res)
105 return NULL;
106 res->slave=strdup(slave);
107 res->master=master;
108 return res;
109}
110
111void mi_free_pty(mi_pty *p)
112{
113 if (!p)
114 return;
115 free(p->slave);
116 free(p);
117}
118
119/**[txh]********************************************************************
120
121 Description:
122 Closes the pseudo termial master and releases the allocated memory.
123
124***************************************************************************/
125
126void gmi_end_pty(mi_pty *p)
127{
128 if (!p)
129 return;
130 close(p->master);
131 mi_free_pty(p);
132}
diff --git a/src/monkey/gdbmi_get_free_vt.c b/src/monkey/gdbmi_get_free_vt.c
deleted file mode 100644
index 25e5e75a7..000000000
--- a/src/monkey/gdbmi_get_free_vt.c
+++ /dev/null
@@ -1,156 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Linux VT.
7 Comments:
8 Helper to find a free VT. That's 100% Linux specific.@p
9 The code comes from "lconsole.c" from Allegro project and was originally
10created by Marek Habersack and then modified by George Foot. I addapted it
11to my needs and changed license from giftware to GPL.@p
12
13***************************************************************************/
14
15#define _GNU_SOURCE
16#include <string.h>
17#include <stdio.h>
18#include <unistd.h>
19#include <fcntl.h>
20#include <sys/ioctl.h>
21#ifdef __APPLE__
22#include <util.h>
23#endif /* __APPLE__ */
24
25#include "gdbmi.h"
26
27#if !defined(__linux__)
28
29int mi_look_for_free_vt()
30{
31 return -1;
32}
33
34mi_aux_term *gmi_look_for_free_vt()
35{
36 return NULL;
37}
38
39#else
40
41#include <linux/vt.h>
42
43/**[txh]********************************************************************
44
45 Description:
46 Look for a free and usable Linux VT. Low level, use
47@x{gmi_look_for_free_vt}.
48
49 Return: The VT number or <0 on error.
50
51***************************************************************************/
52
53int mi_look_for_free_vt()
54{/* Code from Allegro. */
55 int tty, console_fd, fd;
56 unsigned short mask;
57 char tty_name[16];
58 struct vt_stat vts;
59
60 /* Now we need to find a VT we can use. It must be readable and
61 * writable by us, if we're not setuid root. VT_OPENQRY itself
62 * isn't too useful because it'll only ever come up with one
63 * suggestion, with no guarrantee that we actually have access
64 * to it.
65 *
66 * At some stage I think this is a candidate for config
67 * file overriding, but for now we'll stat the first N consoles
68 * to see which ones we can write to (hopefully at least one!),
69 * so that we can use that one to do ioctls. We used to use
70 * /dev/console for that purpose but it looks like it's not
71 * always writable by enough people.
72 *
73 * Having found and opened a writable device, we query the state
74 * of the first sixteen (fifteen really) consoles, and try
75 * opening each unused one in turn.
76 */
77
78 console_fd=open("/dev/console",O_WRONLY);
79 if (console_fd<0)
80 {
81 int n;
82 /* Try some ttys instead... */
83 for (n=1; n<=24; n++)
84 {
85 snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",n);
86 console_fd=open(tty_name,O_WRONLY);
87 if (console_fd>=0)
88 break;
89 }
90 if (n>24)
91 return -1;
92 }
93
94 /* Get the state of the console -- in particular, the free VT field */
95 if (ioctl(console_fd,VT_GETSTATE,&vts)) {
96 close(console_fd);
97 return -2;
98 }
99 close(console_fd);
100
101 /* We attempt to set our euid to 0; if we were run with euid 0 to
102 * start with, we'll be able to do this now. Otherwise, we'll just
103 * ignore the error returned since it might not be a problem if the
104 * ttys we look at are owned by the user running the program. */
105 seteuid(0);
106
107 /* tty0 is not really a console, so start counting at 2. */
108 fd=-1;
109 for (tty=1, mask=2; mask; tty++, mask<<=1)
110 if (!(vts.v_state & mask))
111 {
112 snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",tty);
113 fd=open(tty_name,O_RDWR);
114 if (fd!=-1)
115 {
116 close(fd);
117 break;
118 }
119 }
120
121 seteuid(getuid());
122
123 if (!mask)
124 return -3;
125
126 return tty;
127}
128
129/**[txh]********************************************************************
130
131 Description:
132 Look for a free and usable Linux VT to be used by the child.
133
134 Return: A new mi_aux_term structure, you can use @x{gmi_end_aux_term} to
135release it.
136
137***************************************************************************/
138
139mi_aux_term *gmi_look_for_free_vt()
140{
141 int ret;
142 int vt=mi_look_for_free_vt();
143 mi_aux_term *res;
144
145 if (vt<0)
146 return NULL;
147 res=(mi_aux_term *)malloc(sizeof(mi_aux_term));
148 if (!res)
149 return NULL;
150 res->pid=-1;
151 ret = asprintf(&res->tty,"/dev/tty%d",vt);
152 return res;
153}
154
155#endif
156
diff --git a/src/monkey/gdbmi_misc.c b/src/monkey/gdbmi_misc.c
deleted file mode 100644
index 51088a757..000000000
--- a/src/monkey/gdbmi_misc.c
+++ /dev/null
@@ -1,118 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Miscellaneous commands.
7 Comments:
8 GDB/MI commands for the "Miscellaneous Commands" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12
13-gdb-exit Yes
14-gdb-set Yes
15-gdb-show Yes
16-gdb-version Yes
17@</pre>
18
19GDB Bug workaround for "-gdb-show architecture": gdb 6.1 and olders doesn't
20report it in "value", but they give the output of "show architecture". In
216.4 we observed that not even a clue is reported. So now we always use
22"show architecture".
23
24***************************************************************************/
25
26#include <string.h>
27#include "gdbmi.h"
28
29/* Low level versions. */
30
31void mi_gdb_exit(mi_h *h)
32{
33 mi_send(h,"-gdb-exit\n");
34}
35
36void mi_gdb_version(mi_h *h)
37{
38 mi_send(h,"-gdb-version\n");
39}
40
41void mi_gdb_set(mi_h *h, const char *var, const char *val)
42{
43 mi_send(h,"-gdb-set %s %s\n",var,val);
44}
45
46void mi_gdb_show(mi_h *h, const char *var)
47{
48 if (strcmp(var,"architecture")==0)
49 mi_send(h,"show %s\n",var);
50 else
51 mi_send(h,"-gdb-show %s\n",var);
52}
53
54/* High level versions. */
55
56/**[txh]********************************************************************
57
58 Description:
59 Exit gdb killing the child is it is running.
60
61 Command: -gdb-exit
62
63***************************************************************************/
64
65void gmi_gdb_exit(mi_h *h)
66{
67 mi_gdb_exit(h);
68 mi_res_simple_exit(h);
69}
70
71/**[txh]********************************************************************
72
73 Description:
74 Send the version to the console.
75
76 Command: -gdb-version
77 Return: !=0 OK
78
79***************************************************************************/
80
81int gmi_gdb_version(mi_h *h)
82{
83 mi_gdb_version(h);
84 return mi_res_simple_done(h);
85}
86
87/**[txh]********************************************************************
88
89 Description:
90 Set a gdb variable.
91
92 Command: -gdb-set
93 Return: !=0 OK
94
95***************************************************************************/
96
97int gmi_gdb_set(mi_h *h, const char *var, const char *val)
98{
99 mi_gdb_set(h,var,val);
100 return mi_res_simple_done(h);
101}
102
103/**[txh]********************************************************************
104
105 Description:
106 Get a gdb variable.
107
108 Command: -gdb-show
109 Return: The current value of the variable or NULL on error.
110
111***************************************************************************/
112
113char *gmi_gdb_show(mi_h *h, const char *var)
114{
115 mi_gdb_show(h,var);
116 return mi_res_value(h);
117}
118
diff --git a/src/monkey/gdbmi_parse.c b/src/monkey/gdbmi_parse.c
deleted file mode 100644
index 678276ba3..000000000
--- a/src/monkey/gdbmi_parse.c
+++ /dev/null
@@ -1,1927 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2007 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Parser.
7 Comments:
8 Parses the output of gdb. It basically converts the text from gdb into a
9tree (could be a complex one) that we can easily interpret using C code.
10
11***************************************************************************/
12
13#include <ctype.h>
14#include <string.h>
15#include <assert.h>
16#include "gdbmi.h"
17
18mi_results *mi_get_result(const char *str, const char **end);
19int mi_get_value(mi_results *r, const char *str, const char **end);
20
21
22/* GDB BUG!!!! I got:
23^error,msg="Problem parsing arguments: data-evaluate-expression ""1+2"""
24Afects gdb 2002-04-01-cvs and 6.1.1 for sure.
25That's an heuristical workaround.
26*/
27static inline
28int EndOfStr(const char *s)
29{
30 if (*s=='"')
31 {
32 s++;
33 return !*s || *s==',' || *s==']' || *s=='}';
34 }
35 return 0;
36}
37
38int mi_get_cstring_r(mi_results *r, const char *str, const char **end)
39{
40 const char *s;
41 char *d;
42 int len;
43
44 if (*str!='"')
45 {
46 mi_error=MI_PARSER;
47 return 0;
48 }
49 str++;
50 /* Meassure. */
51 for (s=str, len=0; *s && !EndOfStr(s); s++)
52 {
53 if (!*s) {
54 mi_error = MI_PARSER;
55 return 0;
56 }
57 if (*s=='\\')
58 s++;
59 len++;
60 }
61 /* Copy. */
62 r->type=t_const;
63 d=r->v.cstr=mi_malloc(len+1);
64 if (!r->v.cstr)
65 return 0;
66 for (s=str; *s && !EndOfStr(s); s++, d++)
67 {
68 if (*s=='\\')
69 {
70 s++;
71 switch (*s)
72 {
73 case 'n':
74 *d='\n';
75 break;
76 case 't':
77 *d='\t';
78 break;
79 default:
80 *d=*s;
81 }
82 }
83 else
84 *d=*s;
85 }
86 *d=0;
87 if (end)
88 *end=s+1;
89
90 return 1;
91}
92
93/* TODO: What's a valid variable name?
94 I'll assume a-zA-Z0-9_- */
95inline
96int mi_is_var_name_char(char c)
97{
98 return isalnum(c) || c=='-' || c=='_';
99}
100
101char *mi_get_var_name(const char *str, const char **end)
102{
103 const char *s;
104 char *r;
105 int l;
106 /* Meassure. */
107 for (s=str; *s && mi_is_var_name_char(*s); s++);
108 if (*s!='=')
109 {
110 mi_error=MI_PARSER;
111 return NULL;
112 }
113 /* Allocate. */
114 l=s-str;
115 r=mi_malloc(l+1);
116 /* Copy. */
117 if (NULL != r) {
118 memcpy(r,str,l);
119 r[l]=0;
120 }
121 if (end)
122 *end=s+1;
123 return r;
124}
125
126
127int mi_get_list_res(mi_results *r, const char *str, const char **end, char closeC)
128{
129 mi_results *last_r, *rs;
130
131 last_r=NULL;
132 do
133 {
134 rs=mi_get_result(str,&str);
135 if (last_r)
136 last_r->next=rs;
137 else
138 r->v.rs=rs;
139 last_r=rs;
140 if (*str==closeC)
141 {
142 *end=str+1;
143 return 1;
144 }
145 if (*str!=',')
146 break;
147 str++;
148 }
149 while (1);
150
151 mi_error=MI_PARSER;
152 return 0;
153}
154
155#ifdef __APPLE__
156int mi_get_tuple_val(mi_results *r, const char *str, const char **end)
157{
158 mi_results *last_r, *rs;
159
160 last_r=NULL;
161 do
162 {
163 rs=mi_alloc_results();
164 if (!rs || !mi_get_value(rs,str,&str))
165 {
166 mi_free_results(rs);
167 return 0;
168 }
169 /* Note that rs->var is NULL, that indicates that's just a value and not
170 a result. */
171 if (last_r)
172 last_r->next=rs;
173 else
174 r->v.rs=rs;
175 last_r=rs;
176 if (*str=='}')
177 {
178 *end=str+1;
179 return 1;
180 }
181 if (*str!=',')
182 break;
183 str++;
184 }
185 while (1);
186
187 mi_error=MI_PARSER;
188 return 0;
189}
190#endif /* __APPLE__ */
191
192int mi_get_tuple(mi_results *r, const char *str, const char **end)
193{
194 if (*str!='{')
195 {
196 mi_error=MI_PARSER;
197 return 0;
198 }
199 r->type=t_tuple;
200 str++;
201 if (*str=='}')
202 {/* Special case: empty tuple */
203 *end=str+1;
204 return 1;
205 }
206 #ifdef __APPLE__
207 if (mi_is_var_name_char(*str))
208 return mi_get_list_res(r,str,end,'}');
209 return mi_get_tuple_val(r,str,end);
210 #else /* __APPLE__ */
211 return mi_get_list_res(r,str,end,'}');
212 #endif /* __APPLE__ */
213}
214
215int mi_get_list_val(mi_results *r, const char *str, const char **end)
216{
217 mi_results *last_r, *rs;
218
219 last_r=NULL;
220 do
221 {
222 rs=mi_alloc_results();
223 if (!rs || !mi_get_value(rs,str,&str))
224 {
225 mi_free_results(rs);
226 return 0;
227 }
228 /* Note that rs->var is NULL, that indicates that's just a value and not
229 a result. */
230 if (last_r)
231 last_r->next=rs;
232 else
233 r->v.rs=rs;
234 last_r=rs;
235 if (*str==']')
236 {
237 *end=str+1;
238 return 1;
239 }
240 if (*str!=',')
241 break;
242 str++;
243 }
244 while (1);
245
246 mi_error=MI_PARSER;
247 return 0;
248}
249
250int mi_get_list(mi_results *r, const char *str, const char **end)
251{
252 if (*str!='[')
253 {
254 mi_error=MI_PARSER;
255 return 0;
256 }
257 r->type=t_list;
258 str++;
259 if (*str==']')
260 {/* Special case: empty list */
261 *end=str+1;
262 return 1;
263 }
264 /* Comment: I think they could choose () for values. Is confusing in this way. */
265 if (mi_is_var_name_char(*str))
266 return mi_get_list_res(r,str,end,']');
267 return mi_get_list_val(r,str,end);
268}
269
270int mi_get_value(mi_results *r, const char *str, const char **end)
271{
272 switch (str[0])
273 {
274 case '"':
275 return mi_get_cstring_r(r,str,end);
276 case '{':
277 return mi_get_tuple(r,str,end);
278 case '[':
279 return mi_get_list(r,str,end);
280 }
281 mi_error=MI_PARSER;
282 return 0;
283}
284
285mi_results *mi_get_result(const char *str, const char **end)
286{
287 char *var;
288 mi_results *r;
289
290 var=mi_get_var_name(str,&str);
291 if (!var)
292 return NULL;
293
294 r=mi_alloc_results();
295 if (!r)
296 {
297 free(var);
298 return NULL;
299 }
300 r->var=var;
301
302 if (!mi_get_value(r,str,end))
303 {
304 mi_free_results(r);
305 return NULL;
306 }
307
308 return r;
309}
310
311mi_output *mi_get_results_alone(mi_output *r,const char *str)
312{
313 mi_results *last_r, *rs;
314
315 /* * results */
316 last_r=NULL;
317 do
318 {
319 if (!*str)
320 return r;
321 if (*str!=',')
322 {
323 mi_error=MI_PARSER;
324 break;
325 }
326 str++;
327 rs=mi_get_result(str,&str);
328 if (!rs)
329 break;
330 if (!last_r)
331 r->c=rs;
332 else
333 last_r->next=rs;
334 last_r=rs;
335 }
336 while (1);
337 mi_free_output(r);
338 return NULL;
339}
340
341mi_output *mi_parse_result_record(mi_output *r,const char *str)
342{
343 r->type=MI_T_RESULT_RECORD;
344
345 /* Solve the result-class. */
346 if (strncmp(str,"done",4)==0)
347 {
348 str+=4;
349 r->tclass=MI_CL_DONE;
350 }
351 else if (strncmp(str,"running",7)==0)
352 {
353 str+=7;
354 r->tclass=MI_CL_RUNNING;
355 }
356 else if (strncmp(str,"connected",9)==0)
357 {
358 str+=9;
359 r->tclass=MI_CL_CONNECTED;
360 }
361 else if (strncmp(str,"error",5)==0)
362 {
363 str+=5;
364 r->tclass=MI_CL_ERROR;
365 }
366 else if (strncmp(str,"exit",4)==0)
367 {
368 str+=4;
369 r->tclass=MI_CL_EXIT;
370 }
371 else
372 {
373 mi_error=MI_UNKNOWN_RESULT;
374 return NULL;
375 }
376
377 return mi_get_results_alone(r,str);
378}
379
380mi_output *mi_parse_asyn(mi_output *r,const char *str)
381{
382 r->type=MI_T_OUT_OF_BAND;
383 r->stype=MI_ST_ASYNC;
384 /* async-class. */
385 if (strncmp(str,"stopped",7)==0)
386 {
387 r->tclass=MI_CL_STOPPED;
388 str+=7;
389 return mi_get_results_alone(r,str);
390 }
391 if (strncmp(str,"download",8)==0)
392 {
393 r->tclass=MI_CL_DOWNLOAD;
394 str+=8;
395 return mi_get_results_alone(r,str);
396 }
397 mi_error=MI_UNKNOWN_ASYNC;
398 mi_free_output(r);
399 return NULL;
400}
401
402mi_output *mi_parse_exec_asyn(mi_output *r,const char *str)
403{
404 r->sstype=MI_SST_EXEC;
405 return mi_parse_asyn(r,str);
406}
407
408mi_output *mi_parse_status_asyn(mi_output *r,const char *str)
409{
410 r->sstype=MI_SST_STATUS;
411 return mi_parse_asyn(r,str);
412}
413
414mi_output *mi_parse_notify_asyn(mi_output *r,const char *str)
415{
416 r->sstype=MI_SST_NOTIFY;
417 return mi_parse_asyn(r,str);
418}
419
420mi_output *mi_console(mi_output *r,const char *str)
421{
422 r->type=MI_T_OUT_OF_BAND;
423 r->stype=MI_ST_STREAM;
424 r->c=mi_alloc_results();
425 if (!r->c || !mi_get_cstring_r(r->c,str,NULL))
426 {
427 mi_free_output(r);
428 return NULL;
429 }
430 return r;
431}
432
433mi_output *mi_console_stream(mi_output *r,const char *str)
434{
435 r->sstype=MI_SST_CONSOLE;
436 return mi_console(r,str);
437}
438
439mi_output *mi_target_stream(mi_output *r,const char *str)
440{
441 r->sstype=MI_SST_TARGET;
442 return mi_console(r,str);
443}
444
445mi_output *mi_log_stream(mi_output *r,const char *str)
446{
447 r->sstype=MI_SST_LOG;
448 return mi_console(r,str);
449}
450
451mi_output *mi_parse_gdb_output(const char *str)
452{
453 char type=str[0];
454
455 mi_output *r=mi_alloc_output();
456 if (!r)
457 {
458 mi_error=MI_OUT_OF_MEMORY;
459 return NULL;
460 }
461 str++;
462 switch (type)
463 {
464 case '^':
465 return mi_parse_result_record(r,str);
466 case '*':
467 return mi_parse_exec_asyn(r,str);
468 case '+':
469 return mi_parse_status_asyn(r,str);
470 case '=':
471 return mi_parse_notify_asyn(r,str);
472 case '~':
473 return mi_console_stream(r,str);
474 case '@':
475 return mi_target_stream(r,str);
476 case '&':
477 return mi_log_stream(r,str);
478 }
479 mi_error=MI_PARSER;
480 return NULL;
481}
482
483mi_output *mi_get_rrecord(mi_output *r)
484{
485 if (!r)
486 return NULL;
487 while (r)
488 {
489 if (r->type==MI_T_RESULT_RECORD)
490 return r;
491 r=r->next;
492 }
493 return r;
494}
495
496mi_results *mi_get_var_r(mi_results *r, const char *var)
497{
498 while (r)
499 {
500 if (strcmp(r->var,var)==0)
501 return r;
502 r=r->next;
503 }
504 return NULL;
505}
506
507mi_results *mi_get_var(mi_output *res, const char *var)
508{
509 if (!res)
510 return NULL;
511 return mi_get_var_r(res->c,var);
512}
513
514int mi_get_async_stop_reason(mi_output *r, char **reason)
515{
516 int found_stopped=0;
517
518 *reason=NULL;
519 while (r)
520 {
521 if (r->type==MI_T_RESULT_RECORD && r->tclass==MI_CL_ERROR)
522 {
523 if (r->c->type==t_const)
524 *reason=r->c->v.cstr;
525 return 0;
526 }
527 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
528 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
529 {
530 mi_results *p=r->c;
531 found_stopped=1;
532 while (p)
533 {
534 if (strcmp(p->var,"reason")==0)
535 {
536 *reason=p->v.cstr;
537 return 1;
538 }
539 p=p->next;
540 }
541 }
542 r=r->next;
543 }
544 if (*reason==NULL && found_stopped)
545 {
546 *reason=strdup("unknown (temp bkpt?)");
547 return 1;
548 }
549 return 0;
550}
551
552mi_frames *mi_get_async_frame(mi_output *r)
553{
554 while (r)
555 {
556 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
557 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
558 {
559 mi_results *p=r->c;
560 while (p)
561 {
562 if (strcmp(p->var,"frame")==0)
563 return mi_parse_frame(p->v.rs);
564 p=p->next;
565 }
566 }
567 r=r->next;
568 }
569 return NULL;
570}
571
572int mi_res_simple(mi_h *h, int tclass, int accert_ret)
573{
574 mi_output *r, *res;
575 int ret=0;
576
577 r=mi_get_response_blk(h);
578 res=mi_get_rrecord(r);
579
580 if (res)
581 ret=res->tclass==tclass;
582 mi_free_output(r);
583
584 return ret;
585}
586
587
588int mi_res_simple_done(mi_h *h)
589{
590 return mi_res_simple(h,MI_CL_DONE,0);
591}
592
593int mi_res_simple_exit(mi_h *h)
594{
595 return mi_res_simple(h,MI_CL_EXIT,1);
596}
597
598int mi_res_simple_running(mi_h *h)
599{
600 return mi_res_simple(h,MI_CL_RUNNING,0);
601}
602
603int mi_res_simple_connected(mi_h *h)
604{
605 return mi_res_simple(h,MI_CL_CONNECTED,0);
606}
607
608mi_results *mi_res_var(mi_h *h, const char *var, int tclass)
609{
610 mi_output *r, *res;
611 mi_results *the_var=NULL;
612
613 r=mi_get_response_blk(h);
614 /* All the code that follows is "NULL" tolerant. */
615 /* Look for the result-record. */
616 res=mi_get_rrecord(r);
617 /* Look for the desired var. */
618 if (res && res->tclass==tclass)
619 the_var=mi_get_var(res,var);
620 /* Release all but the one we want. */
621 mi_free_output_but(r,NULL,the_var);
622 return the_var;
623}
624
625mi_results *mi_res_done_var(mi_h *h, const char *var)
626{
627 return mi_res_var(h,var,MI_CL_DONE);
628}
629
630mi_frames *mi_parse_frame(mi_results *c)
631{
632 mi_frames *res=mi_alloc_frames();
633 char *end;
634
635 if (res)
636 {
637 while (c)
638 {
639 if (c->type==t_const)
640 {
641 if (strcmp(c->var,"level")==0)
642 res->level=atoi(c->v.cstr);
643 else if (strcmp(c->var,"addr")==0)
644 res->addr=(void *)strtoul(c->v.cstr,&end,0);
645 else if (strcmp(c->var,"func")==0)
646 {
647 res->func=c->v.cstr;
648 c->v.cstr=NULL;
649 }
650 else if (strcmp(c->var,"file")==0)
651 {
652 res->file=c->v.cstr;
653 c->v.cstr=NULL;
654 }
655 else if (strcmp(c->var,"from")==0)
656 {
657 res->from=c->v.cstr;
658 c->v.cstr=NULL;
659 }
660 else if (strcmp(c->var,"line")==0)
661 res->line=atoi(c->v.cstr);
662 }
663 else if (c->type==t_list && strcmp(c->var,"args")==0)
664 {
665 res->args=c->v.rs;
666 c->v.rs=NULL;
667 }
668 c=c->next;
669 }
670 }
671 return res;
672}
673
674mi_frames *mi_res_frame(mi_h *h)
675{
676 mi_results *r=mi_res_done_var(h,"frame");
677 mi_frames *f=NULL;
678
679 if (r && r->type==t_tuple)
680 f=mi_parse_frame(r->v.rs);
681 mi_free_results(r);
682 return f;
683}
684
685mi_frames *mi_res_frames_array(mi_h *h, const char *var)
686{
687 mi_results *r=mi_res_done_var(h,var), *c;
688 mi_frames *res=NULL, *nframe, *last=NULL;
689
690 if (!r)
691 return NULL;
692#ifdef __APPLE__
693 if (r->type!=t_list && r->type!=t_tuple)
694#else
695 if (r->type!=t_list)
696#endif
697 {
698 mi_free_results(r);
699 return NULL;
700 }
701 c=r->v.rs;
702 while (c)
703 {
704 if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
705 {
706 nframe=mi_parse_frame(c->v.rs);
707 if (nframe)
708 {
709 if (!last)
710 res=nframe;
711 else
712 last->next=nframe;
713 last=nframe;
714 }
715 }
716 c=c->next;
717 }
718 mi_free_results(r);
719 return res;
720}
721
722mi_frames *mi_res_frames_list(mi_h *h)
723{
724 mi_output *r, *res;
725 mi_frames *ret=NULL, *nframe, *last=NULL;
726 mi_results *c;
727
728 r=mi_get_response_blk(h);
729 res=mi_get_rrecord(r);
730 if (res && res->tclass==MI_CL_DONE)
731 {
732 c=res->c;
733 while (c)
734 {
735 if (strcmp(c->var,"frame")==0 && c->type==t_tuple)
736 {
737 nframe=mi_parse_frame(c->v.rs);
738 if (nframe)
739 {
740 if (!last)
741 ret=nframe;
742 else
743 last->next=nframe;
744 last=nframe;
745 }
746 }
747 c=c->next;
748 }
749 }
750 mi_free_output(r);
751 return ret;
752}
753
754int mi_get_thread_ids(mi_output *res, int **list)
755{
756 mi_results *vids, *lids;
757 int ids=-1, i;
758
759 *list=NULL;
760 vids=mi_get_var(res,"number-of-threads");
761 lids=mi_get_var(res,"thread-ids");
762 if (vids && vids->type==t_const &&
763 lids && lids->type==t_tuple)
764 {
765 ids=atoi(vids->v.cstr);
766 if (ids)
767 {
768 int *lst;
769 lst=(int *)mi_calloc(ids,sizeof(int));
770 if (lst)
771 {
772 lids=lids->v.rs;
773 i=0;
774 while (lids)
775 {
776 if (strcmp(lids->var,"thread-id")==0 && lids->type==t_const)
777 lst[i++]=atoi(lids->v.cstr);
778 lids=lids->next;
779 }
780 *list=lst;
781 }
782 else
783 ids=-1;
784 }
785 }
786 return ids;
787}
788
789int mi_res_thread_ids(mi_h *h, int **list)
790{
791 mi_output *r, *res;
792 int ids=-1;
793
794 r=mi_get_response_blk(h);
795 res=mi_get_rrecord(r);
796 if (res && res->tclass==MI_CL_DONE)
797 ids=mi_get_thread_ids(res,list);
798 mi_free_output(r);
799 return ids;
800}
801
802enum mi_gvar_lang mi_lang_str_to_enum(const char *lang)
803{
804 enum mi_gvar_lang lg=lg_unknown;
805
806 if (strcmp(lang,"C")==0)
807 lg=lg_c;
808 else if (strcmp(lang,"C++")==0)
809 lg=lg_cpp;
810 else if (strcmp(lang,"Java")==0)
811 lg=lg_java;
812
813 return lg;
814}
815
816const char *mi_lang_enum_to_str(enum mi_gvar_lang lang)
817{
818 const char *lg;
819
820 switch (lang)
821 {
822 case lg_c:
823 lg="C";
824 break;
825 case lg_cpp:
826 lg="C++";
827 break;
828 case lg_java:
829 lg="Java";
830 break;
831 /*case lg_unknown:*/
832 default:
833 lg="unknown";
834 break;
835 }
836 return lg;
837}
838
839enum mi_gvar_fmt mi_format_str_to_enum(const char *format)
840{
841 enum mi_gvar_fmt fmt=fm_natural;
842
843 if (strcmp(format,"binary")==0)
844 fmt=fm_binary;
845 else if (strcmp(format,"decimal")==0)
846 fmt=fm_decimal;
847 else if (strcmp(format,"hexadecimal")==0)
848 fmt=fm_hexadecimal;
849 else if (strcmp(format,"octal")==0)
850 fmt=fm_octal;
851
852 return fmt;
853}
854
855const char *mi_format_enum_to_str(enum mi_gvar_fmt format)
856{
857 const char *fmt;
858
859 switch (format)
860 {
861 case fm_natural:
862 fmt="natural";
863 break;
864 case fm_binary:
865 fmt="binary";
866 break;
867 case fm_decimal:
868 fmt="decimal";
869 break;
870 case fm_hexadecimal:
871 fmt="hexadecimal";
872 break;
873 case fm_octal:
874 fmt="octal";
875 break;
876 case fm_raw:
877 fmt="raw";
878 break;
879 default:
880 fmt="unknown";
881 }
882 return fmt;
883}
884
885char mi_format_enum_to_char(enum mi_gvar_fmt format)
886{
887 char fmt;
888
889 switch (format)
890 {
891 case fm_natural:
892 fmt='N';
893 break;
894 case fm_binary:
895 fmt='t';
896 break;
897 case fm_decimal:
898 fmt='d';
899 break;
900 case fm_hexadecimal:
901 fmt='x';
902 break;
903 case fm_octal:
904 fmt='o';
905 break;
906 case fm_raw:
907 fmt='r';
908 break;
909 default:
910 fmt=' ';
911 }
912 return fmt;
913}
914
915mi_gvar *mi_get_gvar(mi_output *o, mi_gvar *cur, const char *expression)
916{
917 mi_results *r;
918 mi_gvar *res=cur ? cur : mi_alloc_gvar();
919 int l;
920
921 if (!res)
922 return res;
923 r=o->c;
924 if (expression)
925 res->exp=strdup(expression);
926 while (r)
927 {
928 if (r->type==t_const)
929 {
930 if (strcmp(r->var,"name")==0)
931 {
932 free(res->name);
933 res->name=r->v.cstr;
934 r->v.cstr=NULL;
935 }
936 else if (strcmp(r->var,"numchild")==0)
937 {
938 res->numchild=atoi(r->v.cstr);
939 }
940 else if (strcmp(r->var,"type")==0)
941 {
942 free(res->type);
943 res->type=r->v.cstr;
944 r->v.cstr=NULL;
945 l=strlen(res->type);
946 if (l && res->type[l-1]=='*')
947 res->ispointer=1;
948 }
949 else if (strcmp(r->var,"lang")==0)
950 {
951 res->lang=mi_lang_str_to_enum(r->v.cstr);
952 }
953 else if (strcmp(r->var,"exp")==0)
954 {
955 free(res->exp);
956 res->exp=r->v.cstr;
957 r->v.cstr=NULL;
958 }
959 else if (strcmp(r->var,"format")==0)
960 {
961 res->format=mi_format_str_to_enum(r->v.cstr);
962 }
963 else if (strcmp(r->var,"attr")==0)
964 { /* Note: gdb 6.1.1 have only this: */
965 if (strcmp(r->v.cstr,"editable")==0)
966 res->attr=MI_ATTR_EDITABLE;
967 else /* noneditable */
968 res->attr=MI_ATTR_NONEDITABLE;
969 }
970 }
971 r=r->next;
972 }
973 return res;
974}
975
976mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression)
977{
978 mi_output *r, *res;
979 mi_gvar *gvar=NULL;
980
981 r=mi_get_response_blk(h);
982 res=mi_get_rrecord(r);
983 if (res && res->tclass==MI_CL_DONE)
984 gvar=mi_get_gvar(res,cur,expression);
985 mi_free_output(r);
986 return gvar;
987}
988
989mi_gvar_chg *mi_get_gvar_chg(mi_results *r)
990{
991 mi_gvar_chg *n;
992
993 if (r->type!=t_const)
994 return NULL;
995 n=mi_alloc_gvar_chg();
996 if (n)
997 {
998 while (r)
999 {
1000 if (r->type==t_const)
1001 {
1002 if (strcmp(r->var,"name")==0)
1003 {
1004 n->name=r->v.cstr;
1005 r->v.cstr=NULL;
1006 }
1007 else if (strcmp(r->var,"in_scope")==0)
1008 {
1009 n->in_scope=strcmp(r->v.cstr,"true")==0;
1010 }
1011 else if (strcmp(r->var,"new_type")==0)
1012 {
1013 n->new_type=r->v.cstr;
1014 r->v.cstr=NULL;
1015 }
1016 else if (strcmp(r->var,"new_num_children")==0)
1017 {
1018 n->new_num_children=atoi(r->v.cstr);
1019 }
1020 // type_changed="false" is the default
1021 }
1022 r=r->next;
1023 }
1024 }
1025 return n;
1026}
1027
1028int mi_res_changelist(mi_h *h, mi_gvar_chg **changed)
1029{
1030 mi_gvar_chg *last, *n;
1031 mi_results *res=mi_res_done_var(h,"changelist"), *r;
1032 int count=0;
1033
1034 *changed=NULL;
1035 if (!res)
1036 return 0;
1037 last=NULL;
1038 count=1;
1039 n=NULL;
1040 r=res->v.rs;
1041
1042 if (res->type==t_list)
1043 {// MI v2 a list of tuples
1044 while (r)
1045 {
1046 if (r->type==t_tuple)
1047 {
1048 n=mi_get_gvar_chg(r->v.rs);
1049 if (n)
1050 {
1051 if (last)
1052 last->next=n;
1053 else
1054 *changed=n;
1055 last=n;
1056 count++;
1057 }
1058 }
1059 r=r->next;
1060 }
1061 }
1062 else if (res->type==t_tuple)
1063 {// MI v1 a tuple with all together *8-P
1064 while (r)
1065 {
1066 if (r->type==t_const) /* Just in case. */
1067 {/* Get one var. */
1068 if (strcmp(r->var,"name")==0)
1069 {
1070 if (n)
1071 {/* Add to the list*/
1072 if (last)
1073 last->next=n;
1074 else
1075 *changed=n;
1076 last=n;
1077 count++;
1078 }
1079 n=mi_alloc_gvar_chg();
1080 if (!n)
1081 {
1082 mi_free_gvar_chg(*changed);
1083 return 0;
1084 }
1085 n->name=r->v.cstr;
1086 r->v.cstr=NULL;
1087 }
1088 else if ((NULL != n) && (strcmp(r->var,"in_scope")==0))
1089 {
1090 n->in_scope=strcmp(r->v.cstr,"true")==0;
1091 }
1092 else if ((NULL != n) && (strcmp(r->var,"new_type")==0))
1093 {
1094 n->new_type=r->v.cstr;
1095 r->v.cstr=NULL;
1096 }
1097 else if ((NULL != n) && (strcmp(r->var,"new_num_children")==0))
1098 {
1099 n->new_num_children=atoi(r->v.cstr);
1100 }
1101 // type_changed="false" is the default
1102 }
1103 r=r->next;
1104 }
1105 if (n)
1106 {/* Add to the list*/
1107 if (last)
1108 last->next=n;
1109 else
1110 *changed=n;
1111 last=n;
1112 count++;
1113 }
1114 }
1115 mi_free_results(res);
1116
1117 return count;
1118}
1119
1120int mi_get_children(mi_results *ch, mi_gvar *v)
1121{
1122 mi_gvar *cur=NULL, *aux;
1123 int i=0, count=v->numchild, l;
1124
1125 while (ch)
1126 {
1127 if (strcmp(ch->var,"child")==0 && ch->type==t_tuple && i<count)
1128 {
1129 mi_results *r=ch->v.rs;
1130 aux=mi_alloc_gvar();
1131 if (!aux)
1132 return 0;
1133 if (!v->child)
1134 v->child=aux;
1135 else if (NULL != cur)
1136 cur->next=aux;
1137 cur=aux;
1138 cur->parent=v;
1139 cur->depth=v->depth+1;
1140
1141 while (r)
1142 {
1143 if (r->type==t_const)
1144 {
1145 if (strcmp(r->var,"name")==0)
1146 {
1147 cur->name=r->v.cstr;
1148 r->v.cstr=NULL;
1149 }
1150 else if (strcmp(r->var,"exp")==0)
1151 {
1152 cur->exp=r->v.cstr;
1153 r->v.cstr=NULL;
1154 }
1155 else if (strcmp(r->var,"type")==0)
1156 {
1157 cur->type=r->v.cstr;
1158 r->v.cstr=NULL;
1159 l=strlen(cur->type);
1160 if (l && cur->type[l-1]=='*')
1161 cur->ispointer=1;
1162 }
1163 else if (strcmp(r->var,"value")==0)
1164 {
1165 cur->value=r->v.cstr;
1166 r->v.cstr=NULL;
1167 }
1168 else if (strcmp(r->var,"numchild")==0)
1169 {
1170 cur->numchild=atoi(r->v.cstr);
1171 }
1172 }
1173 r=r->next;
1174 }
1175 i++;
1176 }
1177 ch=ch->next;
1178 }
1179 v->vischild=i;
1180 v->opened=1;
1181 return i==v->numchild;
1182}
1183
1184int mi_res_children(mi_h *h, mi_gvar *v)
1185{
1186 mi_output *r, *res;
1187 int ok=0;
1188
1189 r=mi_get_response_blk(h);
1190 res=mi_get_rrecord(r);
1191 if (res && res->tclass==MI_CL_DONE)
1192 {
1193 mi_results *num=mi_get_var(res,"numchild");
1194 if (num && num->type==t_const)
1195 {
1196 v->numchild=atoi(num->v.cstr);
1197 if (v->child)
1198 {
1199 mi_free_gvar(v->child);
1200 v->child=NULL;
1201 }
1202 if (v->numchild)
1203 {
1204 mi_results *ch =mi_get_var(res,"children");
1205 if (ch && ch->type!=t_const) /* MI v1 tuple, MI v2 list */
1206 ok=mi_get_children(ch->v.rs,v);
1207 }
1208 else
1209 ok=1;
1210 }
1211 }
1212 mi_free_output(r);
1213 return ok;
1214}
1215
1216mi_bkpt *mi_get_bkpt(mi_results *p)
1217{
1218 mi_bkpt *res;
1219 char *end;
1220
1221 res=mi_alloc_bkpt();
1222 if (!res)
1223 return NULL;
1224 while (p)
1225 {
1226 if (p->type==t_const && p->var)
1227 {
1228 if (strcmp(p->var,"number")==0)
1229 res->number=atoi(p->v.cstr);
1230 else if (strcmp(p->var,"type")==0)
1231 {
1232 if (strcmp(p->v.cstr,"breakpoint")==0)
1233 res->type=t_breakpoint;
1234 else
1235 res->type=t_unknown;
1236 }
1237 else if (strcmp(p->var,"disp")==0)
1238 {
1239 if (strcmp(p->v.cstr,"keep")==0)
1240 res->disp=d_keep;
1241 else if (strcmp(p->v.cstr,"del")==0)
1242 res->disp=d_del;
1243 else
1244 res->disp=d_unknown;
1245 }
1246 else if (strcmp(p->var,"enabled")==0)
1247 res->enabled=p->v.cstr[0]=='y';
1248 else if (strcmp(p->var,"addr")==0)
1249 res->addr=(void *)strtoul(p->v.cstr,&end,0);
1250 else if (strcmp(p->var,"func")==0)
1251 {
1252 res->func=p->v.cstr;
1253 p->v.cstr=NULL;
1254 }
1255 else if (strcmp(p->var,"file")==0)
1256 {
1257 res->file=p->v.cstr;
1258 p->v.cstr=NULL;
1259 }
1260 else if (strcmp(p->var,"line")==0)
1261 res->line=atoi(p->v.cstr);
1262 else if (strcmp(p->var,"times")==0)
1263 res->times=atoi(p->v.cstr);
1264 else if (strcmp(p->var,"ignore")==0)
1265 res->ignore=atoi(p->v.cstr);
1266 else if (strcmp(p->var,"cond")==0)
1267 {
1268 res->cond=p->v.cstr;
1269 p->v.cstr=NULL;
1270 }
1271 }
1272 p=p->next;
1273 }
1274 return res;
1275}
1276
1277mi_bkpt *mi_res_bkpt(mi_h *h)
1278{
1279 mi_results *r=mi_res_done_var(h,"bkpt");
1280 mi_bkpt *b=NULL;
1281
1282 if (r && r->type==t_tuple)
1283 b=mi_get_bkpt(r->v.rs);
1284 mi_free_results(r);
1285 return b;
1286}
1287
1288mi_wp *mi_get_wp(mi_results *p, enum mi_wp_mode m)
1289{
1290 mi_wp *res=mi_alloc_wp();
1291
1292 if (res)
1293 {
1294 res->mode=m;
1295 while (p)
1296 {
1297 if (p->type==t_const && p->var)
1298 {
1299 if (strcmp(p->var,"number")==0)
1300 {
1301 res->number=atoi(p->v.cstr);
1302 res->enabled=1;
1303 }
1304 else if (strcmp(p->var,"exp")==0)
1305 {
1306 res->exp=p->v.cstr;
1307 p->v.cstr=NULL;
1308 }
1309 }
1310 p=p->next;
1311 }
1312 }
1313 return res;
1314}
1315
1316mi_wp *mi_parse_wp_res(mi_output *r)
1317{
1318 mi_results *p;
1319 enum mi_wp_mode m=wm_unknown;
1320
1321 /* The info is in a result wpt=... */
1322 p=r->c;
1323 while (p)
1324 {
1325 if (p->var)
1326 {
1327 if (strcmp(p->var,"wpt")==0)
1328 m=wm_write;
1329 else if (strcmp(p->var,"hw-rwpt")==0)
1330 m=wm_read;
1331 else if (strcmp(p->var,"hw-awpt")==0)
1332 m=wm_rw;
1333 if (m!=wm_unknown)
1334 break;
1335 }
1336 p=p->next;
1337 }
1338 if (!p || p->type!=t_tuple)
1339 return NULL;
1340 /* Scan the values inside it. */
1341 return mi_get_wp(p->v.rs,m);
1342}
1343
1344mi_wp *mi_res_wp(mi_h *h)
1345{
1346 mi_output *r, *res;
1347 mi_wp *ret=NULL;
1348
1349 r=mi_get_response_blk(h);
1350 res=mi_get_rrecord(r);
1351
1352 if (res)
1353 ret=mi_parse_wp_res(res);
1354
1355 mi_free_output(r);
1356 return ret;
1357}
1358
1359char *mi_res_value(mi_h *h)
1360{
1361 mi_results *r=mi_res_done_var(h,"value");
1362 char *s=NULL;
1363
1364 if (r && r->type==t_const)
1365 {
1366 s=r->v.cstr;
1367 r->v.rs=NULL;
1368 }
1369 mi_free_results(r);
1370 return s;
1371}
1372
1373mi_output *mi_get_stop_record(mi_output *r)
1374{
1375 while (r)
1376 {
1377 if (r->type==MI_T_OUT_OF_BAND && r->stype==MI_ST_ASYNC &&
1378 r->sstype==MI_SST_EXEC && r->tclass==MI_CL_STOPPED)
1379 return r;
1380 r=r->next;
1381 }
1382 return r;
1383}
1384
1385static
1386char *reason_names[]=
1387{
1388 "breakpoint-hit",
1389 "watchpoint-trigger",
1390 "read-watchpoint-trigger",
1391 "access-watchpoint-trigger",
1392 "watchpoint-scope",
1393 "function-finished",
1394 "location-reached",
1395 "end-stepping-range",
1396 "exited-signalled",
1397 "exited",
1398 "exited-normally",
1399 "signal-received"
1400};
1401
1402static
1403enum mi_stop_reason reason_values[]=
1404{
1405 sr_bkpt_hit,
1406 sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
1407 sr_function_finished, sr_location_reached, sr_end_stepping_range,
1408 sr_exited_signalled, sr_exited, sr_exited_normally,
1409 sr_signal_received
1410};
1411
1412static
1413char *reason_expl[]=
1414{
1415 "Hit a breakpoint",
1416 "Write watchpoint",
1417 "Read watchpoint",
1418 "Access watchpoint",
1419 "Watchpoint out of scope",
1420 "Function finished",
1421 "Location reached",
1422 "End of stepping",
1423 "Exited signalled",
1424 "Exited with error",
1425 "Exited normally",
1426 "Signal received"
1427};
1428
1429enum mi_stop_reason mi_reason_str_to_enum(const char *s)
1430{
1431 int i;
1432
1433 for (i=0; i<sizeof(reason_names)/sizeof(char *); i++)
1434 if (strcmp(reason_names[i],s)==0)
1435 return reason_values[i];
1436 return sr_unknown;
1437}
1438
1439const char *mi_reason_enum_to_str(enum mi_stop_reason r)
1440{
1441 int i;
1442
1443 if (r==sr_unknown)
1444 return "Unknown (temp bkp?)";
1445 for (i=0; i<sizeof(reason_values)/sizeof(char *); i++)
1446 if (reason_values[i]==r)
1447 return reason_expl[i];
1448 return NULL;
1449}
1450
1451mi_stop *mi_get_stopped(mi_results *r)
1452{
1453 mi_stop *res=mi_alloc_stop();
1454
1455 if (res)
1456 {
1457 while (r)
1458 {
1459 if (r->type==t_const)
1460 {
1461 if (strcmp(r->var,"reason")==0)
1462 res->reason=mi_reason_str_to_enum(r->v.cstr);
1463 else if (!res->have_thread_id && strcmp(r->var,"thread-id")==0)
1464 {
1465 res->have_thread_id=1;
1466 res->thread_id=atoi(r->v.cstr);
1467 }
1468 else if (!res->have_bkptno && strcmp(r->var,"bkptno")==0)
1469 {
1470 res->have_bkptno=1;
1471 res->bkptno=atoi(r->v.cstr);
1472 }
1473 else if (!res->have_bkptno && strcmp(r->var,"wpnum")==0)
1474 {
1475 res->have_wpno=1;
1476 res->wpno=atoi(r->v.cstr);
1477 }
1478 else if (strcmp(r->var,"gdb-result-var")==0)
1479 {
1480 res->gdb_result_var=r->v.cstr;
1481 r->v.cstr=NULL;
1482 }
1483 else if (strcmp(r->var,"return-value")==0)
1484 {
1485 res->return_value=r->v.cstr;
1486 r->v.cstr=NULL;
1487 }
1488 else if (strcmp(r->var,"signal-name")==0)
1489 {
1490 res->signal_name=r->v.cstr;
1491 r->v.cstr=NULL;
1492 }
1493 else if (strcmp(r->var,"signal-meaning")==0)
1494 {
1495 res->signal_meaning=r->v.cstr;
1496 r->v.cstr=NULL;
1497 }
1498 else if (!res->have_exit_code && strcmp(r->var,"exit-code")==0)
1499 {
1500 res->have_exit_code=1;
1501 res->exit_code=atoi(r->v.cstr);
1502 }
1503 }
1504 else // tuple or list
1505 {
1506 if (strcmp(r->var,"frame")==0)
1507 res->frame=mi_parse_frame(r->v.rs);
1508 else if (!res->wp && strcmp(r->var,"wpt")==0)
1509 res->wp=mi_get_wp(r->v.rs,wm_write);
1510 else if (!res->wp && strcmp(r->var,"hw-rwpt")==0)
1511 res->wp=mi_get_wp(r->v.rs,wm_read);
1512 else if (!res->wp && strcmp(r->var,"hw-awpt")==0)
1513 res->wp=mi_get_wp(r->v.rs,wm_rw);
1514 else if (!(res->wp_old || res->wp_val) && strcmp(r->var,"value")==0)
1515 {
1516 mi_results *p=r->v.rs;
1517 while (p)
1518 {
1519 if (strcmp(p->var,"value")==0 || strcmp(p->var,"new")==0)
1520 {
1521 res->wp_val=p->v.cstr;
1522 p->v.cstr=NULL;
1523 }
1524 else if (strcmp(p->var,"old")==0)
1525 {
1526 res->wp_old=p->v.cstr;
1527 p->v.cstr=NULL;
1528 }
1529 p=p->next;
1530 }
1531 }
1532 }
1533 r=r->next;
1534 }
1535 }
1536 return res;
1537}
1538
1539mi_stop *mi_res_stop(mi_h *h)
1540{
1541 mi_output *o=mi_retire_response(h);
1542 mi_stop *stop=NULL;
1543
1544 if (o)
1545 {
1546 mi_output *sr=mi_get_stop_record(o);
1547 if (sr)
1548 stop=mi_get_stopped(sr->c);
1549 }
1550 mi_free_output(o);
1551
1552 return stop;
1553}
1554
1555int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
1556 unsigned long *addr)
1557{
1558 char *end;
1559 mi_results *res=mi_res_done_var(h,"memory"), *r;
1560 int ok=0;
1561
1562 *na=0;
1563 r=res;
1564 if (r && r->type==t_list && ws==1)
1565 {
1566 r=r->v.rs;
1567 if (r->type!=t_tuple)
1568 {
1569 mi_free_results(res);
1570 return 0;
1571 }
1572 r=r->v.rs;
1573 while (r)
1574 {
1575 if (r->type==t_list && strcmp(r->var,"data")==0)
1576 {
1577 mi_results *data=r->v.rs;
1578 ok++;
1579 if (data && data->type==t_const &&
1580 strcmp(data->v.cstr,"N/A")==0)
1581 *na=1;
1582 else
1583 while (data)
1584 {
1585 if (data->type==t_const)
1586 *(dest++)=strtol(data->v.cstr,&end,0);
1587 data=data->next;
1588 }
1589 }
1590 else if (r->type==t_const && strcmp(r->var,"addr")==0)
1591 {
1592 ok++;
1593 if (addr)
1594 *addr=strtoul(r->v.cstr,&end,0);
1595 }
1596 r=r->next;
1597 }
1598
1599 }
1600 mi_free_results(res);
1601 return ok==2;
1602}
1603
1604mi_asm_insn *mi_parse_insn(mi_results *c)
1605{
1606 mi_asm_insn *res=NULL, *cur=NULL;
1607 mi_results *sub;
1608 char *end;
1609
1610 while (c)
1611 {
1612 if (c->type==t_tuple)
1613 {
1614 if (!res)
1615 res=cur=mi_alloc_asm_insn();
1616 else
1617 {
1618 cur->next=mi_alloc_asm_insn();
1619 cur=cur->next;
1620 }
1621 if (!cur)
1622 {
1623 mi_free_asm_insn(res);
1624 return NULL;
1625 }
1626 sub=c->v.rs;
1627 while (sub)
1628 {
1629 if (sub->type==t_const)
1630 {
1631 if (strcmp(sub->var,"address")==0)
1632 cur->addr=(void *)strtoul(sub->v.cstr,&end,0);
1633 else if (strcmp(sub->var,"func-name")==0)
1634 {
1635 cur->func=sub->v.cstr;
1636 sub->v.cstr=NULL;
1637 }
1638 else if (strcmp(sub->var,"offset")==0)
1639 cur->offset=atoi(sub->v.cstr);
1640 else if (strcmp(sub->var,"inst")==0)
1641 {
1642 cur->inst=sub->v.cstr;
1643 sub->v.cstr=NULL;
1644 }
1645 }
1646 sub=sub->next;
1647 }
1648 }
1649 c=c->next;
1650 }
1651 return res;
1652}
1653
1654mi_asm_insns *mi_parse_insns(mi_results *c)
1655{
1656 mi_asm_insns *res=NULL, *cur=NULL;
1657 mi_results *sub;
1658
1659 while (c)
1660 {
1661 if (c->var)
1662 {
1663 if (strcmp(c->var,"src_and_asm_line")==0 && c->type==t_tuple)
1664 {
1665 if (!res)
1666 res=cur=mi_alloc_asm_insns();
1667 else
1668 {
1669 cur->next=mi_alloc_asm_insns();
1670 cur=cur->next;
1671 }
1672 if (!cur)
1673 {
1674 mi_free_asm_insns(res);
1675 return NULL;
1676 }
1677 sub=c->v.rs;
1678 while (sub)
1679 {
1680 if (sub->var)
1681 {
1682 if (sub->type==t_const)
1683 {
1684 if (strcmp(sub->var,"line")==0)
1685 cur->line=atoi(sub->v.cstr);
1686 else if (strcmp(sub->var,"file")==0)
1687 {
1688 cur->file=sub->v.cstr;
1689 sub->v.cstr=NULL;
1690 }
1691 }
1692 else if (sub->type==t_list)
1693 {
1694 if (strcmp(sub->var,"line_asm_insn")==0)
1695 cur->ins=mi_parse_insn(sub->v.rs);
1696 }
1697 }
1698 sub=sub->next;
1699 }
1700 }
1701 }
1702 else
1703 {/* No source line, just instructions */
1704 res=mi_alloc_asm_insns();
1705 res->ins=mi_parse_insn(c);
1706 break;
1707 }
1708 c=c->next;
1709 }
1710 return res;
1711}
1712
1713
1714mi_asm_insns *mi_get_asm_insns(mi_h *h)
1715{
1716 mi_results *r=mi_res_done_var(h,"asm_insns");
1717 mi_asm_insns *f=NULL;
1718
1719 if (r && r->type==t_list)
1720 f=mi_parse_insns(r->v.rs);
1721 mi_free_results(r);
1722 return f;
1723}
1724
1725mi_chg_reg *mi_parse_list_regs(mi_results *r, int *how_many)
1726{
1727 mi_results *c=r;
1728 int cregs=0;
1729 mi_chg_reg *first=NULL, *cur=NULL;
1730
1731 /* Create the list. */
1732 while (c)
1733 {
1734 if (c->type==t_const && !c->var)
1735 {
1736 if (first)
1737 cur=cur->next=mi_alloc_chg_reg();
1738 else
1739 first=cur=mi_alloc_chg_reg();
1740
1741 if (NULL != cur) {
1742 cur->name=c->v.cstr;
1743 cur->reg=cregs++;
1744 c->v.cstr=NULL;
1745 }
1746 }
1747 c=c->next;
1748 }
1749 if (how_many)
1750 *how_many=cregs;
1751
1752 return first;
1753}
1754
1755mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many)
1756{
1757 mi_results *r=mi_res_done_var(h,"register-names");
1758 mi_chg_reg *l=NULL;
1759
1760 if (r && r->type==t_list)
1761 l=mi_parse_list_regs(r->v.rs,how_many);
1762 mi_free_results(r);
1763 return l;
1764}
1765
1766mi_chg_reg *mi_parse_list_changed_regs(mi_results *r)
1767{
1768 mi_results *c=r;
1769 mi_chg_reg *first=NULL, *cur=NULL;
1770
1771 /* Create the list. */
1772 while (c)
1773 {
1774 if (c->type==t_const && !c->var)
1775 {
1776 if (first)
1777 cur=cur->next=mi_alloc_chg_reg();
1778 else
1779 first=cur=mi_alloc_chg_reg();
1780 cur->reg=atoi(c->v.cstr);
1781 }
1782 c=c->next;
1783 }
1784
1785 return first;
1786}
1787
1788mi_chg_reg *mi_get_list_changed_regs(mi_h *h)
1789{
1790 mi_results *r=mi_res_done_var(h,"changed-registers");
1791 mi_chg_reg *changed=NULL;
1792
1793 if (r && r->type==t_list)
1794 changed=mi_parse_list_changed_regs(r->v.rs);
1795 mi_free_results(r);
1796 return changed;
1797}
1798
1799int mi_parse_reg_values(mi_results *r, mi_chg_reg *l)
1800{
1801 mi_results *c;
1802
1803 while (r && l)
1804 {
1805 if (r->type==t_tuple && !r->var)
1806 {
1807 c=r->v.rs;
1808 while (c)
1809 {
1810 if (c->type==t_const && c->var)
1811 {
1812 if (strcmp(c->var,"number")==0)
1813 {
1814 if (atoi(c->v.cstr)!=l->reg)
1815 {
1816 mi_error=MI_PARSER;
1817 return 0;
1818 }
1819 }
1820 else if (strcmp(c->var,"value")==0)
1821 {
1822 l->val=c->v.cstr;
1823 c->v.cstr=NULL;
1824 }
1825 }
1826 c=c->next;
1827 }
1828 }
1829 r=r->next;
1830 l=l->next;
1831 }
1832
1833 return !l && !r;
1834}
1835
1836int mi_get_reg_values(mi_h *h, mi_chg_reg *l)
1837{
1838 mi_results *r=mi_res_done_var(h,"register-values");
1839 int ok=0;
1840
1841 if (r && r->type==t_list)
1842 ok=mi_parse_reg_values(r->v.rs,l);
1843 mi_free_results(r);
1844 return ok;
1845}
1846
1847int mi_parse_list_regs_l(mi_results *r, mi_chg_reg *l)
1848{
1849 while (r && l)
1850 {
1851 if (r->type==t_const && !r->var)
1852 {
1853 free(l->name);
1854 l->name=r->v.cstr;
1855 r->v.cstr=NULL;
1856 l=l->next;
1857 }
1858 r=r->next;
1859 }
1860
1861 return !l && !r;
1862}
1863
1864int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l)
1865{
1866 mi_results *r=mi_res_done_var(h,"register-names");
1867 int ok=0;
1868
1869 if (r && r->type==t_list)
1870 ok=mi_parse_list_regs_l(r->v.rs,l);
1871 mi_free_results(r);
1872 return ok;
1873}
1874
1875mi_chg_reg *mi_parse_reg_values_l(mi_results *r, int *how_many)
1876{
1877 mi_results *c;
1878 mi_chg_reg *first=NULL, *cur=NULL;
1879 *how_many=0;
1880
1881 while (r)
1882 {
1883 if (r->type==t_tuple && !r->var)
1884 {
1885 c=r->v.rs;
1886 if (first)
1887 cur=cur->next=mi_alloc_chg_reg();
1888 else
1889 first=cur=mi_alloc_chg_reg();
1890 while (c)
1891 {
1892 if (c->type==t_const && c->var)
1893 {
1894 if (strcmp(c->var,"number")==0)
1895 {
1896 if (NULL != cur)
1897 cur->reg=atoi(c->v.cstr);
1898 (*how_many)++;
1899 }
1900 else if (strcmp(c->var,"value")==0)
1901 {
1902 if (NULL != cur)
1903 cur->val=c->v.cstr;
1904 c->v.cstr=NULL;
1905 }
1906 }
1907 c=c->next;
1908 }
1909 }
1910 r=r->next;
1911 }
1912
1913 return first;
1914}
1915
1916mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many)
1917{
1918 mi_results *r=mi_res_done_var(h,"register-values");
1919 mi_chg_reg *rgs=NULL;
1920
1921 if (r && r->type==t_list)
1922 rgs=mi_parse_reg_values_l(r->v.rs,how_many);
1923 mi_free_results(r);
1924 return rgs;
1925}
1926
1927
diff --git a/src/monkey/gdbmi_prg_control.c b/src/monkey/gdbmi_prg_control.c
deleted file mode 100644
index da37dac21..000000000
--- a/src/monkey/gdbmi_prg_control.c
+++ /dev/null
@@ -1,454 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Program control.
7 Comments:
8 GDB/MI commands for the "Program Control" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12
13-exec-abort N.A. (*) (kill, but with non-interactive options)
14-exec-arguments Yes
15-exec-continue Yes ASYNC
16-exec-finish Yes ASYNC
17-exec-interrupt Yes ASYNC
18-exec-next Yes ASYNC
19-exec-next-instruction Yes ASYNC
20-exec-return Yes
21-exec-run Yes ASYNC
22-exec-show-arguments N.A. (show args) see gmi_stack_info_frame
23-exec-step Yes ASYNC
24-exec-step-instruction Yes ASYNC
25-exec-until Yes ASYNC
26-file-exec-and-symbols Yes
27-file-exec-file No
28-file-list-exec-sections N.A. (info file)
29-file-list-exec-source-files N.A.
30-file-list-shared-libraries N.A.
31-file-list-symbol-files N.A.
32-file-symbol-file Yes
33@</pre>
34
35(*) gmi_exec_kill implements it, but you should ensure that
36gmi_gdb_set("confirm","off") was called. @<p>
37
38GDB Bug workaround for -file-exec-and-symbols and -file-symbol-file: This
39is complex, but a real bug. When you set a breakpoint you never know the
40name of the file as it appears in the debug info. So you can be specifying
41an absolute file name or a relative file name. The reference point could be
42different than the one used in the debug info. To solve all the combinations
43gdb does a search trying various combinations. GDB isn't very smart so you
44must at least specify the working directory and the directory where the
45binary is located to get a good chance (+ user options to solve the rest).
46Once you did it gdb can find the file by doing transformations to the
47"canonical" filename. This search works OK for already loaded symtabs
48(symbol tables), but it have a bug when the search is done for psymtabs
49(partial symtabs). The bug is in the use of source_full_path_of (source.c).
50This function calls openp indicating try_cwd_first. It makes the search file
51if the psymtab file name have at least one dirseparator. It means that
52psymtabs for files compiled with relative paths will fail. The search for
53symtabs uses symtab_to_filename, it calls open_source_file which finally
54calls openp without try_cwd_first.@*
55To workaround this bug we must ensure gdb loads *all* the symtabs to memory.
56And here comes another problem -file-exec-and-symbols doesn't support it
57according to docs. In real life that's a wrapper for "file", but as nobody
58can say it won't change we must use the CLI command.
59
60***************************************************************************/
61
62#include <signal.h>
63#include "gdbmi.h"
64
65/* Low level versions. */
66
67void mi_file_exec_and_symbols(mi_h *h, const char *file)
68{
69 if (mi_get_workaround(MI_PSYM_SEARCH))
70 mi_send(h,"file %s -readnow\n",file);
71 else
72 mi_send(h,"-file-exec-and-symbols %s\n",file);
73}
74
75void mi_exec_arguments(mi_h *h, const char *args)
76{
77 mi_send(h,"-exec-arguments %s\n",args);
78}
79
80void mi_exec_run(mi_h *h)
81{
82 mi_send(h,"-exec-run\n");
83}
84
85void mi_exec_continue(mi_h *h)
86{
87 mi_send(h,"-exec-continue\n");
88}
89
90void mi_target_terminal(mi_h *h, const char *tty_name)
91{
92 mi_send(h,"tty %s\n",tty_name);
93}
94
95void mi_file_symbol_file(mi_h *h, const char *file)
96{
97 if (mi_get_workaround(MI_PSYM_SEARCH))
98 mi_send(h,"symbol-file %s -readnow\n",file);
99 else
100 mi_send(h,"-file-symbol-file %s\n",file);
101}
102
103void mi_exec_finish(mi_h *h)
104{
105 mi_send(h,"-exec-finish\n");
106}
107
108void mi_exec_interrupt(mi_h *h)
109{
110 mi_send(h,"-exec-interrupt\n");
111}
112
113void mi_exec_next(mi_h *h, int count)
114{
115 if (count>1)
116 mi_send(h,"-exec-next %d\n",count);
117 else
118 mi_send(h,"-exec-next\n");
119}
120
121void mi_exec_next_instruction(mi_h *h)
122{
123 mi_send(h,"-exec-next-instruction\n");
124}
125
126void mi_exec_step(mi_h *h, int count)
127{
128 if (count>1)
129 mi_send(h,"-exec-step %d\n",count);
130 else
131 mi_send(h,"-exec-step\n");
132}
133
134void mi_exec_step_instruction(mi_h *h)
135{
136 mi_send(h,"-exec-step-instruction\n");
137}
138
139void mi_exec_until(mi_h *h, const char *file, int line)
140{
141 if (!file)
142 mi_send(h,"-exec-until\n");
143 else
144 mi_send(h,"-exec-until %s:%d\n",file,line);
145}
146
147void mi_exec_until_addr(mi_h *h, void *addr)
148{
149 mi_send(h,"-exec-until *%p\n",addr);
150}
151
152void mi_exec_return(mi_h *h)
153{
154 mi_send(h,"-exec-return\n");
155}
156
157void mi_exec_kill(mi_h *h)
158{
159 mi_send(h,"kill\n");
160}
161
162/* High level versions. */
163
164/**[txh]********************************************************************
165
166 Description:
167 Specify the executable and arguments for local debug.
168
169 Command: -file-exec-and-symbols + -exec-arguments
170 Return: !=0 OK
171
172***************************************************************************/
173
174int gmi_set_exec(mi_h *h, const char *file, const char *args)
175{
176 mi_file_exec_and_symbols(h,file);
177 if (!mi_res_simple_done(h))
178 return 0;
179 if (!args)
180 return 1;
181 mi_exec_arguments(h,args);
182 return mi_res_simple_done(h);
183}
184
185/**[txh]********************************************************************
186
187 Description:
188 Start running the executable. Remote sessions starts running.
189
190 Command: -exec-run
191 Return: !=0 OK
192
193***************************************************************************/
194
195int gmi_exec_run(mi_h *h)
196{
197 mi_exec_run(h);
198 return mi_res_simple_running(h);
199}
200
201/**[txh]********************************************************************
202
203 Description:
204 Continue the execution after a "stop".
205
206 Command: -exec-continue
207 Return: !=0 OK
208
209***************************************************************************/
210
211int gmi_exec_continue(mi_h *h)
212{
213 mi_exec_continue(h);
214 return mi_res_simple_running(h);
215}
216
217/**[txh]********************************************************************
218
219 Description:
220 Indicate which terminal will use the target program. For local sessions.
221
222 Command: tty
223 Return: !=0 OK
224 Example:
225
226***************************************************************************/
227
228int gmi_target_terminal(mi_h *h, const char *tty_name)
229{
230 mi_target_terminal(h,tty_name);
231 return mi_res_simple_done(h);
232}
233
234/**[txh]********************************************************************
235
236 Description:
237 Specify what's the local copy that have debug info. For remote sessions.
238
239 Command: -file-symbol-file
240 Return: !=0 OK
241
242***************************************************************************/
243
244int gmi_file_symbol_file(mi_h *h, const char *file)
245{
246 mi_file_symbol_file(h,file);
247 return mi_res_simple_done(h);
248}
249
250/**[txh]********************************************************************
251
252 Description:
253 Continue until function return, the return value is included in the async
254response.
255
256 Command: -exec-finish
257 Return: !=0 OK.
258
259***************************************************************************/
260
261int gmi_exec_finish(mi_h *h)
262{
263 mi_exec_finish(h);
264 return mi_res_simple_running(h);
265}
266
267/**[txh]********************************************************************
268
269 Description:
270 Stop the program using SIGINT. The corresponding command should be
271-exec-interrupt but not even gdb 6.1.1 can do it because the "async" mode
272isn't really working.
273
274 Command: -exec-interrupt [replacement]
275 Return: Always 1
276 Example:
277
278***************************************************************************/
279
280int gmi_exec_interrupt(mi_h *h)
281{
282 // **** IMPORTANT!!! **** Not even gdb 6.1.1 can do it because the "async"
283 // mode isn't really working.
284 //mi_exec_interrupt(h);
285 //return mi_res_simple_running(h);
286
287 kill(h->pid,SIGINT);
288 return 1; // How can I know?
289}
290
291/**[txh]********************************************************************
292
293 Description:
294 Next line of code.
295
296 Command: -exec-next
297 Return: !=0 OK
298
299***************************************************************************/
300
301int gmi_exec_next(mi_h *h)
302{
303 mi_exec_next(h,1);
304 return mi_res_simple_running(h);
305}
306
307/**[txh]********************************************************************
308
309 Description:
310 Skip count lines of code.
311
312 Command: -exec-next count
313 Return: !=0 OK
314
315***************************************************************************/
316
317int gmi_exec_next_cnt(mi_h *h, int count)
318{
319 mi_exec_next(h,count);
320 return mi_res_simple_running(h);
321}
322
323/**[txh]********************************************************************
324
325 Description:
326 Next line of assembler code.
327
328 Command: -exec-next-instruction
329 Return: !=0 OK
330
331***************************************************************************/
332
333int gmi_exec_next_instruction(mi_h *h)
334{
335 mi_exec_next_instruction(h);
336 return mi_res_simple_running(h);
337}
338
339/**[txh]********************************************************************
340
341 Description:
342 Next line of code. Get inside functions.
343
344 Command: -exec-step
345 Return: !=0 OK
346
347***************************************************************************/
348
349int gmi_exec_step(mi_h *h)
350{
351 mi_exec_step(h,1);
352 return mi_res_simple_running(h);
353}
354
355/**[txh]********************************************************************
356
357 Description:
358 Next count lines of code. Get inside functions.
359
360 Command: -exec-step count
361 Return: !=0 OK
362
363***************************************************************************/
364
365int gmi_exec_step_cnt(mi_h *h, int count)
366{
367 mi_exec_step(h,count);
368 return mi_res_simple_running(h);
369}
370
371/**[txh]********************************************************************
372
373 Description:
374 Next line of assembler code. Get inside calls.
375
376 Command: -exec-step-instruction
377 Return: !=0 OK
378
379***************************************************************************/
380
381int gmi_exec_step_instruction(mi_h *h)
382{
383 mi_exec_step_instruction(h);
384 return mi_res_simple_running(h);
385}
386
387/**[txh]********************************************************************
388
389 Description:
390 Execute until location is reached. If file is NULL then is until next
391line.
392
393 Command: -exec-until
394 Return: !=0 OK
395
396***************************************************************************/
397
398int gmi_exec_until(mi_h *h, const char *file, int line)
399{
400 mi_exec_until(h,file,line);
401 return mi_res_simple_running(h);
402}
403
404/**[txh]********************************************************************
405
406 Description:
407 Execute until location is reached.
408
409 Command: -exec-until (using *address)
410 Return: !=0 OK
411
412***************************************************************************/
413
414int gmi_exec_until_addr(mi_h *h, void *addr)
415{
416 mi_exec_until_addr(h,addr);
417 return mi_res_simple_running(h);
418}
419
420/**[txh]********************************************************************
421
422 Description:
423 Return to previous frame inmediatly.
424
425 Command: -exec-return
426 Return: A pointer to a new mi_frames structure indicating the current
427location. NULL on error.
428
429***************************************************************************/
430
431mi_frames *gmi_exec_return(mi_h *h)
432{
433 mi_exec_return(h);
434 return mi_res_frame(h);
435}
436
437/**[txh]********************************************************************
438
439 Description:
440 Just kill the program. That's what -exec-abort should do, but it isn't
441implemented by gdb. This implementation only works if the interactive mode
442is disabled (gmi_gdb_set("confirm","off")).
443
444 Command: -exec-abort [using kill]
445 Return: !=0 OK
446
447***************************************************************************/
448
449int gmi_exec_kill(mi_h *h)
450{
451 mi_exec_kill(h);
452 return mi_res_simple_done(h);
453}
454
diff --git a/src/monkey/gdbmi_stack_man.c b/src/monkey/gdbmi_stack_man.c
deleted file mode 100644
index 977ea5e2e..000000000
--- a/src/monkey/gdbmi_stack_man.c
+++ /dev/null
@@ -1,222 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Stack manipulation.
7 Comments:
8 GDB/MI commands for the "Stack Manipulation" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12
13-stack-info-frame Yes, implemented as "frame"
14-stack-info-depth Yes
15-stack-list-arguments Yes
16-stack-list-frames Yes
17-stack-list-locals Yes
18-stack-select-frame Yes
19@</pre>
20
21***************************************************************************/
22
23#include "gdbmi.h"
24
25/* Low level versions. */
26
27void mi_stack_list_frames(mi_h *h, int from, int to)
28{
29 if (from<0)
30 mi_send(h,"-stack-list-frames\n");
31 else
32 mi_send(h,"-stack-list-frames %d %d\n",from,to);
33}
34
35void mi_stack_list_arguments(mi_h *h, int show, int from, int to)
36{
37 if (from<0)
38 mi_send(h,"-stack-list-arguments %d\n",show);
39 else
40 mi_send(h,"-stack-list-arguments %d %d %d\n",show,from,to);
41}
42
43void mi_stack_info_frame(mi_h *h)
44{
45 mi_send(h,"frame\n");
46}
47
48void mi_stack_info_depth(mi_h *h, int depth)
49{
50 if (depth<0)
51 mi_send(h,"-stack-info-depth\n");
52 else
53 mi_send(h,"-stack-info-depth %d\n",depth);
54}
55
56void mi_stack_select_frame(mi_h *h, int framenum)
57{
58 mi_send(h,"-stack-select-frame %d\n",framenum);
59}
60
61void mi_stack_list_locals(mi_h *h, int show)
62{
63 mi_send(h,"-stack-list-locals %d\n",show);
64}
65
66/* High level versions. */
67
68/**[txh]********************************************************************
69
70 Description:
71 List of frames. Arguments aren't filled.
72
73 Command: -stack-list-frames
74 Return: A new list of mi_frames or NULL on error.
75
76***************************************************************************/
77
78mi_frames *gmi_stack_list_frames(mi_h *h)
79{
80 mi_stack_list_frames(h,-1,-1);
81 return mi_res_frames_array(h,"stack");
82}
83
84/**[txh]********************************************************************
85
86 Description:
87 List of frames. Arguments aren't filled. Only the frames in the from
88 - to range are returned.
89
90 Command: -stack-list-frames
91 Return: A new list of mi_frames or NULL on error.
92
93***************************************************************************/
94
95mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to)
96{
97 mi_stack_list_frames(h,from,to);
98 return mi_res_frames_array(h,"stack");
99}
100
101/**[txh]********************************************************************
102
103 Description:
104 List arguments. Only level and args filled.
105
106 Command: -stack-list-arguments
107 Return: A new list of mi_frames or NULL on error.
108
109***************************************************************************/
110
111mi_frames *gmi_stack_list_arguments(mi_h *h, int show)
112{
113 mi_stack_list_arguments(h,show,-1,-1);
114 return mi_res_frames_array(h,"stack-args");
115}
116
117/**[txh]********************************************************************
118
119 Description:
120 List arguments. Only level and args filled. Only for the
121frames in the from - to range.
122
123 Command: -stack-list-arguments
124 Return: A new list of mi_frames or NULL on error.
125
126***************************************************************************/
127
128mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to)
129{
130 mi_stack_list_arguments(h,show,from,to);
131 return mi_res_frames_array(h,"stack-args");
132}
133
134/**[txh]********************************************************************
135
136 Description:
137 Information about the current frame, including args.
138
139 Command: -stack-info-frame [using frame]
140 Return: A new mi_frames or NULL on error.
141
142***************************************************************************/
143
144mi_frames *gmi_stack_info_frame(mi_h *h)
145{
146 mi_stack_info_frame(h);
147 return mi_res_frame(h);
148}
149
150/**[txh]********************************************************************
151
152 Description:
153 Stack info depth.
154
155 Command: -stack-info-depth
156 Return: The depth or -1 on error.
157
158***************************************************************************/
159
160int gmi_stack_info_depth(mi_h *h, int max_depth)
161{
162 mi_results *r;
163 int ret=-1;
164
165 mi_stack_info_depth(h,max_depth);
166 r=mi_res_done_var(h,"depth");
167 if (r && r->type==t_const)
168 {
169 ret=atoi(r->v.cstr);
170 mi_free_results(r);
171 }
172 return ret;
173}
174
175/**[txh]********************************************************************
176
177 Description:
178 Set stack info depth.
179
180 Command: -stack-info-depth [no args]
181 Return: The depth or -1 on error.
182 Example:
183
184***************************************************************************/
185
186int gmi_stack_info_depth_get(mi_h *h)
187{
188 return gmi_stack_info_depth(h,-1);
189}
190
191/**[txh]********************************************************************
192
193 Description:
194 Change current frame.
195
196 Command: -stack-select-frame
197 Return: !=0 OK
198
199***************************************************************************/
200
201int gmi_stack_select_frame(mi_h *h, int framenum)
202{
203 mi_stack_select_frame(h,framenum);
204 return mi_res_simple_done(h);
205}
206
207/**[txh]********************************************************************
208
209 Description:
210 List of local vars.
211
212 Command: -stack-list-locals
213 Return: A new mi_results tree containing the variables or NULL on error.
214
215***************************************************************************/
216
217mi_results *gmi_stack_list_locals(mi_h *h, int show)
218{
219 mi_stack_list_locals(h,show);
220 return mi_res_done_var(h,"locals");
221}
222
diff --git a/src/monkey/gdbmi_symbol_query.c b/src/monkey/gdbmi_symbol_query.c
deleted file mode 100644
index 891051771..000000000
--- a/src/monkey/gdbmi_symbol_query.c
+++ /dev/null
@@ -1,32 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Symbol query.
7 Comments:
8 GDB/MI commands for the "Symbol Query" section.@p
9
10@<pre>
11gdb command: Implemented?
12-symbol-info-address N.A. (info address, human readable)
13-symbol-info-file N.A.
14-symbol-info-function N.A.
15-symbol-info-line N.A. (info line, human readable)
16-symbol-info-symbol N.A. (info symbol, human readable)
17-symbol-list-functions N.A. (info functions, human readable)
18-symbol-list-types N.A. (info types, human readable)
19-symbol-list-variables N.A. (info variables, human readable)
20-symbol-list-lines No (gdb 6.x)
21-symbol-locate N.A.
22-symbol-type N.A. (ptype, human readable)
23@</pre>
24
25Note:@p
26
27Only one is implemented and not in gdb 5.x.@p
28
29***************************************************************************/
30
31#include "gdbmi.h"
32
diff --git a/src/monkey/gdbmi_target_man.c b/src/monkey/gdbmi_target_man.c
deleted file mode 100644
index bbb2b9807..000000000
--- a/src/monkey/gdbmi_target_man.c
+++ /dev/null
@@ -1,119 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004-2007 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Target manipulation.
7 Comments:
8 GDB/MI commands for the "Target Manipulation" section. @<p>
9
10@<pre>
11-target-attach Yes (implemented using attach)
12-target-compare-sections N.A. (compare-sections)
13-target-detach Yes
14-target-download Yes
15-target-exec-status N.A.
16-target-list-available-targets N.A. (help target)
17-target-list-current-targets N.A. (info file among other things)
18-target-list-parameters N.A.
19-target-select Yes
20@</pre>
21
22***************************************************************************/
23
24#include "gdbmi.h"
25
26/* Low level versions. */
27
28void mi_target_select(mi_h *h, const char *type, const char *params)
29{
30 mi_send(h,"-target-select %s %s\n",type,params);
31}
32
33/* Note: -target-attach isn't currently implemented :-( (gdb 6.1.1) */
34void mi_target_attach(mi_h *h, pid_t pid)
35{
36 mi_send(h,"attach %d\n",pid);
37}
38
39void mi_target_detach(mi_h *h)
40{
41 mi_send(h,"-target-detach\n");
42}
43
44void mi_target_download(mi_h *h)
45{
46 mi_send(h,"-target-download\n");
47}
48
49/* High level versions. */
50
51/**[txh]********************************************************************
52
53 Description:
54 Connect to a remote gdbserver using the specified methode.
55
56 Command: -target-select
57 Return: !=0 OK
58
59***************************************************************************/
60
61int gmi_target_select(mi_h *h, const char *type, const char *params)
62{
63 mi_target_select(h,type,params);
64 if (!mi_res_simple_connected(h))
65 return 0;
66 mi_send_target_commands(h);
67 return 1;
68}
69
70/**[txh]********************************************************************
71
72 Description:
73 Attach to an already running process.
74
75 Command: -target-attach [using attach]
76 Return: The frame of the current location, NULL on error.
77
78***************************************************************************/
79
80mi_frames *gmi_target_attach(mi_h *h, pid_t pid)
81{
82 mi_target_attach(h,pid);
83 //return mi_res_simple_done(h);
84 return mi_res_frame(h);
85}
86
87/**[txh]********************************************************************
88
89 Description:
90 Detach from an attached process.
91
92 Command: -target-detach
93 Return: !=0 OK
94
95***************************************************************************/
96
97int gmi_target_detach(mi_h *h)
98{
99 mi_target_detach(h);
100 return mi_res_simple_done(h);
101}
102
103/**[txh]********************************************************************
104
105 Description:
106 Loads the executable onto the remote target.
107
108 Command: -target-download
109 Return: !=0 OK
110
111***************************************************************************/
112
113int gmi_target_download(mi_h *h)
114{
115 mi_target_download(h);
116 // TODO: this response have some data
117 return mi_res_simple_done(h);
118}
119
diff --git a/src/monkey/gdbmi_thread.c b/src/monkey/gdbmi_thread.c
deleted file mode 100644
index b8fa63d90..000000000
--- a/src/monkey/gdbmi_thread.c
+++ /dev/null
@@ -1,89 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Thread commands.
7 Comments:
8 GDB/MI commands for the "Thread Commands" section. @<p>
9
10@<pre>
11gdb command: Implemented?
12-thread-info N.A.
13-thread-list-all-threads Yes, implemented as "info threads"
14-thread-list-ids Yes
15-thread-select Yes
16@</pre>
17
18***************************************************************************/
19
20#include "gdbmi.h"
21
22/* Low level versions. */
23
24void mi_thread_list_ids(mi_h *h)
25{
26 mi_send(h,"-thread-list-ids\n");
27}
28
29void mi_thread_select(mi_h *h, int id)
30{
31 mi_send(h,"-thread-select %d\n",id);
32}
33
34void mi_thread_list_all_threads(mi_h *h)
35{
36 mi_send(h,"info threads\n");
37}
38
39/* High level versions. */
40
41/**[txh]********************************************************************
42
43 Description:
44 List available thread ids.
45
46 Command: -thread-list-ids
47 Return: !=0 OK
48
49***************************************************************************/
50
51int gmi_thread_list_ids(mi_h *h, int **list)
52{
53 mi_thread_list_ids(h);
54 return mi_res_thread_ids(h,list);
55}
56
57/**[txh]********************************************************************
58
59 Description:
60 Select a thread.
61
62 Command: -thread-select
63 Return: A new mi_frames or NULL on error.
64
65***************************************************************************/
66
67mi_frames *gmi_thread_select(mi_h *h, int id)
68{
69 mi_thread_select(h,id);
70 return mi_res_frame(h);
71}
72
73/**[txh]********************************************************************
74
75 Description:
76 Get a list of frames for each available thread. Implemented using "info
77thread".
78
79 Command: -thread-list-all-threads
80 Return: A kist of frames, NULL on error
81
82***************************************************************************/
83
84mi_frames *gmi_thread_list_all_threads(mi_h *h)
85{
86 mi_thread_list_all_threads(h);
87 return mi_res_frames_list(h);
88}
89
diff --git a/src/monkey/gdbmi_var_obj.c b/src/monkey/gdbmi_var_obj.c
deleted file mode 100644
index 435feecb7..000000000
--- a/src/monkey/gdbmi_var_obj.c
+++ /dev/null
@@ -1,371 +0,0 @@
1/**[txh]********************************************************************
2
3 Copyright (c) 2004 by Salvador E. Tropea.
4 Covered by the GPL license.
5
6 Module: Variable objects.
7 Comments:
8 GDB/MI commands for the "Variable Objects" section.
9 @<p>
10
11@<pre>
12gdb command: Imp? Description:
13-var-create Yes create a variable object
14-var-delete Yes delete the variable object and its children
15-var-set-format Yes set the display format of this variable
16-var-show-format Yes show the display format of this variable
17-var-info-num-children Yes tells how many children this object has
18-var-list-children Yes* return a list of the object's children
19-var-info-type Yes show the type of this variable object
20-var-info-expression Yes print what this variable object represents
21-var-show-attributes Yes is this variable editable?
22-var-evaluate-expression Yes get the value of this variable
23-var-assign Yes set the value of this variable
24-var-update Yes* update the variable and its children
25@</pre>
26
27Notes: @<p>
281) I suggest letting gdb to choose the names for the variables.@*
292) -var-list-children supports an optional "show values" argument in MI v2.
30It isn't implemented.@*
31
32 @<p>
33
34* MI v1 and v2 result formats supported. @<p>
35
36***************************************************************************/
37
38#include "gdbmi.h"
39
40/* Low level versions. */
41
42void mi_var_create(mi_h *h, const char *name, int frame, const char *exp)
43{
44 const char *n=name ? name : "-";
45
46 if (frame<0)
47 mi_send(h,"-var-create %s * %s\n",n,exp);
48 else
49 mi_send(h,"-var-create %s %d %s\n",n,frame,exp);
50}
51
52void mi_var_delete(mi_h *h, const char *name)
53{
54 mi_send(h,"-var-delete %s\n",name);
55}
56
57void mi_var_set_format(mi_h *h, const char *name, const char *format)
58{
59 mi_send(h,"-var-set-format \"%s\" %s\n",name,format);
60}
61
62void mi_var_show_format(mi_h *h, const char *name)
63{
64 mi_send(h,"-var-show-format \"%s\"\n",name);
65}
66
67void mi_var_info_num_children(mi_h *h, const char *name)
68{
69 mi_send(h,"-var-info-num-children \"%s\"\n",name);
70}
71
72void mi_var_info_type(mi_h *h, const char *name)
73{
74 mi_send(h,"-var-info-type \"%s\"\n",name);
75}
76
77void mi_var_info_expression(mi_h *h, const char *name)
78{
79 mi_send(h,"-var-info-expression \"%s\"\n",name);
80}
81
82void mi_var_show_attributes(mi_h *h, const char *name)
83{
84 mi_send(h,"-var-show-attributes \"%s\"\n",name);
85}
86
87void mi_var_update(mi_h *h, const char *name)
88{
89 if (name)
90 mi_send(h,"-var-update %s\n",name);
91 else
92 mi_send(h,"-var-update *\n");
93}
94
95void mi_var_assign(mi_h *h, const char *name, const char *expression)
96{
97 mi_send(h,"-var-assign \"%s\" \"%s\"\n",name,expression);
98}
99
100void mi_var_evaluate_expression(mi_h *h, const char *name)
101{
102 mi_send(h,"-var-evaluate-expression \"%s\"\n",name);
103}
104
105void mi_var_list_children(mi_h *h, const char *name)
106{
107 if (h->version>=MI_VERSION2U(2,0,0))
108 mi_send(h,"-var-list-children --all-values \"%s\"\n",name);
109 else
110 mi_send(h,"-var-list-children \"%s\"\n",name);
111}
112
113/* High level versions. */
114
115/**[txh]********************************************************************
116
117 Description:
118 Create a variable object. I recommend using gmi_var_create and letting
119gdb choose the names.
120
121 Command: -var-create
122 Return: A new mi_gvar strcture or NULL on error.
123
124***************************************************************************/
125
126mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp)
127{
128 mi_var_create(h,name,frame,exp);
129 return mi_res_gvar(h,NULL,exp);
130}
131
132/**[txh]********************************************************************
133
134 Description:
135 Create a variable object. The name is selected by gdb. Alternative:
136 gmi_full_var_create.
137
138 Command: -var-create [auto name]
139 Return: A new mi_gvar strcture or NULL on error.
140
141***************************************************************************/
142
143mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp)
144{
145 return gmi_var_create_nm(h,NULL,frame,exp);
146}
147
148/**[txh]********************************************************************
149
150 Description:
151 Delete a variable object. Doesn't free the mi_gvar data.
152
153 Command: -var-delete
154 Return: !=0 OK
155
156***************************************************************************/
157
158int gmi_var_delete(mi_h *h, mi_gvar *var)
159{
160 mi_var_delete(h,var->name);
161 return mi_res_simple_done(h);
162}
163
164/**[txh]********************************************************************
165
166 Description:
167 Set the format used to represent the result.
168
169 Command: -var-set-format
170 Return: !=0 OK
171
172***************************************************************************/
173
174int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format)
175{
176 int ret;
177
178 mi_var_set_format(h,var->name,mi_format_enum_to_str(format));
179 ret=mi_res_simple_done(h);
180 if (ret)
181 var->format=format;
182 return ret;
183}
184
185/**[txh]********************************************************************
186
187 Description:
188 Fill the format field with info from gdb.
189
190 Command: -var-show-format
191 Return: !=0 OK.
192
193***************************************************************************/
194
195int gmi_var_show_format(mi_h *h, mi_gvar *var)
196{
197 mi_var_show_format(h,var->name);
198 return mi_res_gvar(h,var,NULL)!=NULL;
199}
200
201/**[txh]********************************************************************
202
203 Description:
204 Fill the numchild field with info from gdb.
205
206 Command: -var-info-num-children
207 Return: !=0 OK
208
209***************************************************************************/
210
211int gmi_var_info_num_children(mi_h *h, mi_gvar *var)
212{
213 mi_var_info_num_children(h,var->name);
214 return mi_res_gvar(h,var,NULL)!=NULL;
215}
216
217/**[txh]********************************************************************
218
219 Description:
220 Fill the type field with info from gdb.
221
222 Command: -var-info-type
223 Return: !=0 OK
224
225***************************************************************************/
226
227int gmi_var_info_type(mi_h *h, mi_gvar *var)
228{
229 mi_var_info_type(h,var->name);
230 return mi_res_gvar(h,var,NULL)!=NULL;
231}
232
233/**[txh]********************************************************************
234
235 Description:
236 Fill the expression and lang fields with info from gdb. Note that lang
237isn't filled during creation.
238
239 Command: -var-info-expression
240 Return: !=0 OK
241
242***************************************************************************/
243
244int gmi_var_info_expression(mi_h *h, mi_gvar *var)
245{
246 mi_var_info_expression(h,var->name);
247 return mi_res_gvar(h,var,NULL)!=NULL;
248}
249
250
251/**[txh]********************************************************************
252
253 Description:
254 Fill the attr field with info from gdb. Note that attr isn't filled
255during creation.
256
257 Command: -var-show-attributes
258 Return: !=0 OK
259
260***************************************************************************/
261
262int gmi_var_show_attributes(mi_h *h, mi_gvar *var)
263{
264 mi_var_show_attributes(h,var->name);
265 return mi_res_gvar(h,var,NULL)!=NULL;
266}
267
268/**[txh]********************************************************************
269
270 Description:
271 Create the variable and also fill the lang and attr fields. The name is
272selected by gdb.
273
274 Command: -var-create + -var-info-expression + -var-show-attributes
275 Return: A new mi_gvar strcture or NULL on error.
276
277***************************************************************************/
278
279mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp)
280{
281 mi_gvar *var=gmi_var_create_nm(h,NULL,frame,exp);
282 if (var)
283 {/* What if it fails? */
284 gmi_var_info_expression(h,var);
285 gmi_var_show_attributes(h,var);
286 }
287 return var;
288}
289
290/**[txh]********************************************************************
291
292 Description:
293 Update variable. Use NULL for all. Note that *changed can be NULL if none
294updated.
295
296 Command: -var-update
297 Return: !=0 OK. The changed list contains the list of changed vars.
298
299***************************************************************************/
300
301int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed)
302{
303 mi_var_update(h,var ? var->name : NULL);
304 return mi_res_changelist(h,changed);
305}
306
307/**[txh]********************************************************************
308
309 Description:
310 Change variable. The new value replaces the value field.
311
312 Command: -var-assign
313 Return: !=0 OK
314
315***************************************************************************/
316
317int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression)
318{
319 char *res;
320 mi_var_assign(h,var->name,expression);
321 res=mi_res_value(h);
322 if (res)
323 {
324 free(var->value);
325 var->value=res;
326 return 1;
327 }
328 return 0;
329}
330
331/**[txh]********************************************************************
332
333 Description:
334 Fill the value field getting the current value for a variable.
335
336 Command: -var-evaluate-expression
337 Return: !=0 OK, value contains the result.
338
339***************************************************************************/
340
341int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var)
342{
343 char *s;
344
345 mi_var_evaluate_expression(h,var->name);
346 s=mi_res_value(h);
347 if (s)
348 {
349 free(var->value);
350 var->value=s;
351 }
352 return s!=NULL;
353}
354
355/**[txh]********************************************************************
356
357 Description:
358 List children. It ONLY returns the first level information. :-(@*
359 On success the child field contains the list of children.
360
361 Command: -var-list-children
362 Return: !=0 OK
363
364***************************************************************************/
365
366int gmi_var_list_children(mi_h *h, mi_gvar *var)
367{
368 mi_var_list_children(h,var->name);
369 return mi_res_children(h,var);
370}
371
diff --git a/src/monkey/gnunet-monkey.c b/src/monkey/gnunet-monkey.c
deleted file mode 100644
index 18d9abf32..000000000
--- a/src/monkey/gnunet-monkey.c
+++ /dev/null
@@ -1,201 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file monkey/gnunet-monkey.c
23 * @brief Monkey: gnunet automated debugging tool
24 */
25
26#include <stdio.h>
27#include "platform.h"
28#include "gnunet_common.h"
29#include "gnunet_getopt_lib.h"
30#include "gnunet_program_lib.h"
31#include "gnunet_monkey_action.h"
32
33static const char *mode;
34static const char *dumpFileName;
35static const char *binaryName;
36static const char *emailAddress;
37static const char *edbFilePath;
38static const char *gdbBinaryPath;
39static const char *inspectExpression;
40static const char *inspectFunction;
41static int ret = 0;
42
43/**
44 * Main function that will launch the action api.
45 *
46 * @param cls closure
47 * @param args remaining command-line arguments
48 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
49 * @param c configuration
50 */
51static void
52run (void *cls,
53 char *const *args,
54 const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
55{
56 int result;
57 struct GNUNET_MONKEY_ACTION_Context *cntxt;
58
59 if (strcasecmp (mode, "email") == 0)
60 {
61 if (NULL == emailAddress)
62 {
63 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
64 "Working in email mode requires an email address!\n");
65 ret = 1;
66 return;
67 }
68 }
69 else if (strcasecmp (mode, "text") == 0)
70 {
71 if (NULL == dumpFileName)
72 {
73 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
74 "Working in text mode requires a path for the dump file!\n");
75 ret = 1;
76 return;
77 }
78 }
79
80 /* Initialize context for the Action API */
81 cntxt = GNUNET_malloc (sizeof (struct GNUNET_MONKEY_ACTION_Context));
82 cntxt->binary_name = binaryName;
83 cntxt->expression_database_path = edbFilePath;
84 cntxt->gdb_binary_path = gdbBinaryPath;
85 cntxt->inspect_expression = inspectExpression;
86 cntxt->inspect_function = inspectFunction;
87
88 result = GNUNET_MONKEY_ACTION_rerun_with_gdb (cntxt);
89 switch (result)
90 {
91 int retVal;
92 case GDB_STATE_ERROR:
93 break;
94 case GDB_STATE_EXIT_NORMALLY:
95 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
96 "Debug with gdb, program exited normally!\n");
97 /*FIXME: Valgrind should be launched here */
98 break;
99 case GDB_STATE_STOPPED:
100 /*FIXME: Expression Database should be inspected here (before writing the report) */
101 retVal = GNUNET_MONKEY_ACTION_inspect_expression_database (cntxt);
102 if (GNUNET_NO == retVal)
103 {
104 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
105 "Error using Expression Database!\n");
106 ret = 1;
107 break;
108 }
109 else if (GDB_STATE_ERROR == retVal)
110 {
111 /* GDB could not locate a NULL value expression, launch Valgrind */
112 retVal = GNUNET_MONKEY_ACTION_rerun_with_valgrind (cntxt);
113 if (GNUNET_NO == retVal)
114 {
115 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error using Valgrind!\n");
116 ret = 1;
117 break;
118 }
119 }
120 if (GNUNET_OK != GNUNET_MONKEY_ACTION_format_report (cntxt))
121 {
122 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
123 "Error in generating debug report!\n");
124 ret = 1;
125 }
126 if (strcasecmp (mode, "email") == 0)
127 {
128 if (GNUNET_OK != GNUNET_MONKEY_ACTION_report_email (cntxt))
129 {
130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error sending email!\n");
131 ret = 1;
132 }
133 }
134 else
135 {
136 /* text mode */
137 if (GNUNET_OK !=
138 GNUNET_MONKEY_ACTION_report_file (cntxt, dumpFileName))
139 {
140 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
141 "Error in saving debug file!\n");
142 ret = 1;
143 }
144 }
145 break;
146 default:
147 break;
148 }
149 GNUNET_MONKEY_ACTION_delete_context(cntxt);
150}
151
152
153int
154main (int argc, char *argv[])
155{
156 static const struct GNUNET_GETOPT_CommandLineOption options[] = {
157 {'m', "mode", NULL,
158 gettext_noop
159 ("monkey's mode of operation: options are \"text\" or \"email\""),
160 GNUNET_YES, &GNUNET_GETOPT_set_string, &mode},
161 {'b', "binary", NULL,
162 gettext_noop ("binary for program to debug with monkey"),
163 GNUNET_YES, &GNUNET_GETOPT_set_string, &binaryName},
164 {'o', "output", NULL,
165 gettext_noop
166 ("path to file to dump monkey's output in case of text mode"),
167 GNUNET_YES, &GNUNET_GETOPT_set_string, &dumpFileName},
168 {'a', "address", NULL,
169 gettext_noop ("address to send email to in case of email mode"),
170 GNUNET_YES, &GNUNET_GETOPT_set_string, &emailAddress},
171 {'d', "database", NULL, gettext_noop ("path to Expression Database file"),
172 GNUNET_YES, &GNUNET_GETOPT_set_string, &edbFilePath},
173 {'g', "gdb", NULL,
174 gettext_noop ("path to gdb binary in use; default is /usr/bin/gdb"),
175 GNUNET_YES, &GNUNET_GETOPT_set_string, &gdbBinaryPath},
176 {'f', "function", NULL, gettext_noop ("Monkey will set a breakpoint on this function"),
177 GNUNET_YES, &GNUNET_GETOPT_set_string, &inspectFunction},
178 {'i', "inspect", NULL, gettext_noop ("An expression to inspect in the function specified after the argument f"),
179 GNUNET_YES, &GNUNET_GETOPT_set_string, &inspectExpression},
180 GNUNET_GETOPT_OPTION_END
181 };
182
183 if (argc < 2)
184 {
185 printf ("%s",
186 "Monkey should take arguments: Use --help to get a list of options.\n");
187 return 1;
188 }
189
190 if (GNUNET_OK == GNUNET_PROGRAM_run (argc,
191 argv,
192 "gnunet-monkey",
193 gettext_noop
194 ("Automatically debug a service"),
195 options, &run, NULL))
196 {
197 return ret;
198 }
199
200 return 1;
201}
diff --git a/src/monkey/gnunet-service-monkey.c b/src/monkey/gnunet-service-monkey.c
deleted file mode 100644
index 7db83833a..000000000
--- a/src/monkey/gnunet-service-monkey.c
+++ /dev/null
@@ -1,6 +0,0 @@
1
2
3int main(int argc, char *argv[])
4{
5 return 0;
6}
diff --git a/src/monkey/gnunet_monkey_action.h b/src/monkey/gnunet_monkey_action.h
deleted file mode 100644
index 7c49525a4..000000000
--- a/src/monkey/gnunet_monkey_action.h
+++ /dev/null
@@ -1,103 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2010, 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/**
22 * @file monkey/gnunet_monkey_action.h
23 * @brief Monkey API for actions taken by Monkey while debugging
24 */
25
26#ifndef GNUNET_MONKEY_ACTION_H
27#define GNUNET_MONKEY_ACTION_H
28
29#include "gdbmi.h"
30
31#ifdef __cplusplus
32extern "C"
33{
34#if 0 /* keep Emacsens' auto-indent happy */
35}
36#endif
37#endif
38
39
40/* Debug constants */
41#define DEBUG_MODE_GDB 0
42#define GDB_STATE_STOPPED 1
43#define GDB_STATE_EXIT_NORMALLY 2
44#define GDB_STATE_ERROR 3
45#define DEBUG_MODE_VALGRIND 4
46#define DEBUG_MODE_REPORT_READY 5
47#define BUG_NULL_POINTER 6
48#define BUG_CUSTOM 7
49
50
51/**
52 * Context for the Action API
53 */
54struct GNUNET_MONKEY_ACTION_Context
55{
56 const char *binary_name;
57 const char *email_address;
58 const char *expression_database_path;
59 const char *gdb_binary_path;
60 const char *inspect_expression;
61 const char *inspect_function;
62 int debug_mode;
63 int bug_detected;
64 char *debug_report;
65
66 /* gdb debugging attributes */
67 mi_h *gdb_handle;
68 const char *gdb_in_use;
69 mi_stop *gdb_stop_reason;
70 mi_frames *gdb_frames;
71 const char *gdb_null_variable;
72
73 /* Valgrind memcheck attributes */
74 char* valgrind_output_tmp_file_name;
75};
76
77
78int GNUNET_MONKEY_ACTION_report_file (struct GNUNET_MONKEY_ACTION_Context
79 *cntxt, const char *dumpFileName);
80int GNUNET_MONKEY_ACTION_report_email (struct GNUNET_MONKEY_ACTION_Context
81 *cntxt);
82int GNUNET_MONKEY_ACTION_inspect_expression_database (struct
83 GNUNET_MONKEY_ACTION_Context
84 *cntxt);
85int GNUNET_MONKEY_ACTION_rerun_with_gdb (struct GNUNET_MONKEY_ACTION_Context
86 *cntxt);
87int GNUNET_MONKEY_ACTION_rerun_with_valgrind (struct
88 GNUNET_MONKEY_ACTION_Context
89 *cntxt);
90int GNUNET_MONKEY_ACTION_format_report (struct GNUNET_MONKEY_ACTION_Context
91 *cntxt);
92int GNUNET_MONKEY_ACTION_delete_context(struct GNUNET_MONKEY_ACTION_Context *cntxt);
93
94int GNUNET_MONKEY_ACTION_check_bug_redundancy (void);
95
96
97#if 0 /* keep Emacsens' auto-indent happy */
98{
99#endif
100#ifdef __cplusplus
101}
102#endif
103#endif
diff --git a/src/monkey/gnunet_monkey_edb.h b/src/monkey/gnunet_monkey_edb.h
deleted file mode 100644
index d3d82f183..000000000
--- a/src/monkey/gnunet_monkey_edb.h
+++ /dev/null
@@ -1,129 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2009, 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/**
22 * @file monkey/gnunet_monkey_edb.h
23 * @brief Monkey API for accessing the Expression Database (edb)
24 */
25
26#ifndef GNUNET_MONKEY_EDB_H
27#define GNUNET_MONKEY_EDB_H
28
29#ifdef __cplusplus
30extern "C"
31{
32#if 0 /* keep Emacsens' auto-indent happy */
33}
34#endif
35#endif
36
37
38struct GNUNET_MONKEY_EDB_Context;
39
40/**
41 * Establish a connection to the Expression Database
42 *
43 * @param db_file_name path the Expression Database file
44 * @return context to use for Accessing the Expression Database, NULL on error
45 */
46struct GNUNET_MONKEY_EDB_Context *GNUNET_MONKEY_EDB_connect (const char
47 *db_file_name);
48
49
50/**
51 * Disconnect from Database, and cleanup resources
52 *
53 * @param context context
54 * @return GNUNET_OK on success, GNUNET_NO on failure
55 */
56int GNUNET_MONKEY_EDB_disconnect (struct GNUNET_MONKEY_EDB_Context *cntxt);
57
58
59typedef int (*GNUNET_MONKEY_ExpressionIterator) (void *, int, char **,
60 char **);
61
62
63
64/**
65 * Return the line number of the end-of-scope for the expression indicated by start_line_no
66 *
67 * @param cntxt context containing the Expression Database handle
68 * @param file_name path to the file in which the expression in question exists
69 * @param start_line_no expression's line
70 * @param iter callback function, iterator for values returned from the Database
71 * @param iter_cls closure for the expression iterator, will contain the scope-end line number
72 * @return GNUNET_OK on success, GNUNET_NO on failure
73 */
74int
75GNUNET_MONKEY_EDB_get_expression_scope_end(struct GNUNET_MONKEY_EDB_Context *cntxt,
76 const char *file_name, int start_line_no,
77 GNUNET_MONKEY_ExpressionIterator iter,
78 void *iter_cls);
79
80
81/**
82 * Run an SQLite query to retrieve those expressions that are previous to
83 * given expression and are in the same scope of the given expression
84 * For example, consider the following code snippet:
85 *
86 * {
87 * struct Something whole; // line no.1
88 * struct SomethingElse part; // line no.2
89 * whole.part = &part; // line no.3
90 * whole.part->member = 1; // line no.4
91 * }
92 *
93 * If the expression supplied to the function is that of line no.4 "whole.part->member = 1;"
94 * The returned list of expressions will be: whole.part (line no.4), whole.part->member (line no.4),
95 * whole (line no.3), whole.part (line no.3), &part (line no.3), whole.part = &part (line no.3)
96 *
97 * @param cntxt context containing the Expression Database handle.
98 * @param file_name path to the file in which the expression in question exists
99 * @param start_line_no expression beginning line
100 * @param end_line_no line number for the expression's scope end
101 * @param iter callback function, iterator for expressions returned from the Database
102 * @param iter_cls closure for the expression iterator
103 * @return GNUNET_OK success, GNUNET_NO failure
104 */
105int
106GNUNET_MONKEY_EDB_get_expressions (struct GNUNET_MONKEY_EDB_Context *cntxt,
107 const char *file_name, int start_line_no,
108 int end_line_no,
109 GNUNET_MONKEY_ExpressionIterator iter,
110 void *iter_cls);
111
112
113int
114GNUNET_MONKEY_EDB_get_sub_expressions (struct GNUNET_MONKEY_EDB_Context *cntxt,
115 const char *file_name, int start_line_no,
116 int end_line_no,
117 GNUNET_MONKEY_ExpressionIterator iter,
118 void *iter_cls);
119
120
121
122#if 0 /* keep Emacsens' auto-indent happy */
123{
124#endif
125#ifdef __cplusplus
126}
127#endif
128
129#endif
diff --git a/src/monkey/mail_sender.c b/src/monkey/mail_sender.c
deleted file mode 100644
index 122a4d0ab..000000000
--- a/src/monkey/mail_sender.c
+++ /dev/null
@@ -1,226 +0,0 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <ctype.h>
4#include <unistd.h>
5#include <getopt.h>
6#include <string.h>
7#include <fcntl.h>
8#include <signal.h>
9#include <errno.h>
10#include <stdarg.h>
11
12#include <openssl/ssl.h>
13#include <auth-client.h>
14#include <libesmtp.h>
15
16#if !defined (__GNUC__) || __GNUC__ < 2
17# define __attribute__(x)
18#endif
19
20
21int
22handle_invalid_peer_certificate(long vfy_result)
23{
24 const char *k ="rare error";
25 switch(vfy_result) {
26 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
27 k="X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"; break;
28 case X509_V_ERR_UNABLE_TO_GET_CRL:
29 k="X509_V_ERR_UNABLE_TO_GET_CRL"; break;
30 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
31 k="X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE"; break;
32 case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
33 k="X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE"; break;
34 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
35 k="X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY"; break;
36 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
37 k="X509_V_ERR_CERT_SIGNATURE_FAILURE"; break;
38 case X509_V_ERR_CRL_SIGNATURE_FAILURE:
39 k="X509_V_ERR_CRL_SIGNATURE_FAILURE"; break;
40 case X509_V_ERR_CERT_NOT_YET_VALID:
41 k="X509_V_ERR_CERT_NOT_YET_VALID"; break;
42 case X509_V_ERR_CERT_HAS_EXPIRED:
43 k="X509_V_ERR_CERT_HAS_EXPIRED"; break;
44 case X509_V_ERR_CRL_NOT_YET_VALID:
45 k="X509_V_ERR_CRL_NOT_YET_VALID"; break;
46 case X509_V_ERR_CRL_HAS_EXPIRED:
47 k="X509_V_ERR_CRL_HAS_EXPIRED"; break;
48 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
49 k="X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"; break;
50 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
51 k="X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"; break;
52 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
53 k="X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD"; break;
54 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
55 k="X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD"; break;
56 case X509_V_ERR_OUT_OF_MEM:
57 k="X509_V_ERR_OUT_OF_MEM"; break;
58 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
59 k="X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT"; break;
60 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
61 k="X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN"; break;
62 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
63 k="X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY"; break;
64 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
65 k="X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE"; break;
66 case X509_V_ERR_CERT_CHAIN_TOO_LONG:
67 k="X509_V_ERR_CERT_CHAIN_TOO_LONG"; break;
68 case X509_V_ERR_CERT_REVOKED:
69 k="X509_V_ERR_CERT_REVOKED"; break;
70 case X509_V_ERR_INVALID_CA:
71 k="X509_V_ERR_INVALID_CA"; break;
72 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
73 k="X509_V_ERR_PATH_LENGTH_EXCEEDED"; break;
74 case X509_V_ERR_INVALID_PURPOSE:
75 k="X509_V_ERR_INVALID_PURPOSE"; break;
76 case X509_V_ERR_CERT_UNTRUSTED:
77 k="X509_V_ERR_CERT_UNTRUSTED"; break;
78 case X509_V_ERR_CERT_REJECTED:
79 k="X509_V_ERR_CERT_REJECTED"; break;
80 }
81 printf("SMTP_EV_INVALID_PEER_CERTIFICATE: %ld: %s\n", vfy_result, k);
82 return 1; /* Accept the problem */
83}
84
85
86void event_cb (smtp_session_t session, int event_no, void *arg,...)
87{
88 va_list alist;
89 int *ok;
90
91 va_start(alist, arg);
92 switch(event_no) {
93 case SMTP_EV_CONNECT:
94 case SMTP_EV_MAILSTATUS:
95 case SMTP_EV_RCPTSTATUS:
96 case SMTP_EV_MESSAGEDATA:
97 case SMTP_EV_MESSAGESENT:
98 case SMTP_EV_DISCONNECT: break;
99 case SMTP_EV_WEAK_CIPHER: {
100 int bits;
101 bits = va_arg(alist, long); ok = va_arg(alist, int*);
102 printf("SMTP_EV_WEAK_CIPHER, bits=%d - accepted.\n", bits);
103 *ok = 1; break;
104 }
105 case SMTP_EV_STARTTLS_OK:
106 puts("SMTP_EV_STARTTLS_OK - TLS started here."); break;
107 case SMTP_EV_INVALID_PEER_CERTIFICATE: {
108 long vfy_result;
109 vfy_result = va_arg(alist, long); ok = va_arg(alist, int*);
110 *ok = handle_invalid_peer_certificate(vfy_result);
111 break;
112 }
113 case SMTP_EV_NO_PEER_CERTIFICATE: {
114 ok = va_arg(alist, int*);
115 puts("SMTP_EV_NO_PEER_CERTIFICATE - accepted.");
116 *ok = 1; break;
117 }
118 case SMTP_EV_WRONG_PEER_CERTIFICATE: {
119 ok = va_arg(alist, int*);
120 puts("SMTP_EV_WRONG_PEER_CERTIFICATE - accepted.");
121 *ok = 1; break;
122 }
123 case SMTP_EV_NO_CLIENT_CERTIFICATE: {
124 ok = va_arg(alist, int*);
125 puts("SMTP_EV_NO_CLIENT_CERTIFICATE - accepted.");
126 *ok = 1; break;
127 }
128 default:
129 printf("Got event: %d - ignored.\n", event_no);
130 }
131 va_end(alist);
132}
133
134
135/* Callback to prnt the recipient status */
136void
137print_recipient_status (smtp_recipient_t recipient,
138 const char *mailbox, void *arg)
139{
140 const smtp_status_t *status;
141
142 status = smtp_recipient_status (recipient);
143 printf ("%s: %d %s", mailbox, status->code, status->text);
144}
145
146
147void sendMail(const char *messageContents, const char *emailAddress)
148{
149 smtp_session_t session;
150 smtp_message_t message;
151 smtp_recipient_t recipient;
152 const smtp_status_t *status;
153 struct sigaction sa;
154 char *host = "localhost:25";
155 char *from = "gnunet-monkey";
156 char *subject = "e-mail from Libesmtp!";
157 const char *recipient_address = emailAddress;
158 char tempFileName[1000];
159 int tempFd;
160 FILE *fp;
161 enum notify_flags notify = Notify_SUCCESS | Notify_FAILURE;
162
163 auth_client_init();
164 session = smtp_create_session();
165 message = smtp_add_message(session);
166
167 /* Ignore sigpipe */
168 sa.sa_handler = SIG_IGN;
169 sigemptyset(&sa.sa_mask);
170 sa.sa_flags = 0;
171 sigaction(SIGPIPE, &sa, NULL);
172
173
174 smtp_set_server(session, host);
175 smtp_set_eventcb(session, event_cb, NULL);
176
177 /* Set the reverse path for the mail envelope. (NULL is ok)
178 */
179 smtp_set_reverse_path(message, from);
180
181 /* Set the Subject: header. For no reason, we want the supplied subject
182 to override any subject line in the message headers. */
183 if (subject != NULL) {
184 smtp_set_header(message, "Subject", subject);
185 smtp_set_header_option(message, "Subject", Hdr_OVERRIDE, 1);
186 }
187
188
189 /* Prepare message */
190 memset(tempFileName, 0, sizeof(tempFileName));
191 sprintf(tempFileName, "/tmp/messageXXXXXX");
192 tempFd = mkstemp(tempFileName);
193 fp = fdopen(tempFd, "w");
194 fprintf(fp, "%s", messageContents);
195 fclose(fp);
196 fp = fopen(tempFileName, "r");
197 smtp_set_message_fp(message, fp);
198
199
200 recipient = smtp_add_recipient(message, recipient_address);
201
202 smtp_dsn_set_notify (recipient, notify);
203
204 /* Initiate a connection to the SMTP server and transfer the
205 message. */
206 if (!smtp_start_session(session)) {
207 char buf[128];
208
209 fprintf(stderr, "SMTP server problem %s\n", smtp_strerror(smtp_errno(),
210 buf, sizeof buf));
211 } else {
212 /* Report on the success or otherwise of the mail transfer.
213 */
214 status = smtp_message_transfer_status(message);
215 printf("%d %s", status->code, (status->text != NULL) ? status->text
216 : "\n");
217 smtp_enumerate_recipients(message, print_recipient_status, NULL);
218 }
219
220 /* Free resources consumed by the program.
221 */
222 smtp_destroy_session(session);
223 fclose(fp);
224 auth_client_exit();
225}
226
diff --git a/src/monkey/seaspider/C.jj b/src/monkey/seaspider/C.jj
deleted file mode 100644
index ebbaece17..000000000
--- a/src/monkey/seaspider/C.jj
+++ /dev/null
@@ -1,587 +0,0 @@
1/*
2
3 C grammar defintion for use with JavaCC
4 Contributed by Doug South (dsouth@squirrel.com.au) 21/3/97
5
6 This parser assumes that the C source file has been preprocessed : all
7 #includes have been included and all macros have been expanded. I accomplish
8 this with "gcc -P -E <source file> > <output file>".
9
10 There is a problem with compiler specific types, such as __signed, __const,
11 __inline__, etc. These types can be added as typedef types before the parser
12 is run on a file. See main() for an example. I have also found a strange little
13 compiler specific "type" if you can call it that. It is __attribute__, but it
14 does not seem to be used as a type. I found that just deleting the __attribute__
15 and the following "offensive" code works.
16
17 This grammar also prints out all the types defined while parsing the file. This
18 is done via a call to printTypes() when the parser is complete. If you do not want
19 this, just comment out the printTypes() method call in the production rule
20 TranslationUnit(), which BTW is the root node for parsing a C source file.
21
22 I have not in anyway extensively tested this grammar, in fact it is barely tested,
23 but I imagine it is better to have a starting point for a C grammar other than from
24 scratch. It has not been optimized in anyway, my main aim was to get a parser that
25 works. Lookahead may not be optimum at choice points and may even be insufficient at
26 times. I choose to err on the side of not optimum if I made a choice at all.
27
28 If you use this grammar, I would appreciate hearing from you. I will try to maintain
29 this grammar to the best of my ability, but at this point in time, this is only a side
30 hobby (unless someone wants to pay me for doing JavaCC work!). In that regards, I am
31 interested in hearing bugs and comments.
32
33 TODO:
34
35 Insert the appropriate code to enable C source trees from this grammar.
36
37=============================================
383/2/06: Modified by Tom Copeland
39- STRING_LITERAL now handles embedded escaped newlines, thanks to J.Chris Findlay for the patch
40- Works with JavaCC 4.0
41- Preprocessor directives are now simply SKIP'd, so no need to run C files through GCC first
42
4331/8/10: Modified heavily by Christian Grothoff
44- No more tracking of type names (so we can run without preprocessing)
45- Support certain gcc-isms (unsigned long long, 33LL, etc.)
46- No support for certain older C constructs
47- Support for magic "GNUNET_PACKED" construct (extra "IDENTIFIER" in struct)
48
498/11/10: Modified some more by Christian Grothoff
50- support for arguments without variable names (in particular, just 'void')
51- support for string concatenations
52*/
53
54PARSER_BEGIN(CParser)
55
56import java.util.*;
57
58 public class CParser{
59
60 // Run the parser
61 public static void main ( String args [ ] ) {
62 CParser parser ;
63
64 if(args.length == 0){
65 System.out.println("C Parser Version 0.1Alpha: Reading from standard input . . .");
66 parser = new CParser(System.in);
67 }
68 else if(args.length == 1){
69 System.out.println("C Parser Version 0.1Alpha: Reading from file " + args[0] + " . . ." );
70 try {
71 parser = new CParser(new java.io.FileInputStream(args[0]));
72 }
73 catch(java.io.FileNotFoundException e){
74 System.out.println("C Parser Version 0.1: File " + args[0] + " not found.");
75 return ;
76 }
77 }
78 else {
79 System.out.println("C Parser Version 0.1Alpha: Usage is one of:");
80 System.out.println(" java CParser < inputfile");
81 System.out.println("OR");
82 System.out.println(" java CParser inputfile");
83 return ;
84 }
85 try {
86 parser.TranslationUnit();
87 System.out.println("C Parser Version 0.1Alpha: Java program parsed successfully.");
88 }
89 catch(ParseException e){
90 System.out.println("C Parser Version 0.1Alpha: Encountered errors during parse.");
91 e.printStackTrace();
92 }
93 }
94 }
95
96PARSER_END(CParser)
97
98SKIP : {
99 " "
100| "\t"
101| "\n"
102| "\r"
103| <"//" (~["\n","\r"])* ("\n" | "\r" | "\r\n")>
104| <"/*" (~["*"])* "*" ("*" | ~["*","/"] (~["*"])* "*")* "/">
105| "#" : PREPROCESSOR_OUTPUT
106}
107
108<PREPROCESSOR_OUTPUT> SKIP:
109{
110 "\n" : DEFAULT
111}
112
113<PREPROCESSOR_OUTPUT> MORE:
114{
115 "\\\n"
116 |
117 "\\\r\n"
118 |
119 < ~[] >
120}
121
122
123TOKEN : {
124 <INTEGER_LITERAL: <DECIMAL_LITERAL> (["l","L"])? (["l","L"])? | <HEX_LITERAL> (["l","L"])? (["l","L"])? | <OCTAL_LITERAL> (["l","L"])? (["l","L"])?>
125| <#DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
126| <#HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+>
127| <#OCTAL_LITERAL: "0" (["0"-"7"])*>
128| <FLOATING_POINT_LITERAL: (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])? | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])? | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])? | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]>
129| <#EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+>
130|
131 < CHARACTER_LITERAL:
132 "'"
133 ( (~["'","\\","\n","\r"])
134 | ("\\"
135 ( ["n","t","b","r","f","\\","'","\""]
136 | ["0"-"7"] ( ["0"-"7"] )?
137 | ["0"-"3"] ["0"-"7"] ["0"-"7"]
138 )
139 )
140 )
141 "'"
142 >
143| < STRING_LITERAL:
144 ("\""
145 ( (~["\"","\\","\n","\r"])
146 | ("\\"
147 ( ["n","t","b","r","f","\\","'","\""]
148 | ["0"-"7"] ( ["0"-"7"] )?
149 | ["0"-"3"] ["0"-"7"] ["0"-"7"]
150 )
151 )
152 )*
153 "\"")+
154 >
155}
156
157TOKEN : {
158 <CONTINUE: "continue"> |
159 <VOLATILE: "volatile"> |
160 <REGISTER: "register"> |
161 <UNSIGNED: "unsigned"> |
162 <TYPEDEF: "typedef"> |
163 <DFLT: "default"> |
164 <DOUBLE: "double"> |
165 <SIZEOF: "sizeof"> |
166 <SWITCH: "switch"> |
167 <RETURN: "return"> |
168 <EXTERN: "extern"> |
169 <STRUCT: "struct"> |
170 <STATIC: "static"> |
171 <SIGNED: "signed"> |
172 <WHILE: "while"> |
173 <BREAK: "break"> |
174 <UNION: "union"> |
175 <CONST: "const"> |
176 <FLOAT: "float"> |
177 <SHORT: "short"> |
178 <ELSE: "else"> |
179 <CASE: "case"> |
180 <LONG: "long"> |
181 <ENUM: "enum"> |
182 <AUTO: "auto"> |
183 <VOID: "void"> |
184 <CHAR: "char"> |
185 <GOTO: "goto"> |
186 <FOR: "for"> |
187 <INT: "int"> |
188 <IF: "if"> |
189 <DO: "do">
190}
191
192TOKEN : {
193 <IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)*>
194| <#LETTER: ["$","A"-"Z","_","a"-"z"]>
195| <#DIGIT: ["0"-"9"]>
196}
197
198void TranslationUnit() : {}
199{
200 (ExternalDeclaration())+
201 <EOF>
202}
203
204void ExternalDeclaration() : {}
205{
206 (StorageClassSpecifier())*
207 (
208 LOOKAHEAD (FunctionDeclaration()) FunctionDeclaration() |
209 LOOKAHEAD (StructOrUnionSpecifier() ";") StructOrUnionSpecifier() ";" |
210 LOOKAHEAD (EnumSpecifier() ";") EnumSpecifier() ";" |
211 LOOKAHEAD (VariableDeclaration()) VariableDeclaration() |
212 LOOKAHEAD (TypeDeclaration()) TypeDeclaration ()
213 )
214}
215
216void FunctionDeclaration() : {}
217{
218 TypeSpecifier ()
219 <IDENTIFIER>
220 "(" [ ParameterList () ] ")"
221 ( ";" | CompoundStatement() )
222}
223
224void StorageClassSpecifier() : {}
225{
226 ( <STATIC> | <EXTERN> )
227}
228
229void TypeDeclaration() : {}
230{
231 <TYPEDEF>
232 ( LOOKAHEAD (DataType() ";") DataType () | FunctionType() ) ";"
233}
234
235void DataType() : {}
236{
237 StructOrUnionSpecifier () <IDENTIFIER>
238}
239
240void FunctionType() : {}
241{
242 TypeSpecifier () "(" "*" <IDENTIFIER> ")" "(" [ ParameterList() ] ")"
243}
244
245void ParameterList() : {}
246{
247 ParameterDeclaration() ( LOOKAHEAD (2) "," ParameterDeclaration() )* [ "," "..." ]
248}
249
250void ParameterDeclaration() : {}
251{
252 TypeSpecifier() [<IDENTIFIER> [ Array () ]]
253}
254
255void VariableDeclaration() : {}
256{
257 VariableClassSpecifier ()
258 TypeSpecifier ()
259 InitDeclaratorList() ";"
260}
261
262void LocalVariableDeclaration() : {}
263{
264 [ <STATIC> ] VariableDeclaration ()
265}
266
267void VariableClassSpecifier() : {}
268{
269 ( <AUTO> | <REGISTER> )*
270}
271
272void TypeSpecifier() : {}
273{
274 [ <CONST> ]
275 ( <VOID>
276 | <CHAR>
277 | <SHORT> [ <INT> ]
278 | <INT>
279 | <LONG> [ <LONG> ]
280 | <FLOAT> | <DOUBLE>
281 | (<SIGNED> | <UNSIGNED>) [ <CHAR>
282 | <SHORT> [ <INT> ]
283 | <INT>
284 | <LONG> [ <LONG> ] ]
285 | StructOrUnionSpecifier()
286 | EnumSpecifier()
287 | <IDENTIFIER>
288 )
289 [ Pointer () ]
290 [ Array () ]
291}
292
293/* this is needed for 'va_arg' where a type is an argument
294 -- and we cannot disambiguate the use of 'FOO'
295 after a 'typedef int FOO' from the variable 'FOO';
296 hence this hack */
297void NoIdentifierTypeSpecifier() : {}
298{
299 [ <CONST> ]
300 ( <VOID>
301 | <CHAR>
302 | <SHORT> [ <INT> ]
303 | <INT>
304 | <LONG> [ <LONG> ]
305 | <FLOAT> | <DOUBLE>
306 | (<SIGNED> | <UNSIGNED>) [ <CHAR>
307 | <SHORT> [ <INT> ]
308 | <INT>
309 | <LONG> [ <LONG> ] ]
310 | StructOrUnionSpecifier()
311 | EnumSpecifier()
312 )
313 [ Pointer () ]
314 [ Array () ]
315}
316
317void StructOrUnionSpecifier() : {}
318{
319 LOOKAHEAD (3)
320 StructOrUnion() [ <IDENTIFIER> ] "{" StructDeclarationList() "}" |
321 StructOrUnion() <IDENTIFIER>
322}
323
324void StructOrUnion() : {}
325{
326 ( <STRUCT> | <UNION> )
327}
328
329void StructDeclarationList() : {}
330{
331 (StructDeclaration())*
332}
333
334void InitDeclaratorList() : {}
335{
336 InitDeclarator() ("," InitDeclarator())*
337}
338
339void InitDeclarator() : {}
340{
341 <IDENTIFIER> [ Array () ] [ "=" Initializer() ]
342}
343
344void StructDeclaration() : {}
345{
346 TypeSpecifier() <IDENTIFIER> [ Array() | ":" ConstantExpression() ] [ <IDENTIFIER> ] ";"
347}
348
349void EnumSpecifier() : {}
350{
351 <ENUM> ( LOOKAHEAD(3) [ <IDENTIFIER> ] "{" EnumeratorList() "}" | <IDENTIFIER> )
352}
353
354void EnumeratorList() : {}
355{
356 Enumerator() ("," Enumerator())*
357}
358
359void Enumerator() : {}
360{
361 <IDENTIFIER> [ "=" ConstantExpression() ]
362}
363
364void Pointer() : {}
365{
366 "*" [ <CONST> ] [ Pointer() ]
367}
368
369void Initializer() : {}
370{
371 ( AssignmentExpression() |
372 "{" InitializerList() [","] "}" )
373}
374
375void InitializerList() : {}
376{
377 Initializer() (LOOKAHEAD(2) "," Initializer())*
378}
379
380
381void Array() : {}
382{
383 ("[" [ConstantExpression()] "]" )+
384}
385
386void Statement() : {}
387{
388 ( LOOKAHEAD(2) LabeledStatement() |
389 ExpressionStatement() |
390 CompoundStatement() |
391 SelectionStatement() |
392 IterationStatement() |
393 JumpStatement() )
394}
395
396void LabeledStatement() : {}
397{
398 ( <IDENTIFIER> ":" Statement() |
399 <CASE> ConstantExpression() ":" Statement() |
400 <DFLT> ":" Statement() )
401}
402
403void ExpressionStatement() : {}
404{
405 [ Expression() ] ";"
406}
407
408void CompoundStatement() : {}
409{
410 "{" ( LOOKAHEAD (LocalVariableDeclaration()) LocalVariableDeclaration () |
411 Statement() )*
412 "}"
413}
414
415void SelectionStatement() : {}
416{
417 ( IfStatement() | SwitchStatement() )
418}
419
420void IfStatement() : {}
421{
422 <IF> "(" Expression() ")" Statement() [ LOOKAHEAD(2) <ELSE> Statement() ]
423}
424
425void SwitchStatement() : {}
426{
427 <SWITCH> "(" Expression() ")" Statement()
428}
429
430void IterationStatement() : {}
431{
432 ( WhileStatement() | DoWhileStatement() | ForStatement() )
433}
434void WhileStatement() : {}
435{
436 <WHILE> "(" Expression() ")" Statement()
437}
438void DoWhileStatement() : {}
439{
440 <DO> Statement() <WHILE> "(" Expression() ")" ";"
441}
442void ForStatement() : {}
443{
444 <FOR> "(" [ Expression() ] ";" [ Expression() ] ";" [ Expression() ] ")" Statement()
445}
446
447void JumpStatement() : {}
448{
449 ( <GOTO> <IDENTIFIER> ";" |
450 <CONTINUE> ";" |
451 <BREAK> ";" |
452 <RETURN> [ Expression() ] ";" )
453}
454
455void Expression() : {}
456{
457 AssignmentExpression() ( "," AssignmentExpression() )*
458}
459
460void AssignmentExpression() : {}
461{
462 LOOKAHEAD(UnaryExpression() AssignmentOperator()) UnaryExpression() AssignmentOperator() AssignmentExpression() |
463 LOOKAHEAD(3) ConditionalExpression()
464}
465
466void AssignmentOperator() : {}
467{
468 ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" )
469}
470
471void ConditionalExpression() : {}
472{
473 LogicalORExpression() [ "?" Expression() ":" ConditionalExpression() ]
474}
475
476void ConstantExpression() : {}
477{
478 ConditionalExpression()
479}
480
481void LogicalORExpression() : {}
482{
483 LogicalANDExpression() [ "||" LogicalORExpression() ]
484}
485
486void LogicalANDExpression() : {}
487{
488 InclusiveORExpression() [ "&&" LogicalANDExpression() ]
489}
490
491void InclusiveORExpression() : {}
492{
493 ExclusiveORExpression() [ "|" InclusiveORExpression() ]
494}
495
496void ExclusiveORExpression() : {}
497{
498 ANDExpression() [ "^" ExclusiveORExpression() ]
499}
500
501void ANDExpression() : {}
502{
503 EqualityExpression() [ "&" ANDExpression() ]
504}
505
506void EqualityExpression() : {}
507{
508 RelationalExpression() [ ( "==" | "!=" ) EqualityExpression() ]
509}
510
511void RelationalExpression() : {}
512{
513 ShiftExpression() [ ( "<" | ">" | "<=" | ">=" ) RelationalExpression() ]
514}
515
516void ShiftExpression() : {}
517{
518 AdditiveExpression() [ ( "<<" | ">>" ) ShiftExpression() ]
519}
520
521void AdditiveExpression() : {}
522{
523 MultiplicativeExpression() [ ( "+" | "-" ) AdditiveExpression() ]
524}
525
526void MultiplicativeExpression() : {}
527{
528 CastExpression() [ ( "*" | "/" | "%" ) MultiplicativeExpression() ]
529}
530
531void CastExpression() : {}
532{
533 ( LOOKAHEAD("(" TypeSpecifier() ")" CastExpression() ) "(" TypeSpecifier() ")" CastExpression() |
534 UnaryExpression() )
535}
536
537void UnaryExpression() : {}
538{
539 ( LOOKAHEAD(3) PostfixExpression() |
540 "++" UnaryExpression() |
541 "--" UnaryExpression() |
542 UnaryOperator() CastExpression() |
543 <SIZEOF> ( LOOKAHEAD(UnaryExpression() ) UnaryExpression() | "(" TypeSpecifier() ")" ) )
544}
545
546void UnaryOperator() : {}
547{
548 ( "&" | "*" | "+" | "-" | "~" | "!" )
549}
550
551void PostfixExpression() : {}
552{
553 PrimaryExpression() ( "[" Expression() "]" |
554 "(" [ LOOKAHEAD(ArgumentExpressionList() ) ArgumentExpressionList() ] ")" |
555 "." <IDENTIFIER> |
556 "->" <IDENTIFIER> |
557 "++" |
558 "--" )*
559}
560
561void PrimaryExpression() : {}
562{
563 <IDENTIFIER> |
564 Constant() |
565 "(" Expression() ")"
566}
567
568void ArgumentExpressionList() : {}
569{
570 AssignmentOrTypeExpression() ( "," AssignmentOrTypeExpression() )*
571}
572
573
574void AssignmentOrTypeExpression() : {}
575{
576 NoIdentifierTypeSpecifier() |
577 AssignmentExpression()
578}
579
580void Constant() : {}
581{
582 <INTEGER_LITERAL> |
583 <FLOATING_POINT_LITERAL> |
584 <CHARACTER_LITERAL> |
585 (<STRING_LITERAL>)+
586}
587
diff --git a/src/monkey/seaspider/Makefile b/src/monkey/seaspider/Makefile
deleted file mode 100755
index 0f7a0b668..000000000
--- a/src/monkey/seaspider/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
1all:
2 jtb C.jj
3 javacc C.out.jj
4 javac -nowarn -classpath ../../../contrib/antlr-runtime-3.1.3.jariantlr-runtime-3.1.3.jarantlr-runtime-3.1.3.jar:../../../contrib/sqljet.1.0.3.b914.jar `find * -name "*.java"`
5 jar -cvf seaspider.jar `find * -name "*.class"`
diff --git a/src/monkey/seaspider/SeaspiderTest.c b/src/monkey/seaspider/SeaspiderTest.c
deleted file mode 100644
index d09eae38f..000000000
--- a/src/monkey/seaspider/SeaspiderTest.c
+++ /dev/null
@@ -1,83 +0,0 @@
1/**
2 * @file src/monkey/seaspider/SeaspiderTest.c
3 * @brief C file to test Seaspider's parsing
4 */
5
6/* include */
7#include <stdio.h>
8
9
10#define PRE_PROC_DIR 0
11#define MACRO_fun(arg1, arg2) (arg1 + arg2)
12
13struct MyStruct {
14 int member;
15 struct MyStruct *part;
16};
17
18
19enum MyEnum{
20 enumMember1,
21 enumMember2,
22 enumMember3
23};
24
25
26static int fun(int arg1, int arg2)
27{
28 return arg1 + arg2;
29}
30
31
32int main(int args, const char * argv[])
33{
34 /* variables declarations */
35 struct MyStruct whole;
36 struct MyStruct part;
37 enum MyEnum myEnum;
38 int i;
39 int x, y;
40
41 /* Allocations and assignments */
42 whole.member = 1;
43 whole.part = &part;
44 whole.part->member = 2;
45 myEnum = enumMember3;
46 x = 0, y = 1;
47
48 /* block */
49 {
50 /* arithmetic and logic operations */
51 float f = 20.0;
52 whole.part->member = (int)(whole.part->member + 5) - 6; // cast - multilevel assignment
53 }
54
55 /* for loop */
56 for (i = 0; i < 2; i++) {
57 /* conditional expressions */
58 if ( x > 0) {
59 while (y < 5) {
60 y++;
61 }
62 } else if (x > 0 || y == 4) {
63 do {
64 y--;
65 } while (y != 1);
66 }
67 else {
68 switch (myEnum) {
69 case enumMember1:
70 fun(enumMember1, enumMember2);
71 break;
72 case enumMember2:
73 fun(enumMember1, enumMember2 ? enumMember2 : enumMember1); // ternary operator
74 break;
75 default:
76 MACRO_fun(enumMember1, PRE_PROC_DIR); // preprocessing directive
77 break;
78 }
79 }
80 }
81
82 return 1;
83}
diff --git a/src/monkey/seaspider/org/gnunet/seaspider/ExpressionDatabaseHandler.java b/src/monkey/seaspider/org/gnunet/seaspider/ExpressionDatabaseHandler.java
deleted file mode 100644
index 1627aca26..000000000
--- a/src/monkey/seaspider/org/gnunet/seaspider/ExpressionDatabaseHandler.java
+++ /dev/null
@@ -1,204 +0,0 @@
1package org.gnunet.seaspider;
2
3import java.io.File;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.Stack;
7import org.tmatesoft.sqljet.core.SqlJetException;
8import org.tmatesoft.sqljet.core.SqlJetTransactionMode;
9import org.tmatesoft.sqljet.core.table.ISqlJetTable;
10import org.tmatesoft.sqljet.core.table.SqlJetDb;
11
12/**
13 * ExpressionDatabaseHandler is fed by expressions from the C code parser, and
14 * inserts them into SQLite Expression database using SQLJet API. Before
15 * inserting an expression into the database, ExpressionDatabaseHandler makes
16 * sure it's not redundant.
17 * For example:
18 * int x = 0;
19 * int y = 1;
20 * int z = x + y // line 3
21 * The parser input for line 3 is: z, x, y, x + y, and z = x + y The
22 * expressions to be committed to the database will be only: z, and z = x + y
23 */
24public class ExpressionDatabaseHandler {
25
26 private static final boolean DEBUG = false;
27
28 private static final boolean PRINT_STACK = false;
29
30 private static SqlJetDb db;
31
32 private static ISqlJetTable table;
33
34 private static String currentFileName = null;
35
36 private static int currentScopeEnd = 0;
37
38 private static Stack<HashMap<String, Integer>> expressionStack = new Stack<HashMap<String, Integer>>();
39
40 public static void createExpressionDatabase(String databasePath) {
41 String createTableQuery = "CREATE TABLE Expression ( expr_ID INTEGER PRIMARY KEY AUTOINCREMENT, "
42 + "file_name TEXT NOT NULL , expr_syntax TEXT NOT NULL ,"
43 + " start_lineno INT, end_lineno INT)";
44
45 File dbFile = new File(databasePath);
46 dbFile.delete();/* Delete it if already existent */
47
48 /* Create Expressions database */
49 try {
50 db = SqlJetDb.open(dbFile, true);
51 db.getOptions().setAutovacuum(true);
52 db.beginTransaction(SqlJetTransactionMode.WRITE);
53 try {
54 db.getOptions().setUserVersion(1);/* Sets the user's cookie */
55 } finally {
56 db.commit();
57 }
58 /* Create table Expression */
59 db.createTable(createTableQuery);
60 db.beginTransaction(SqlJetTransactionMode.WRITE);
61 table = db.getTable("Expression");
62 } catch (SqlJetException e) {
63 e.printStackTrace();
64 }
65 }
66
67 public static void closeDatabase() {
68 try {
69 db.commit();
70 db.close();
71 } catch (SqlJetException e) {
72 e.printStackTrace();
73 }
74 }
75
76 private static void doInsertExpression(String fileName,
77 String expressionSyntax, int startLineNo, int endLineNo) {
78 try {
79 if (DEBUG)
80 System.out.println(fileName + ":[" + startLineNo + "-"
81 + endLineNo + "]: " + expressionSyntax);
82 table.insert(null, currentFileName, expressionSyntax, startLineNo,
83 endLineNo);
84 } catch (SqlJetException e) {
85 e.printStackTrace();
86 }
87 }
88
89 private static boolean isRedundant(String expressionSyntax) {
90 Iterator<HashMap<String, Integer>> itr = expressionStack.iterator();
91 HashMap<String, Integer> scope;
92
93 while (itr.hasNext()) {
94 scope = itr.next();
95 if (null != scope.get(expressionSyntax))
96 return true;
97 }
98
99 return false;
100 }
101
102 private static int getScopeEnd(HashMap<String, Integer> scope) {
103 Iterator<Integer> itr = scope.values().iterator();
104 return itr.next();
105 }
106
107 private static HashMap<String, Integer> pushNewScope(int endLineNo) {
108 HashMap<String, Integer> scope = new HashMap<String, Integer>();
109 currentScopeEnd = endLineNo;
110 expressionStack.push(scope);
111
112 return scope;
113 }
114
115 private static void printExpressionStack(String expressionSyntax,
116 int startLineNo, int endLineNo) {
117 HashMap<String, Integer> hashMap;
118 Iterator<String> itr;
119 System.out.println("Commit call for expression: " + expressionSyntax
120 + " start:" + startLineNo + " end:" + endLineNo);
121 for (int i = 0; i < expressionStack.size(); i++) {
122 hashMap = expressionStack.get(i);
123 itr = hashMap.keySet().iterator();
124 System.out.println("Printing expressions of scope " + i + ":");
125 while (itr.hasNext()) {
126 System.out.println(itr.next());
127 }
128 }
129 System.out.println("");
130 }
131
132 private static void insertExpression(String fileName,
133 String expressionSyntax, int startLineNo, int endLineNo) {
134
135 HashMap<String, Integer> currentScopeExpressions = null;
136
137 if (PRINT_STACK)
138 printExpressionStack(expressionSyntax, startLineNo, endLineNo);
139
140 if (null == currentFileName || !currentFileName.equals(fileName)) {
141 /* First time, or new file */
142 currentFileName = fileName;
143 if (!expressionStack.empty())
144 expressionStack.clear();
145 currentScopeExpressions = pushNewScope(endLineNo);
146 } else {
147 if (endLineNo > currentScopeEnd) {
148 /*
149 * We are either in a new function or back to an outer scope
150 */
151 expressionStack.pop();
152 if (expressionStack.empty()) {
153 /* We are in a new function */
154 currentScopeExpressions = pushNewScope(endLineNo);
155 } else {
156 /* We just left an inner scope to an outer one */
157 currentScopeExpressions = expressionStack.lastElement();
158 currentScopeEnd = getScopeEnd(currentScopeExpressions);
159 if (isRedundant(expressionSyntax))
160 return;
161 }
162 } else {
163 /* Either we delved into a sub-scope or we are in the same scope */
164 if (isRedundant(expressionSyntax))
165 return;
166 if (endLineNo == currentScopeEnd) // same scope
167 currentScopeExpressions = expressionStack.lastElement();
168 else
169 // new sub-scope
170 currentScopeExpressions = pushNewScope(endLineNo);
171 }
172 }
173
174 /* Add the new expression */
175 currentScopeExpressions.put(expressionSyntax, endLineNo);
176 doInsertExpression(fileName, expressionSyntax, startLineNo, endLineNo);
177 }
178
179 /**
180 * Inserts expression into the Expression Database
181 *
182 * @param fileName source file the expression comes from
183 * @param expressionSyntax string of the expression
184 * @param startLineNo line number of the expression
185 * @param endLineNo end line of the expression scope
186 */
187 public static void insertIntoExpressionTable(String fileName,
188 String expressionSyntax, int startLineNo, int endLineNo) {
189 if (expressionSyntax.matches("[0-9]*"))
190 return;
191 if (expressionSyntax.startsWith("\""))
192 return;
193 if (db == null) {
194 System.out
195 .println("Error:Database handle is not initialized. Program will exit now!");
196 System.exit(1);
197 }
198
199 String[] fileNameArr = fileName.split("src/");
200 if (fileNameArr.length > 1)
201 fileName = fileNameArr[1];
202 insertExpression(fileName, expressionSyntax, startLineNo, endLineNo);
203 }
204}
diff --git a/src/monkey/seaspider/org/gnunet/seaspider/ExpressionExtractorVisitor.java b/src/monkey/seaspider/org/gnunet/seaspider/ExpressionExtractorVisitor.java
deleted file mode 100644
index fdad3f697..000000000
--- a/src/monkey/seaspider/org/gnunet/seaspider/ExpressionExtractorVisitor.java
+++ /dev/null
@@ -1,713 +0,0 @@
1package org.gnunet.seaspider;
2
3import org.gnunet.seaspider.parser.nodes.ANDExpression;
4import org.gnunet.seaspider.parser.nodes.AdditiveExpression;
5import org.gnunet.seaspider.parser.nodes.ArgumentExpressionList;
6import org.gnunet.seaspider.parser.nodes.AssignmentExpression;
7import org.gnunet.seaspider.parser.nodes.AssignmentOperator;
8import org.gnunet.seaspider.parser.nodes.CastExpression;
9import org.gnunet.seaspider.parser.nodes.CompoundStatement;
10import org.gnunet.seaspider.parser.nodes.ConditionalExpression;
11import org.gnunet.seaspider.parser.nodes.ConstantExpression;
12import org.gnunet.seaspider.parser.nodes.DoWhileStatement;
13import org.gnunet.seaspider.parser.nodes.EqualityExpression;
14import org.gnunet.seaspider.parser.nodes.ExclusiveORExpression;
15import org.gnunet.seaspider.parser.nodes.Expression;
16import org.gnunet.seaspider.parser.nodes.ExpressionStatement;
17import org.gnunet.seaspider.parser.nodes.ForStatement;
18import org.gnunet.seaspider.parser.nodes.FunctionDeclaration;
19import org.gnunet.seaspider.parser.nodes.IfStatement;
20import org.gnunet.seaspider.parser.nodes.InclusiveORExpression;
21import org.gnunet.seaspider.parser.nodes.InitDeclarator;
22import org.gnunet.seaspider.parser.nodes.InitDeclaratorList;
23import org.gnunet.seaspider.parser.nodes.Initializer;
24import org.gnunet.seaspider.parser.nodes.InitializerList;
25import org.gnunet.seaspider.parser.nodes.JumpStatement;
26import org.gnunet.seaspider.parser.nodes.LogicalANDExpression;
27import org.gnunet.seaspider.parser.nodes.LogicalORExpression;
28import org.gnunet.seaspider.parser.nodes.MultiplicativeExpression;
29import org.gnunet.seaspider.parser.nodes.Node;
30import org.gnunet.seaspider.parser.nodes.NodeChoice;
31import org.gnunet.seaspider.parser.nodes.NodeSequence;
32import org.gnunet.seaspider.parser.nodes.NodeToken;
33import org.gnunet.seaspider.parser.nodes.ParameterDeclaration;
34import org.gnunet.seaspider.parser.nodes.PostfixExpression;
35import org.gnunet.seaspider.parser.nodes.PrimaryExpression;
36import org.gnunet.seaspider.parser.nodes.RelationalExpression;
37import org.gnunet.seaspider.parser.nodes.ShiftExpression;
38import org.gnunet.seaspider.parser.nodes.StructOrUnionSpecifier;
39import org.gnunet.seaspider.parser.nodes.SwitchStatement;
40import org.gnunet.seaspider.parser.nodes.TranslationUnit;
41import org.gnunet.seaspider.parser.nodes.TypeDeclaration;
42import org.gnunet.seaspider.parser.nodes.UnaryExpression;
43import org.gnunet.seaspider.parser.nodes.UnaryOperator;
44import org.gnunet.seaspider.parser.nodes.VariableDeclaration;
45import org.gnunet.seaspider.parser.nodes.WhileStatement;
46import org.gnunet.seaspider.parser.visitors.DepthFirstVisitor;
47import org.grothoff.LineNumberInfo;
48
49/**
50 * @author grothoff
51 *
52 */
53public class ExpressionExtractorVisitor extends DepthFirstVisitor {
54
55 class ExpressionBuilder {
56 String expression = "";
57
58 void push(String token) {
59 expression = expression + token;
60 }
61
62 void commit(int line) {
63 ExpressionDatabaseHandler.insertIntoExpressionTable(filename,
64 expression, line, scope_end_line);
65 }
66
67 }
68
69 final String filename;
70
71 ExpressionBuilder current_expression;
72
73 int scope_end_line;
74
75 boolean operator;
76
77 boolean skip_mode = true;
78
79 /**
80 *
81 */
82 public ExpressionExtractorVisitor(String filename) {
83 this.filename = filename;
84 }
85
86 public void visit(TranslationUnit n) {
87 LineNumberInfo lin = LineNumberInfo.get(n);
88 scope_end_line = lin.lineEnd;
89 n.f0.accept(this);
90 assert scope_end_line == lin.lineEnd;
91 }
92
93 public void visit(NodeToken n) {
94 if (skip_mode)
95 return;
96 current_expression.push(n.tokenImage);
97 }
98
99 public void visit(StructOrUnionSpecifier n) {
100 // do nothing -- skip!
101 }
102
103 public void visit(TypeDeclaration n) {
104 // do nothing -- skip!
105 }
106
107 public void visit(InitDeclaratorList n) {
108 assert skip_mode == true;
109 super.visit(n);
110 assert skip_mode == true;
111 }
112
113 public void visit(Initializer n) {
114 assert skip_mode == true;
115 if (n.f0.which == 0) {
116 boolean old_mode = skip_mode;
117 skip_mode = false;
118 ExpressionBuilder old = current_expression;
119 current_expression = new ExpressionBuilder();
120 n.f0.accept(this);
121 LineNumberInfo lin = LineNumberInfo.get(n);
122 if (old != null) {
123 old.push(current_expression.expression);
124 old.commit(lin.lineEnd);
125 } else {
126 current_expression.commit(lin.lineEnd);
127 }
128 current_expression = old;
129 skip_mode = old_mode;
130 } else {
131 super.visit(n);
132 }
133 assert skip_mode == true;
134 }
135
136 public void visit(InitializerList n) {
137 assert skip_mode == true;
138 super.visit(n);
139 assert skip_mode == true;
140 }
141
142 public void visit(VariableDeclaration n) {
143 assert skip_mode == true;
144 super.visit(n);
145 }
146
147 public void visit(FunctionDeclaration n) {
148 if (n.f5.which == 0)
149 return; // no body
150 int old_scope = scope_end_line;
151 LineNumberInfo lin = LineNumberInfo.get(n);
152 scope_end_line = lin.lineEnd;
153 n.f3.accept(this);
154 n.f5.accept(this);
155 assert scope_end_line == lin.lineEnd;
156 scope_end_line = old_scope;
157 }
158
159 public void visit(ParameterDeclaration n) {
160 skip_mode = false;
161 assert current_expression == null;
162 if (n.f1.present()) {
163 NodeSequence ns = (NodeSequence) n.f1.node;
164 Node var = ns.elementAt(0);
165 current_expression = new ExpressionBuilder();
166 var.accept(this);
167 LineNumberInfo lin = LineNumberInfo.get(var);
168 current_expression.commit(lin.lineEnd);
169 }
170 current_expression = null;
171 skip_mode = true;
172 }
173
174 public void visit(InitDeclarator n) {
175 skip_mode = false;
176 assert current_expression == null;
177 current_expression = new ExpressionBuilder();
178 n.f0.accept(this);
179 current_expression = null;
180 skip_mode = true;
181 n.f2.accept(this);
182 }
183
184 public void visit(ExpressionStatement n) {
185 if (!n.f0.present())
186 return;
187 assert current_expression == null;
188 skip_mode = false;
189 current_expression = new ExpressionBuilder();
190 n.f0.accept(this);
191 LineNumberInfo lin = LineNumberInfo.get(n);
192 current_expression.commit(lin.lineEnd);
193 current_expression = null;
194 skip_mode = true;
195 }
196
197 public void visit(CompoundStatement n) {
198 assert current_expression == null;
199 assert skip_mode == true;
200 int old_end = scope_end_line;
201 scope_end_line = n.f2.endLine;
202 n.f1.accept(this);
203 scope_end_line = old_end;
204 }
205
206 public void visit(SwitchStatement n) {
207 assert current_expression == null;
208 skip_mode = false;
209 current_expression = new ExpressionBuilder();
210 n.f2.accept(this);
211 current_expression.commit(n.f0.endLine);
212 skip_mode = true;
213 current_expression = null;
214 n.f4.accept(this);
215 }
216
217 public void visit(IfStatement n) {
218 assert current_expression == null;
219 skip_mode = false;
220 current_expression = new ExpressionBuilder();
221 n.f2.accept(this);
222 current_expression.commit(n.f0.endLine);
223 skip_mode = true;
224 current_expression = null;
225 n.f4.accept(this);
226 n.f5.accept(this);
227 }
228
229 public void visit(WhileStatement n) {
230 assert current_expression == null;
231 skip_mode = false;
232 current_expression = new ExpressionBuilder();
233 n.f2.accept(this);
234 current_expression.commit(n.f0.endLine);
235 skip_mode = true;
236 current_expression = null;
237 n.f4.accept(this);
238 }
239
240 public void visit(DoWhileStatement n) {
241 assert current_expression == null;
242 skip_mode = false;
243 current_expression = new ExpressionBuilder();
244 n.f4.accept(this);
245 current_expression.commit(n.f6.endLine);
246 skip_mode = true;
247 current_expression = null;
248 n.f1.accept(this);
249 }
250
251 public void visit(ForStatement n) {
252 assert current_expression == null;
253 skip_mode = false;
254 int old_scope = scope_end_line;
255 LineNumberInfo lin = LineNumberInfo.get(n);
256 scope_end_line = lin.lineEnd;
257 if (n.f2.present()) {
258 current_expression = new ExpressionBuilder();
259 n.f2.accept(this);
260 current_expression.commit(n.f3.endLine);
261 }
262 if (n.f4.present()) {
263 current_expression = new ExpressionBuilder();
264 n.f4.accept(this);
265 current_expression.commit(n.f5.endLine);
266 }
267 if (n.f6.present()) {
268 current_expression = new ExpressionBuilder();
269 n.f6.accept(this);
270 current_expression.commit(n.f7.endLine);
271 }
272 skip_mode = true;
273 current_expression = null;
274 n.f8.accept(this);
275 scope_end_line = old_scope;
276 }
277
278 public void visit(JumpStatement n) {
279 if (n.f0.which != 3)
280 return;
281 NodeSequence ns = (NodeSequence) n.f0.choice;
282 assert current_expression == null;
283 skip_mode = false;
284 current_expression = new ExpressionBuilder();
285 ns.elementAt(1).accept(this);
286 LineNumberInfo lin = LineNumberInfo.get(n);
287 current_expression.commit(lin.lineEnd);
288 current_expression = null;
289 skip_mode = true;
290 }
291
292 public void visit(Expression n) {
293 ExpressionBuilder old = current_expression;
294 current_expression = new ExpressionBuilder();
295 n.f0.accept(this);
296 for (int i = 0; i < n.f1.size(); i++) {
297 NodeSequence ns = (NodeSequence) n.f1.elementAt(i);
298 current_expression = new ExpressionBuilder();
299 ns.elementAt(1).accept(this);
300 }
301 old.push(current_expression.expression);
302 current_expression = old;
303 }
304
305 public void visit(AssignmentOperator n) {
306 operator = true;
307 super.visit(n);
308 operator = false;
309 }
310
311 public void visit(AssignmentExpression n)
312 {
313 if (0 == n.f0.which)
314 {
315 NodeSequence ns = (NodeSequence) n.f0.choice;
316 UnaryExpression u = (UnaryExpression) ns.elementAt(0);
317 AssignmentOperator ao = (AssignmentOperator) ns.elementAt(1);
318 AssignmentExpression ae = (AssignmentExpression) ns.elementAt(2);
319 LineNumberInfo lin = LineNumberInfo.get(n);
320
321 ExpressionBuilder old = current_expression;
322 current_expression = new ExpressionBuilder();
323 u.accept(this);
324 current_expression.commit(lin.lineEnd);
325 ao.accept (this);
326 old.push(current_expression.expression);
327 current_expression = new ExpressionBuilder();
328 ae.accept(this);
329 current_expression.commit(lin.lineEnd);
330 old.push(current_expression.expression);
331 current_expression = old;
332 }
333 else
334 {
335 n.f0.choice.accept (this);
336 }
337 }
338
339 public void visit(ConditionalExpression n) {
340 ExpressionBuilder old = current_expression;
341 current_expression = new ExpressionBuilder();
342 n.f0.accept(this);
343 old.push(current_expression.expression);
344 if (n.f1.present()) {
345 LineNumberInfo lin = LineNumberInfo.get(n);
346 NodeSequence ns = (NodeSequence) n.f1.node;
347 current_expression = new ExpressionBuilder();
348 ns.elementAt(1).accept(this);
349 current_expression.commit(lin.lineEnd);
350 old.push("?");
351 old.push(current_expression.expression);
352 current_expression = new ExpressionBuilder();
353 ns.elementAt(3).accept(this);
354 current_expression.commit(lin.lineEnd);
355 old.push(":");
356 old.push(current_expression.expression);
357 old.commit(lin.lineEnd);
358 }
359 current_expression = old;
360 }
361
362 public void visit(ConstantExpression n) {
363 /* skip */
364 }
365
366 public void visit(LogicalORExpression n) {
367 assert skip_mode == false;
368 ExpressionBuilder old = current_expression;
369 current_expression = new ExpressionBuilder();
370 n.f0.accept(this);
371 if (n.f1.present()) {
372 LineNumberInfo lin = LineNumberInfo.get(n);
373 current_expression.commit(lin.lineEnd);
374 operator = true;
375 NodeSequence ns = (NodeSequence) n.f1.node;
376 ns.nodes.get(0).accept(this);
377 operator = false;
378 old.push(current_expression.expression);
379 current_expression = new ExpressionBuilder();
380 ns.nodes.get(1).accept(this);
381 current_expression.commit(lin.lineEnd);
382 }
383 old.push(current_expression.expression);
384 current_expression = old;
385 }
386
387 public void visit(LogicalANDExpression n) {
388 assert skip_mode == false;
389 ExpressionBuilder old = current_expression;
390 current_expression = new ExpressionBuilder();
391 n.f0.accept(this);
392 if (n.f1.present()) {
393 LineNumberInfo lin = LineNumberInfo.get(n);
394 current_expression.commit(lin.lineEnd);
395 operator = true;
396 NodeSequence ns = (NodeSequence) n.f1.node;
397 ns.nodes.get(0).accept(this);
398 operator = false;
399 old.push(current_expression.expression);
400 current_expression = new ExpressionBuilder();
401 ns.nodes.get(1).accept(this);
402 current_expression.commit(lin.lineEnd);
403 }
404 old.push(current_expression.expression);
405 current_expression = old;
406 }
407
408 public void visit(InclusiveORExpression n) {
409 assert skip_mode == false;
410 ExpressionBuilder old = current_expression;
411 current_expression = new ExpressionBuilder();
412 n.f0.accept(this);
413 if (n.f1.present()) {
414 LineNumberInfo lin = LineNumberInfo.get(n.f0);
415 current_expression.commit(lin.lineEnd);
416 operator = true;
417 NodeSequence ns = (NodeSequence) n.f1.node;
418 ns.nodes.get(0).accept(this);
419 operator = false;
420 ExpressionBuilder tmp = current_expression;
421 current_expression = new ExpressionBuilder();
422 ns.nodes.get(1).accept(this);
423 lin = LineNumberInfo.get(ns.nodes.get(1));
424 current_expression.commit(lin.lineEnd);
425 tmp.push (current_expression.expression);
426 current_expression = tmp;
427 }
428 old.push(current_expression.expression);
429 current_expression = old;
430 }
431
432 public void visit(ExclusiveORExpression n) {
433 assert skip_mode == false;
434 ExpressionBuilder old = current_expression;
435 current_expression = new ExpressionBuilder();
436 n.f0.accept(this);
437 if (n.f1.present()) {
438 LineNumberInfo lin = LineNumberInfo.get(n.f0);
439 current_expression.commit(lin.lineEnd);
440 operator = true;
441 NodeSequence ns = (NodeSequence) n.f1.node;
442 ns.nodes.get(0).accept(this);
443 operator = false;
444 ExpressionBuilder tmp = current_expression;
445 current_expression = new ExpressionBuilder();
446 ns.nodes.get(1).accept(this);
447 lin = LineNumberInfo.get(ns.nodes.get(1));
448 current_expression.commit(lin.lineEnd);
449 tmp.push (current_expression.expression);
450 current_expression = tmp;
451 }
452 old.push(current_expression.expression);
453 current_expression = old;
454 }
455
456 public void visit(ANDExpression n) {
457 assert skip_mode == false;
458 ExpressionBuilder old = current_expression;
459 current_expression = new ExpressionBuilder();
460 n.f0.accept(this);
461 if (n.f1.present()) {
462 LineNumberInfo lin = LineNumberInfo.get(n.f0);
463 current_expression.commit(lin.lineEnd);
464 operator = true;
465 NodeSequence ns = (NodeSequence) n.f1.node;
466 ns.nodes.get(0).accept(this);
467 operator = false;
468 ExpressionBuilder tmp = current_expression;
469 current_expression = new ExpressionBuilder();
470 ns.nodes.get(1).accept(this);
471 lin = LineNumberInfo.get(ns.nodes.get(1));
472 current_expression.commit(lin.lineEnd);
473 tmp.push (current_expression.expression);
474 current_expression = tmp;
475 }
476 old.push(current_expression.expression);
477 current_expression = old;
478 }
479
480 // Safey: this function was fixed to commit the right hand side, the
481 // other similar functions still need to be updated accordingly...
482 public void visit(EqualityExpression n) {
483 assert skip_mode == false;
484 ExpressionBuilder old = current_expression;
485 current_expression = new ExpressionBuilder();
486 n.f0.accept(this);
487 if (n.f1.present()) {
488 LineNumberInfo lin = LineNumberInfo.get(n);
489 current_expression.commit(lin.lineEnd);
490 operator = true;
491 NodeSequence ns = (NodeSequence) n.f1.node;
492 ns.nodes.get(0).accept(this);
493 operator = false;
494 old.push(current_expression.expression);
495 current_expression = new ExpressionBuilder();
496 ns.nodes.get(1).accept(this);
497 current_expression.commit(lin.lineEnd);
498 }
499 old.push(current_expression.expression);
500 current_expression = old;
501 }
502
503 public void visit(RelationalExpression n) {
504 assert skip_mode == false;
505 ExpressionBuilder old = current_expression;
506 current_expression = new ExpressionBuilder();
507 n.f0.accept(this);
508 if (n.f1.present()) {
509 LineNumberInfo lin = LineNumberInfo.get(n);
510 current_expression.commit(lin.lineEnd);
511 operator = true;
512 NodeSequence ns = (NodeSequence) n.f1.node;
513 ns.nodes.get(0).accept(this);
514 operator = false;
515 old.push(current_expression.expression);
516 current_expression = new ExpressionBuilder();
517 ns.nodes.get(1).accept(this);
518 current_expression.commit(lin.lineEnd);
519 }
520 old.push(current_expression.expression);
521 current_expression = old;
522 }
523
524 public void visit(ShiftExpression n) {
525 assert skip_mode == false;
526 ExpressionBuilder old = current_expression;
527 current_expression = new ExpressionBuilder();
528 n.f0.accept(this);
529 if (n.f1.present()) {
530 LineNumberInfo lin = LineNumberInfo.get(n.f0);
531 current_expression.commit(lin.lineEnd);
532 operator = true;
533 NodeSequence ns = (NodeSequence) n.f1.node;
534 ns.nodes.get(0).accept(this);
535 operator = false;
536 ExpressionBuilder tmp = current_expression;
537 current_expression = new ExpressionBuilder();
538 ns.nodes.get(1).accept(this);
539 lin = LineNumberInfo.get(ns.nodes.get(1));
540 current_expression.commit(lin.lineEnd);
541 tmp.push (current_expression.expression);
542 current_expression = tmp;
543 }
544 old.push(current_expression.expression);
545 current_expression = old;
546 }
547
548 public void visit(AdditiveExpression n) {
549 assert skip_mode == false;
550 ExpressionBuilder old = current_expression;
551 current_expression = new ExpressionBuilder();
552 n.f0.accept(this);
553 if (n.f1.present()) {
554 LineNumberInfo lin = LineNumberInfo.get(n.f0);
555 current_expression.commit(lin.lineEnd);
556 operator = true;
557 NodeSequence ns = (NodeSequence) n.f1.node;
558 ns.nodes.get(0).accept(this);
559 operator = false;
560 ExpressionBuilder tmp = current_expression;
561 current_expression = new ExpressionBuilder();
562 ns.nodes.get(1).accept(this);
563 lin = LineNumberInfo.get(ns.nodes.get(1));
564 current_expression.commit(lin.lineEnd);
565 tmp.push (current_expression.expression);
566 current_expression = tmp;
567 }
568 old.push(current_expression.expression);
569 current_expression = old;
570 }
571
572 public void visit(MultiplicativeExpression n) {
573 assert skip_mode == false;
574 ExpressionBuilder old = current_expression;
575 current_expression = new ExpressionBuilder();
576 n.f0.accept(this);
577 if (n.f1.present()) {
578 LineNumberInfo lin = LineNumberInfo.get(n.f0);
579 current_expression.commit(lin.lineEnd);
580 operator = true;
581 NodeSequence ns = (NodeSequence) n.f1.node;
582 ns.nodes.get(0).accept(this);
583 operator = false;
584 ExpressionBuilder tmp = current_expression;
585 current_expression = new ExpressionBuilder();
586 ns.nodes.get(1).accept(this);
587 lin = LineNumberInfo.get(ns.nodes.get(1));
588 current_expression.commit(lin.lineEnd);
589 tmp.push (current_expression.expression);
590 current_expression = tmp;
591 }
592 old.push(current_expression.expression);
593 current_expression = old;
594 }
595
596 public void visit(CastExpression n) {
597 if (n.f0.which == 1) {
598 n.f0.accept(this);
599 return;
600 }
601 NodeSequence ns = (NodeSequence) n.f0.choice;
602 ns.nodes.get(3).accept(this);
603 }
604
605 public void visit(UnaryExpression n) {
606 if ((n.f0.which == 1) || (n.f0.which == 2)) {
607 NodeSequence ns = (NodeSequence) n.f0.choice;
608 ns.nodes.get(1).accept(this);
609 } else
610 n.f0.accept(this);
611
612 }
613
614 public void visit(UnaryOperator n) {
615 operator = true;
616 n.f0.accept(this);
617 operator = false;
618 }
619
620 public void visit(PostfixExpression n) {
621 n.f0.accept(this);
622 for (int i = 0; i < n.f1.size(); i++) {
623 NodeChoice nc = (NodeChoice) n.f1.elementAt(i);
624 switch (nc.which) {
625 case 0: // []
626 {
627 ExpressionBuilder old = current_expression;
628 current_expression = new ExpressionBuilder();
629 NodeSequence ns = (NodeSequence) nc.choice;
630 ns.elementAt(1).accept(this);
631 LineNumberInfo lin = LineNumberInfo.get(n);
632 current_expression.commit(lin.lineEnd);
633 old.push("[");
634 old.push(current_expression.expression);
635 old.push("]");
636 current_expression = old;
637 }
638 case 1: // ()
639 {
640 ExpressionBuilder old = current_expression;
641 current_expression = new ExpressionBuilder();
642 NodeSequence ns = (NodeSequence) nc.choice;
643 ns.elementAt(1).accept(this);
644 LineNumberInfo lin = LineNumberInfo.get (ns.elementAt(1));
645 if (! current_expression.expression.isEmpty())
646 current_expression.commit(lin.lineEnd);
647 old.push("(");
648 old.push(current_expression.expression);
649 old.push(")");
650 current_expression = old;
651 }
652 break;
653 case 2: // .
654 case 3: // ->
655 {
656 ExpressionBuilder old = current_expression;
657 LineNumberInfo lin = LineNumberInfo.get(n);
658 old.commit(lin.lineEnd);
659 current_expression = new ExpressionBuilder();
660 NodeSequence ns = (NodeSequence) nc.choice;
661 ns.elementAt(1).accept(this);
662 if (nc.which == 2)
663 old.push(".");
664 else
665 old.push("->");
666 old.push(current_expression.expression);
667 current_expression = old;
668 }
669 break;
670 case 4: // ++
671 case 5: // --
672 /* skip */
673 break;
674 default:
675 throw new Error("Oops!");
676 }
677 }
678 }
679
680 public void visit(PrimaryExpression n) {
681 if (n.f0.which == 2) {
682 ExpressionBuilder old = current_expression;
683 current_expression = new ExpressionBuilder();
684 NodeSequence ns = (NodeSequence) n.f0.choice;
685 ns.elementAt(1).accept(this);
686 LineNumberInfo lin1 = LineNumberInfo.get (ns.elementAt(1));
687 current_expression.commit(lin1.lineEnd);
688 old.push("(");
689 old.push(current_expression.expression);
690 old.push(")");
691 LineNumberInfo lin = LineNumberInfo.get(n);
692 old.commit(lin.lineEnd);
693 current_expression = old;
694 } else
695 n.f0.accept(this);
696 }
697
698 public void visit(ArgumentExpressionList n) {
699 ExpressionBuilder old = current_expression;
700 current_expression = new ExpressionBuilder();
701 n.f0.accept(this);
702 old.push(current_expression.expression);
703 for (int i = 0; i < n.f1.size(); i++) {
704 NodeSequence ns = (NodeSequence) n.f1.elementAt(i);
705 current_expression = new ExpressionBuilder();
706 ns.elementAt(1).accept(this);
707 old.push(",");
708 old.push(current_expression.expression);
709 }
710 current_expression = old;
711 }
712
713}
diff --git a/src/monkey/seaspider/org/gnunet/seaspider/Seaspider.java b/src/monkey/seaspider/org/gnunet/seaspider/Seaspider.java
deleted file mode 100644
index c9b54c6d5..000000000
--- a/src/monkey/seaspider/org/gnunet/seaspider/Seaspider.java
+++ /dev/null
@@ -1,132 +0,0 @@
1package org.gnunet.seaspider;
2
3import java.io.File;
4import java.io.FileInputStream;
5import java.io.FileNotFoundException;
6import java.io.FilenameFilter;
7
8import org.gnunet.seaspider.parser.CParser;
9import org.gnunet.seaspider.parser.ParseException;
10import org.gnunet.seaspider.parser.TokenMgrError;
11import org.gnunet.seaspider.parser.nodes.Node;
12
13public class Seaspider {
14
15 private static final boolean DEBUG = true;
16 private static CParser parser = null;
17 private static boolean isFirstFile = true;
18 private static int successCount = 0;
19 private static int failureCount = 0;
20 private static FilenameFilter filter = new FilenameFilter() {
21 public boolean accept(File dir, String fileName) {
22 File file = new File(dir.getPath() + "/" + fileName);
23 if ((file.isDirectory() && !fileName.startsWith(".")) || (fileName.endsWith(".c") && !fileName.startsWith("test_")))
24 /* directories like .svn are of no interest */
25 return true;
26 return false;
27 }
28 };
29
30
31 private static void doParseFile(String filePath)
32 {
33 try {
34 if (isFirstFile) {
35 parser = new CParser(new FileInputStream(filePath));
36 isFirstFile = false;
37 }
38 else
39 parser.ReInit(new FileInputStream(filePath));
40 }
41 catch (FileNotFoundException e) {
42 /* This should never happen */
43 System.err.println("File not found!");
44 e.printStackTrace();
45 System.exit(1);
46 }
47 try {
48 System.out.println("Parsing file: " + filePath);
49 Node root = parser.TranslationUnit();
50 root.accept(new ExpressionExtractorVisitor(filePath));
51 System.out.println("File " + filePath + " parsed successfully.");
52 successCount++;
53 }
54 catch (ParseException e) {
55 System.out.println("Encountered errors during parsing file " + filePath);
56 failureCount++;
57 if (DEBUG)
58 e.printStackTrace();
59 } catch (TokenMgrError e) {
60 System.err.println("Encountered errors during parsing file " + filePath + ":" + e.getMessage());
61 failureCount++;
62 if (DEBUG)
63 e.printStackTrace();
64 }
65 }
66
67
68 private static void parseRecursively(String path)
69 {
70 File file = new File(path);
71
72 if (!file.isDirectory()) {
73 if (path.endsWith(".db"))
74 return;
75 /* A source file */
76 doParseFile(path);
77 return;
78 }
79
80 /* A source directory */
81 System.out.println("Reading from: " + path + " source directory...");
82 String[] dirContents = file.list(filter);/* Only directories and .c files */
83 for (int i = 0; i < dirContents.length; i++) {
84 String fullPath = path + "/" + dirContents[i];
85 parseRecursively(fullPath);
86 }
87 }
88
89 public static void main(String args[])
90 {
91 String dbFilePath = null;
92
93 if (args.length < 2)
94 {
95 System.err.println("Invoke seaspider with database filename and source path!");
96 System.exit(1);
97 }
98 System.out.println("Seaspider 0.0\n");
99
100
101 for (int i = 0; i < args.length; i++) {
102 if (args[i].endsWith(".db"))
103 dbFilePath = args[i];
104 else {
105 /* Should be a valid path for a file or a directory */
106 File file = new File(args[i]);
107 if (!file.exists()) {
108 System.err.println("\"" + args[i] + "\" is an invalid file or directory location");
109 System.exit(1);
110 } else if (!file.isDirectory() && !args[i].endsWith(".c")) {
111 System.err.println("\"" + args[i] + "\" only source files can be parsed");
112 }
113 }
114 }
115 if (null == dbFilePath) {
116 System.err.println("Missing database file path");
117 System.exit(1);
118 }
119
120 /* Create the Expressions Database */
121 ExpressionDatabaseHandler.createExpressionDatabase(dbFilePath);
122
123 for (int i = 0; i < args.length; i++)
124 parseRecursively(args[i]);
125
126 /* We're done with the Expression Database, close it */
127 ExpressionDatabaseHandler.closeDatabase();
128
129 System.out.println(successCount + " parsed successfully.");
130 System.out.println("Failed to parse " + failureCount + " files.");
131 }
132}
diff --git a/src/monkey/seaspider/org/grothoff/LineNumberInfo.java b/src/monkey/seaspider/org/grothoff/LineNumberInfo.java
deleted file mode 100644
index 67d8ef541..000000000
--- a/src/monkey/seaspider/org/grothoff/LineNumberInfo.java
+++ /dev/null
@@ -1,192 +0,0 @@
1package org.grothoff;
2
3import java.lang.reflect.Field;
4import java.util.Enumeration;
5import java.util.WeakHashMap;
6
7/**
8 * Obtain line number information for any JTB node. Note that
9 * "any" really means any -- we use reflection to overcome the
10 * problem that we do not know the full name of the AST root
11 * (in particular, there maybe multiple AST hierarchies in the
12 * project with multiple root "Node" classes).<p>
13 *
14 * Essentially, pass a JTB node to the static "get" method
15 * and (if it is a JTB node and there is source corresponding
16 * to it), a LineNumberInfo object with the scope of the
17 * subtree is returned. Otherwise null.<p>
18 *
19 *
20 * Minimal example:
21 * <code>
22 * void semanticError(String message, Node n) {
23 * throw new Error(message + " at " + LineNumberInfo.get(n));
24 * }
25 * </code>
26 *<p>
27 *
28 * This code is dual licensed under both BSD and LGPL.
29 *
30 * @author Christian Grothoff
31 */
32public class LineNumberInfo {
33
34 private static final Object NULL = new Object();
35 private static final Object SELF = new Object();
36 private static final WeakHashMap<Object, Object> cacheF_ = new WeakHashMap<Object,Object>();
37 private static final WeakHashMap<Object, Object> cacheL_ = new WeakHashMap<Object,Object>();
38
39 public final int lineStart;
40 public final int lineEnd;
41 public final int colStart;
42 public final int colEnd;
43
44 public LineNumberInfo(int s, int e, int cs, int ce) {
45 lineStart = s;
46 lineEnd = e;
47 colStart = cs;
48 colEnd = ce;
49 }
50
51 public String toString() {
52 return "["+lineStart+":"+colStart+","+lineEnd+":"+colEnd+"]";
53 }
54
55 /**
56 * Compute line number information for the given JTB node.
57 *
58 * @param o any JTB node (the type should be node, but since this
59 * code handles any JTB AST we cannot hardwire the
60 * type ("Node" -- but which package?)
61 * @return
62 */
63 public static LineNumberInfo get(Object o) {
64 if (o == null)
65 return null; // fail!
66 Object p = firstMatch(o);
67 Object q = lastMatch(o);
68 try {
69 int lstart = ((Integer)p.getClass().getField("beginLine").get(p)).intValue();
70 int cstart = ((Integer)p.getClass().getField("beginColumn").get(p)).intValue();
71 int lend = ((Integer)p.getClass().getField("endLine").get(q)).intValue();
72 int cend = ((Integer)p.getClass().getField("endColumn").get(q)).intValue();
73 return new LineNumberInfo(lstart, lend, cstart, cend);
74 } catch (Throwable t) {
75 return null; // failed
76 }
77 }
78
79 private static Object firstMatch(Object o) {
80 synchronized(cacheF_) {
81 Object r = cacheF_.get(o);
82 if (r != null)
83 return (r == SELF) ? o : (r == NULL) ? null : r;
84 }
85 Object r = firstMatch_(o);
86 synchronized(cacheF_) {
87 cacheF_.put(o, r == o ? SELF : r == null ? NULL : r);
88 }
89 return r;
90 }
91
92
93 private static Object lastMatch(Object o) {
94 synchronized(cacheL_) {
95 Object r = cacheL_.get(o);
96 if (r != null)
97 return (r == SELF) ? o : (r == NULL) ? null : r;
98 }
99 Object r = lastMatch_(o);
100 synchronized(cacheL_) {
101 cacheL_.put(o, r == o ? SELF : r == null ? NULL : r);
102 }
103 return r;
104 }
105
106 private static Object firstMatch_(Object o) {
107 if (o == null)
108 return null;
109 Class c = o.getClass();
110 if (c.getName().endsWith("NodeToken"))
111 return o;
112 try {
113 int i=0;
114 while (true) {
115 Field f = null;
116 try {
117 f = c.getField("f" + i);
118 } catch (Throwable t) {
119 }
120 if ( (f == null) && (i == 0) && (c.getName().endsWith("NodeChoice")) ) {
121 f = c.getField("choice");
122 } else if ( (f == null) && (i == 0) && (c.getName().endsWith("NodeOptional")) ) {
123 f = c.getField("node");
124 } else if ( (f == null) && (i == 0) ) {
125 // special cases: node sequence, etc.
126 Enumeration e = (Enumeration) c.getMethod("elements").invoke(o);
127 while (e.hasMoreElements()) {
128 Object x = firstMatch(e.nextElement());
129 if (x != null)
130 return x;
131 }
132 }
133 if (f != null) {
134 Object r = firstMatch(f.get(o));
135 if (r != null)
136 return r;
137 } else {
138 return null;
139 }
140 i++;
141 }
142 } catch (Throwable t) {
143 }
144 return null;
145 }
146
147 private static Object lastMatch_(Object o) {
148 if (o == null)
149 return null;
150 Class c = o.getClass();
151 if (c.getName().endsWith("NodeToken"))
152 return o;
153
154 Object ret = null;
155 try {
156 int i=0;
157 while (true) {
158 Field f = null;
159 try {
160 f = c.getField("f" + i);
161 } catch (Throwable t) {
162 }
163 if ( (f == null) && (i == 0) && (c.getName().endsWith("NodeChoice")) ) {
164 f = c.getField("choice");
165 } else if ( (f == null) && (i == 0) && (c.getName().endsWith("NodeOptional")) ) {
166 f = c.getField("node");
167 } else if ( (f == null) && (i == 0) ) {
168 // special cases: node sequence, etc.
169 Enumeration e = (Enumeration) o.getClass().getMethod("elements").invoke(o);
170 while (e.hasMoreElements()) {
171 Object x = lastMatch(e.nextElement());
172 if (x != null)
173 ret = x;
174 }
175 return ret;
176 }
177 if (f != null) {
178 Object r = lastMatch(f.get(o));
179 if (r != null)
180 ret = r;
181 } else {
182 return ret;
183 }
184 i++;
185 }
186 } catch (Throwable t) {
187 }
188 return ret;
189 }
190
191}
192
diff --git a/src/monkey/test.db b/src/monkey/test.db
deleted file mode 100644
index 6d15e709f..000000000
--- a/src/monkey/test.db
+++ /dev/null
Binary files differ
diff --git a/src/monkey/test_gnunet_monkey.c b/src/monkey/test_gnunet_monkey.c
deleted file mode 100644
index d1d4155d0..000000000
--- a/src/monkey/test_gnunet_monkey.c
+++ /dev/null
@@ -1,72 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file monkey/test_gnunet_monkey.c
23 * @brief Testcase for Monkey
24 * @author Safey Abdel Halim
25 */
26
27/**
28 * Test case for Monkey Automatic Debugger.
29 * It launches Monkey to run binaries having
30 * known bugs (e.g. Null Pointer Exception)
31 * Monkey should be able to detect the problem and send an e-mail
32 * containing the problem description.
33 */
34
35
36#include "platform.h"
37#include "gnunet_common.h"
38#include "gnunet_util_lib.h"
39#include "gnunet_program_lib.h"
40
41
42static int
43check ()
44{
45 GNUNET_OS_process_close (GNUNET_OS_start_process (NULL, NULL,
46 "gnunet-monkey",
47 "gnunet-monkey",
48 "./bug_null_pointer_exception",
49 NULL));
50
51 return 0;
52}
53
54
55int
56main (int argc, char *argv[])
57{
58 int ret;
59
60 GNUNET_log_setup ("test-gnunet-monkey",
61#if VERBOSE
62 "DEBUG",
63#else
64 "WARNING",
65#endif
66 NULL);
67 ret = check ();
68 return ret;
69}
70
71/* end of test_gnunet_monkey.c */
72
diff --git a/src/monkey/test_gnunet_monkey.sh b/src/monkey/test_gnunet_monkey.sh
deleted file mode 100755
index 7595a68fb..000000000
--- a/src/monkey/test_gnunet_monkey.sh
+++ /dev/null
@@ -1,199 +0,0 @@
1#!/bin/sh
2
3rm -rf /tmp/test-gnunetd-monkey/
4exe="./gnunet-monkey -c test_monkey_api_data.conf"
5out=`mktemp /tmp/test-gnunet-monkey-logXXXXXXXX`
6arm="gnunet-arm -c test_monkey_api_data.conf $DEBUG"
7#DEBUG="-L DEBUG"
8# -----------------------------------
9echo -n "Preparing: Starting service..."
10
11$arm -s > /dev/null
12sleep 1
13$arm -i monkey > /dev/null
14sleep 1
15echo "DONE"
16
17# ----------------------------------------------------------------------------------
18echo -n "TEST: Bad argument checking..."
19
20if $exe -x 2> /dev/null; then
21 echo "FAIL: error running $exe"
22 $arm -e
23 exit 1
24fi
25echo "PASS"
26
27# ----------------------------------------------------------------------------------
28echo -n "TEST: Set value..."
29
30if ! $exe $DEBUG -n test -s subsystem 42 ; then
31 echo "FAIL: error running $exe"
32 $arm -e
33 exit 1
34fi
35echo "PASS"
36
37# ----------------------------------------------------------------------------------
38echo -n "TEST: Set another value..."
39
40if ! $exe $DEBUG -n other -s osystem 43 ; then
41 echo "FAIL: error running $exe"
42 $arm -e
43 exit 1
44fi
45echo "PASS"
46
47# ----------------------------------------------------------------------------------
48echo -n "TEST: viewing all stats..."
49
50if ! $exe $DEBUG > $out; then
51 echo "FAIL: error running $exe"
52 $arm -e
53 exit 1
54fi
55LINES=`cat $out | wc -l`
56if test $LINES -ne 2; then
57 echo "FAIL: unexpected output"
58 $arm -e
59 exit 1
60fi
61echo "PASS"
62
63# ----------------------------------------------------------------------------------
64echo -n "TEST: viewing stats by name..."
65
66if ! $exe $DEBUG -n other > $out; then
67 echo "FAIL: error running $exe"
68 $arm -e
69 exit 1
70fi
71LINES=`cat $out | grep 43 | wc -l`
72if test $LINES -ne 1; then
73 echo "FAIL: unexpected output"
74 $arm -e
75 exit 1
76fi
77echo "PASS"
78
79# ----------------------------------------------------------------------------------
80echo -n "TEST: viewing stats by subsystem..."
81
82if ! $exe $DEBUG -s subsystem > $out; then
83 echo "FAIL: error running $exe"
84 $arm -e
85 exit 1
86fi
87LINES=`cat $out | grep 42 | wc -l`
88if test $LINES -ne 1; then
89 echo "FAIL: unexpected output"
90 $arm -e
91 exit 1
92fi
93echo "PASS"
94
95
96# ----------------------------------------------------------------------------------
97echo -n "TEST: Set persistent value..."
98
99if ! $exe $DEBUG -n lasting -s subsystem 40 -p; then
100 echo "FAIL: error running $exe"
101 $arm -e
102 exit 1
103fi
104if ! $exe $DEBUG > $out; then
105 echo "FAIL: error running $exe"
106 $arm -e
107 exit 1
108fi
109LINES=`cat $out | grep 40 | wc -l`
110if test $LINES -ne 1; then
111 echo "FAIL: unexpected output"
112 cat $out
113 $arm -e
114 exit 1
115fi
116echo "PASS"
117
118# -----------------------------------
119echo -n "Restarting service..."
120$arm -k monkey > /dev/null
121sleep 1
122$arm -i monkey > /dev/null
123sleep 1
124echo "DONE"
125
126# ----------------------------------------------------------------------------------
127echo -n "TEST: checking persistence..."
128
129if ! $exe $DEBUG > $out; then
130 echo "FAIL: error running $exe"
131 $arm -e
132 exit 1
133fi
134LINES=`cat $out | grep 40 | wc -l`
135if test $LINES -ne 1; then
136 echo "FAIL: unexpected output"
137 cat $out
138 $arm -e
139 exit 1
140fi
141echo "PASS"
142
143
144
145# ----------------------------------------------------------------------------------
146echo -n "TEST: Removing persistence..."
147
148if ! $exe $DEBUG -n lasting -s subsystem 40; then
149 echo "FAIL: error running $exe"
150 $arm -e
151 exit 1
152fi
153if ! $exe $DEBUG > $out; then
154 echo "FAIL: error running $exe"
155 $arm -e
156 exit 1
157fi
158LINES=`cat $out | grep \! | wc -l`
159if test $LINES -ne 0; then
160 echo "FAIL: unexpected output"
161 cat $out
162 $arm -e
163 exit 1
164fi
165echo "PASS"
166
167
168# -----------------------------------
169echo -n "Restarting service..."
170$arm -k monkey > /dev/null
171sleep 1
172$arm -i monkey > /dev/null
173sleep 1
174echo "DONE"
175
176# ----------------------------------------------------------------------------------
177echo -n "TEST: checking removed persistence..."
178
179if ! $exe $DEBUG > $out; then
180 echo "FAIL: error running $exe"
181 $arm -e
182 exit 1
183fi
184LINES=`cat $out | grep 40 | wc -l`
185if test $LINES -ne 0; then
186 echo "FAIL: unexpected output"
187 cat $out
188 $arm -e
189 exit 1
190fi
191echo "PASS"
192
193# -----------------------------------
194echo -n "Stopping service..."
195$arm -e > /dev/null
196sleep 1
197echo "DONE"
198rm -f $out
199rm -rf /tmp/test-gnunetd-monkey/
diff --git a/src/monkey/test_gnunet_monkey_data.conf b/src/monkey/test_gnunet_monkey_data.conf
deleted file mode 100644
index 9ae1d6772..000000000
--- a/src/monkey/test_gnunet_monkey_data.conf
+++ /dev/null
@@ -1,43 +0,0 @@
1[PATHS]
2SERVICEHOME = /tmp/test-gnunetd-arm/
3DEFAULTCONFIG = test_arm_api_data.conf
4
5[arm]
6PORT = 23354
7DEFAULTSERVICES =
8BINARY = gnunet-service-arm
9OPTIONS = -L ERROR
10# DEBUG = YES
11#PREFIX = valgrind --tool=memcheck --leak-check=yes
12
13[gnunet-monkey]
14# DEBUG = YES
15PORT = 23355
16BINARY = gnunet-monkey
17# PREFIX = valgrind
18
19
20[fs]
21AUTOSTART = NO
22
23[datastore]
24AUTOSTART = NO
25
26[core]
27AUTOSTART = NO
28
29[transport]
30AUTOSTART = NO
31
32[peerinfo]
33AUTOSTART = NO
34
35[statistics]
36AUTOSTART = YES
37# DEBUG = NO
38
39
40[dns]
41AUTOSTART = NO
42
43
diff --git a/src/monkey/test_monkey_edb.c b/src/monkey/test_monkey_edb.c
deleted file mode 100644
index b418bee9a..000000000
--- a/src/monkey/test_monkey_edb.c
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20/**
21 * @file monkey/test_monkey_edb.c
22 * @brief testcase for edb_api.c
23 */
24#include "platform.h"
25#include "gnunet_common.h"
26#include "gnunet_monkey_edb.h"
27
28
29static const char *ref[16] =
30 { "args", "32", "argv", "32", "whole", "42", "whole.member", "42",
31 "whole.member=1", "42", "whole.part", "43", "&part", "43",
32 "whole.part=&part", "43"
33};
34
35static int refCount = 0;
36static int ret = 1;
37
38int
39expressionIterator (void *cls, int colNum, char **colValues, char **colNames)
40{
41 int i;
42 for (i = 0; i < colNum; i++)
43 {
44 if (strcmp (colValues[i], ref[refCount]) != 0)
45 return 1;
46 refCount++;
47 }
48
49 return 0;
50}
51
52
53int
54main (int args, const char *argv[])
55{
56 struct GNUNET_MONKEY_EDB_Context *cntxt;
57 cntxt = GNUNET_MONKEY_EDB_connect ("test.db");
58 ret =
59 GNUNET_MONKEY_EDB_get_expressions (cntxt,
60 "monkey/seaspider/SeaspiderTest.c", 44,
61 83, &expressionIterator, NULL);
62 GNUNET_MONKEY_EDB_disconnect (cntxt);
63
64 if (ret == GNUNET_OK)
65 {
66 return 0;
67 }
68 return 1;
69}
diff --git a/src/monkey/test_monkey_npe.sh b/src/monkey/test_monkey_npe.sh
deleted file mode 100755
index c8fa2ceaa..000000000
--- a/src/monkey/test_monkey_npe.sh
+++ /dev/null
@@ -1,11 +0,0 @@
1#!/bin/sh
2echo -n "Test Monkey with Bug - Null Pointer Exception -"
3gnunet-monkey --mode text --binary bug_null_pointer_exception --output npe.out && exit 0
4grep "Bug detected in file:bug_null_pointer_exception.c" npe.out > /dev/null || exit 1
5grep "function:crashFunction" npe.out > /dev/null || exit 1
6grep "line:8" npe.out > /dev/null || exit 1
7grep "reason:Signal received" npe.out > /dev/null || exit 1
8grep "received signal:EXC_BAD_ACCESS" npe.out > /dev/null || exit 1
9grep "Could not access memory" npe.out > /dev/null || exit 1
10rm -f npe.out
11echo "PASS" \ No newline at end of file
diff --git a/src/monkey/tmp b/src/monkey/tmp
deleted file mode 100644
index b3a613732..000000000
--- a/src/monkey/tmp
+++ /dev/null
@@ -1,30 +0,0 @@
1==1277== Memcheck, a memory error detector
2==1277== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
3==1277== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
4==1277== Command: ./bug_bad_memory_access
5==1277== Parent PID: 1666
6==1277==
7==1277== Invalid write of size 4
8==1277== at 0x400512: badMemoryAccess (bug_bad_memory_access.c:9)
9==1277== by 0x400532: main (bug_bad_memory_access.c:14)
10==1277== Address 0x4252352 is not stack'd, malloc'd or (recently) free'd
11==1277==
12==1277==
13==1277== Process terminating with default action of signal 11 (SIGSEGV)
14==1277== Access not within mapped region at address 0x4252352
15==1277== at 0x400512: badMemoryAccess (bug_bad_memory_access.c:9)
16==1277== by 0x400532: main (bug_bad_memory_access.c:14)
17==1277== If you believe this happened as a result of a stack
18==1277== overflow in your program's main thread (unlikely but
19==1277== possible), you can try to increase the size of the
20==1277== main thread stack using the --main-stacksize= flag.
21==1277== The main thread stack size used in this run was 8388608.
22==1277==
23==1277== HEAP SUMMARY:
24==1277== in use at exit: 0 bytes in 0 blocks
25==1277== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
26==1277==
27==1277== All heap blocks were freed -- no leaks are possible
28==1277==
29==1277== For counts of detected and suppressed errors, rerun with: -v
30==1277== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)