diff options
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) |
585 | fi | 585 | fi |
586 | 586 | ||
587 | # libesmtp | ||
588 | esmtp=0 | ||
589 | AC_MSG_CHECKING([for libesmtp]) | ||
590 | AC_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))]) | ||
615 | AM_CONDITIONAL(HAVE_ESMTP, test x$esmtp = x1) | ||
616 | AC_DEFINE_UNQUOTED([HAVE_ESMTP], $esmtp, [We have libesmtp]) | ||
617 | # restore LIBS | ||
618 | LIBS=$SAVE_LIBS | ||
619 | |||
620 | |||
621 | 587 | ||
622 | # check for gettext | 588 | # check for gettext |
623 | AM_GNU_GETTEXT([external]) | 589 | AM_GNU_GETTEXT([external]) |
@@ -826,7 +792,6 @@ src/include/Makefile | |||
826 | src/include/gnunet_directories.h | 792 | src/include/gnunet_directories.h |
827 | src/hostlist/Makefile | 793 | src/hostlist/Makefile |
828 | src/mesh/Makefile | 794 | src/mesh/Makefile |
829 | src/monkey/Makefile | ||
830 | src/nat/Makefile | 795 | src/nat/Makefile |
831 | src/peerinfo/Makefile | 796 | src/peerinfo/Makefile |
832 | src/peerinfo-tool/Makefile | 797 | src/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 | |||
55 | PORT = 2086 | 55 | PORT = 2086 |
56 | ADVERTISED_PORT = 2086 | 56 | ADVERTISED_PORT = 2086 |
57 | 57 | ||
58 | TIMEOUT = 300000 | 58 | # Maximum number of open TCP connections allowed |
59 | MAX_CONNECTIONS = 128 | ||
60 | |||
61 | # After how long do we drop inactive connections? | ||
62 | TIMEOUT = 5000 | ||
59 | 63 | ||
60 | # Allow use of loopback address | 64 | # Allow use of loopback address |
61 | USE_LOCALADDR = NO | 65 | USE_LOCALADDR = NO |
@@ -416,3 +420,4 @@ ACCEPT_FROM = 127.0.0.1; | |||
416 | ACCEPT_FROM6 = ::1; | 420 | ACCEPT_FROM6 = ::1; |
417 | UNIXPATH = /tmp/gnunet-service-dns.sock | 421 | UNIXPATH = /tmp/gnunet-service-dns.sock |
418 | PROVIDE_EXIT = NO | 422 | PROVIDE_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 | ||
5 | if HAVE_ESMTP | ||
6 | if HAVE_OPENSSL | ||
7 | if HAVE_EXPERIMENTAL | ||
8 | MONKEY_DIR = monkey | ||
9 | endif | ||
10 | endif | ||
11 | endif | ||
12 | |||
13 | if HAVE_EXPERIMENTAL | 5 | if HAVE_EXPERIMENTAL |
14 | EXP_DIR = fragmentation mesh vpn chat | 6 | EXP_DIR = fragmentation mesh vpn chat |
15 | endif | 7 | endif |
@@ -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 @@ | |||
1 | INCLUDES = -I$(top_srcdir)/src/include | ||
2 | |||
3 | if MINGW | ||
4 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
5 | endif | ||
6 | |||
7 | if USE_COVERAGE | ||
8 | AM_CFLAGS = --coverage -O0 | ||
9 | XLIB = -lgcov | ||
10 | endif | ||
11 | |||
12 | |||
13 | if !MINGW | ||
14 | if HAVE_ESMTP | ||
15 | if HAVE_OPENSSL | ||
16 | |||
17 | |||
18 | lib_LTLIBRARIES = libmonkeyedb.la \ | ||
19 | libmonkeyaction.la | ||
20 | |||
21 | libmonkeyedb_la_SOURCES = \ | ||
22 | edb_api.c \ | ||
23 | gnunet_monkey_edb.h | ||
24 | |||
25 | libmonkeyedb_la_LIBADD = \ | ||
26 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
27 | -lsqlite3 \ | ||
28 | $(GN_LIBINTL) $(XLIB) | ||
29 | |||
30 | libmonkeyaction_la_SOURCES = \ | ||
31 | action_api.c \ | ||
32 | gnunet_monkey_action.h | ||
33 | |||
34 | libmonkeyaction_la_LIBADD = \ | ||
35 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
36 | $(GN_LIBINTL) $(XLIB) | ||
37 | |||
38 | bin_PROGRAMS = \ | ||
39 | gnunet-monkey \ | ||
40 | gnunet-service-monkey | ||
41 | |||
42 | noinst_PROGRAMS = \ | ||
43 | bug_null_pointer_exception \ | ||
44 | bug_bad_memory_access \ | ||
45 | bug_assertion_failure \ | ||
46 | bug_crypto_crc | ||
47 | |||
48 | gnunet_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 | |||
68 | gnunet_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 | |||
76 | gnunet_service_monkey_SOURCES = \ | ||
77 | gnunet-service-monkey.c | ||
78 | gnunet_service_monkey_LDADD = \ | ||
79 | $(top_builddir)/src/util/libgnunetutil.la \ | ||
80 | $(GN_LIBINTL) | ||
81 | |||
82 | |||
83 | bug_null_pointer_exception: | ||
84 | gcc -g -O0 -o bug_null_pointer_exception bug_null_pointer_exception.c | ||
85 | |||
86 | bug_bad_memory_access: | ||
87 | gcc -g -O0 -o bug_bad_memory_access bug_bad_memory_access.c | ||
88 | |||
89 | bug_assertion_failure: | ||
90 | gcc -g -O0 -o bug_assertion_failure bug_assertion_failure.c | ||
91 | |||
92 | bug_crypto_crc: | ||
93 | gcc -g -O0 -o bug_crypto_crc bug_crypto_crc.c | ||
94 | |||
95 | check_PROGRAMS = \ | ||
96 | test_monkey_edb | ||
97 | #test_gnunet_monkey | ||
98 | |||
99 | if ENABLE_TEST_RUN | ||
100 | # TESTS = $(check_SCRIPTS) | ||
101 | TESTS = $(check_PROGRAMS) | ||
102 | endif | ||
103 | |||
104 | test_monkey_edb_SOURCES = \ | ||
105 | test_monkey_edb.c | ||
106 | test_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 | |||
117 | check_SCRIPTS = \ | ||
118 | #test_gnunet_monkey.sh \ | ||
119 | #test_monkey_npe.sh | ||
120 | |||
121 | EXTRA_DIST = \ | ||
122 | test_gnunet_monkey_data.conf \ | ||
123 | test.db | ||
124 | #$(check_SCRIPTS) | ||
125 | |||
126 | endif | ||
127 | endif | ||
128 | endif | ||
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 | |||
33 | extern void sendMail (const char *messageContents, const char *emailAddress); | ||
34 | |||
35 | |||
36 | static int async_c = 0; | ||
37 | static struct Expression *expressionListHead = NULL; | ||
38 | static struct Expression *expressionListTail = NULL; | ||
39 | static struct WatchInfo *watchInfoListHead = NULL; | ||
40 | static struct WatchInfo *watchInfoListTail = NULL; | ||
41 | static struct Expression *faultyExpression = NULL; | ||
42 | |||
43 | struct Expression | ||
44 | { | ||
45 | struct Expression *next; | ||
46 | struct Expression *prev; | ||
47 | const char *expressionSyntax; | ||
48 | const char *expressionValue; | ||
49 | int lineNo; | ||
50 | }; | ||
51 | |||
52 | struct WatchInfo | ||
53 | { | ||
54 | struct WatchInfo *next; | ||
55 | struct WatchInfo *prev; | ||
56 | int hitNumber; | ||
57 | const char *value; | ||
58 | }; | ||
59 | |||
60 | |||
61 | static void | ||
62 | cb_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. */ | ||
69 | static void | ||
70 | cb_target (const char *str, void *data) | ||
71 | { | ||
72 | printf ("TARGET> %s\n", str); | ||
73 | } | ||
74 | |||
75 | |||
76 | static void | ||
77 | cb_log (const char *str, void *data) | ||
78 | { | ||
79 | printf ("LOG> %s\n", str); | ||
80 | } | ||
81 | |||
82 | |||
83 | static void | ||
84 | cb_to (const char *str, void *data) | ||
85 | { | ||
86 | printf (">> %s", str); | ||
87 | } | ||
88 | |||
89 | |||
90 | static void | ||
91 | cb_from (const char *str, void *data) | ||
92 | { | ||
93 | printf ("<< %s\n", str); | ||
94 | } | ||
95 | |||
96 | |||
97 | static void | ||
98 | cb_async (mi_output * o, void *data) | ||
99 | { | ||
100 | printf ("ASYNC\n"); | ||
101 | async_c++; | ||
102 | } | ||
103 | |||
104 | |||
105 | static int | ||
106 | wait_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 | |||
171 | int | ||
172 | GNUNET_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 | |||
183 | int | ||
184 | GNUNET_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 | |||
193 | static int | ||
194 | iterateExpressions (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 | |||
213 | static int | ||
214 | scopeEndCallback (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 | |||
226 | static struct Expression * | ||
227 | getFaultyExpression (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 | |||
248 | static int | ||
249 | analyzeSegmentationFault (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 | |||
302 | static int | ||
303 | analyzeCustomFault (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 | |||
328 | int | ||
329 | GNUNET_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 | |||
380 | int | ||
381 | GNUNET_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 | |||
405 | int | ||
406 | GNUNET_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 | |||
478 | static int | ||
479 | getExpressionListSize(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 | |||
494 | static const char * | ||
495 | expressionListToString (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 | ||
517 | static int | ||
518 | getWatchInfoListSize(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 | |||
534 | static const char* | ||
535 | watchInfoListToString(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 | |||
557 | static 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 | |||
573 | int | ||
574 | GNUNET_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 | |||
636 | int | ||
637 | GNUNET_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 | |||
651 | int | ||
652 | GNUNET_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 | |||
4 | void assertionFailure() | ||
5 | { | ||
6 | int x = 5; | ||
7 | printf("Assertion Failure Now!\n"); | ||
8 | assert(x < 4); | ||
9 | } | ||
10 | |||
11 | int 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 | |||
5 | void badMemoryAccess() | ||
6 | { | ||
7 | int *p = (int*) 0x4252352; | ||
8 | printf("Bad memory access now!\n"); | ||
9 | *p = 5; | ||
10 | } | ||
11 | |||
12 | int 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 | ||
40 | static 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 | */ | ||
47 | static void | ||
48 | crc_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 | */ | ||
77 | static unsigned long | ||
78 | crc_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 | */ | ||
96 | int32_t | ||
97 | crc32_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 | |||
106 | int 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 | |||
5 | struct CrashStruct { | ||
6 | const char *crashValue; | ||
7 | }; | ||
8 | |||
9 | void crashFunction() | ||
10 | { | ||
11 | struct CrashStruct *crashStruct; | ||
12 | crashStruct = NULL; | ||
13 | printf("Now the program will crash!\n"); | ||
14 | crashStruct->crashValue = "hello!"; | ||
15 | } | ||
16 | |||
17 | int 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 | */ | ||
35 | struct 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 | */ | ||
50 | struct GNUNET_MONKEY_EDB_Context * | ||
51 | GNUNET_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 | */ | ||
75 | int | ||
76 | GNUNET_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 | */ | ||
94 | int | ||
95 | GNUNET_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 | */ | ||
132 | int | ||
133 | GNUNET_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 | |||
164 | int | ||
165 | GNUNET_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 | ||
15 | extern "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 | |||
47 | enum 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 | |||
91 | struct 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 | }; | ||
102 | typedef struct mi_results_struct mi_results; | ||
103 | |||
104 | struct 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 | }; | ||
116 | typedef struct mi_output_struct mi_output; | ||
117 | |||
118 | typedef void (*stream_cb)(const char *, void *); | ||
119 | typedef void (*async_cb)(mi_output *o, void *); | ||
120 | typedef int (*tm_cb)(void *); | ||
121 | |||
122 | /* Values of this structure shouldn't be manipulated by the user. */ | ||
123 | struct 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 | }; | ||
165 | typedef struct mi_h_struct mi_h; | ||
166 | |||
167 | #define MI_TO(a) ((a)->to_gdb[1]) | ||
168 | |||
169 | enum mi_bkp_type { t_unknown=0, t_breakpoint=1, t_hw=2 }; | ||
170 | enum mi_bkp_disp { d_unknown=0, d_keep=1, d_del=2 }; | ||
171 | enum mi_bkp_mode { m_file_line=0, m_function=1, m_file_function=2, m_address=3 }; | ||
172 | |||
173 | struct 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 | }; | ||
193 | typedef struct mi_bkpt_struct mi_bkpt; | ||
194 | |||
195 | enum mi_wp_mode { wm_unknown=0, wm_write=1, wm_read=2, wm_rw=3 }; | ||
196 | |||
197 | struct 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 | }; | ||
207 | typedef struct mi_wp_struct mi_wp; | ||
208 | |||
209 | struct 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 | }; | ||
224 | typedef struct mi_frames_struct mi_frames; | ||
225 | |||
226 | struct mi_aux_term_struct | ||
227 | { | ||
228 | pid_t pid; | ||
229 | char *tty; | ||
230 | }; | ||
231 | typedef struct mi_aux_term_struct mi_aux_term; | ||
232 | |||
233 | struct mi_pty_struct | ||
234 | { | ||
235 | char *slave; | ||
236 | int master; | ||
237 | }; | ||
238 | typedef struct mi_pty_struct mi_pty; | ||
239 | |||
240 | enum 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 }; | ||
244 | enum 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 | |||
250 | struct 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 | }; | ||
280 | typedef struct mi_gvar_struct mi_gvar; | ||
281 | |||
282 | struct 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 | }; | ||
291 | typedef struct mi_gvar_chg_struct mi_gvar_chg; | ||
292 | |||
293 | |||
294 | /* A list of assembler instructions. */ | ||
295 | struct 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 | }; | ||
304 | typedef struct mi_asm_insn_struct mi_asm_insn; | ||
305 | |||
306 | /* A list of source lines containing assembler instructions. */ | ||
307 | struct 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 | }; | ||
315 | typedef struct mi_asm_insns_struct mi_asm_insns; | ||
316 | |||
317 | /* Changed register. */ | ||
318 | struct 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 | }; | ||
327 | typedef struct mi_chg_reg_struct mi_chg_reg; | ||
328 | |||
329 | /* | ||
330 | Examining gdb sources and looking at docs I can see the following "stop" | ||
331 | reasons: | ||
332 | |||
333 | Breakpoints: | ||
334 | a) breakpoint-hit (bkptno) + frame | ||
335 | Also: without reason for temporal breakpoints. | ||
336 | |||
337 | Watchpoints: | ||
338 | b) watchpoint-trigger (wpt={number,exp};value={old,new}) + frame | ||
339 | c) read-watchpoint-trigger (hw-rwpt{number,exp};value={value}) + frame | ||
340 | d) access-watchpoint-trigger (hw-awpt{number,exp};value={[old,]new}) + frame | ||
341 | e) watchpoint-scope (wpnum) + frame | ||
342 | |||
343 | Movement: | ||
344 | f) function-finished ([gdb-result-var,return-value]) + frame | ||
345 | g) location-reached + frame | ||
346 | h) end-stepping-range + frame | ||
347 | |||
348 | Exit: | ||
349 | i) exited-signalled (signal-name,signal-meaning) | ||
350 | j) exited (exit-code) | ||
351 | k) exited-normally | ||
352 | |||
353 | Signal: | ||
354 | l) signal-received (signal-name,signal-meaning) + frame | ||
355 | |||
356 | Plus: thread-id | ||
357 | */ | ||
358 | enum 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 | |||
368 | struct 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 | }; | ||
396 | typedef struct mi_stop_struct mi_stop; | ||
397 | |||
398 | /* Variable containing the last error. */ | ||
399 | extern int mi_error; | ||
400 | extern char *mi_error_from_gdb; | ||
401 | const char *mi_get_error_str(); | ||
402 | |||
403 | /* Indicate the name of gdb exe. Default is /usr/bin/gdb */ | ||
404 | void mi_set_gdb_exe(const char *name); | ||
405 | const char *mi_get_gdb_exe(); | ||
406 | /* Indicate the name of a file containing commands to send at start-up */ | ||
407 | void mi_set_gdb_start(const char *name); | ||
408 | const char *mi_get_gdb_start(); | ||
409 | /* Indicate the name of a file containing commands to send after connection */ | ||
410 | void mi_set_gdb_conn(const char *name); | ||
411 | const char *mi_get_gdb_conn(); | ||
412 | void mi_send_target_commands(mi_h *h); | ||
413 | /* Connect to a local copy of gdb. */ | ||
414 | mi_h *mi_connect_local(); | ||
415 | /* Close connection. You should ask gdb to quit first. */ | ||
416 | void mi_disconnect(mi_h *h); | ||
417 | /* Force MI version. */ | ||
418 | #define MI_VERSION2U(maj,mid,min) (maj*0x1000000+mid*0x10000+min) | ||
419 | void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle, | ||
420 | unsigned vMinor); | ||
421 | void mi_set_workaround(unsigned wa, int enable); | ||
422 | int mi_get_workaround(unsigned wa); | ||
423 | /* Parse gdb output. */ | ||
424 | mi_output *mi_parse_gdb_output(const char *str); | ||
425 | /* Functions to set/get the tunneled streams callbacks. */ | ||
426 | void mi_set_console_cb(mi_h *h, stream_cb cb, void *data); | ||
427 | void mi_set_target_cb(mi_h *h, stream_cb cb, void *data); | ||
428 | void mi_set_log_cb(mi_h *h, stream_cb cb, void *data); | ||
429 | stream_cb mi_get_console_cb(mi_h *h, void **data); | ||
430 | stream_cb mi_get_target_cb(mi_h *h, void **data); | ||
431 | stream_cb mi_get_log_cb(mi_h *h, void **data); | ||
432 | /* The callback to deal with async events. */ | ||
433 | void mi_set_async_cb(mi_h *h, async_cb cb, void *data); | ||
434 | async_cb mi_get_async_cb(mi_h *h, void **data); | ||
435 | /* Time out in gdb responses. */ | ||
436 | void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data); | ||
437 | tm_cb mi_get_time_out_cb(mi_h *h, void **data); | ||
438 | void mi_set_time_out(mi_h *h, int to); | ||
439 | int mi_get_time_out(mi_h *h); | ||
440 | /* Callbacks to "see" the dialog with gdb. */ | ||
441 | void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data); | ||
442 | void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data); | ||
443 | stream_cb mi_get_to_gdb_cb(mi_h *h, void **data); | ||
444 | stream_cb mi_get_from_gdb_cb(mi_h *h, void **data); | ||
445 | /* Sends a message to gdb. */ | ||
446 | int mi_send(mi_h *h, const char *format, ...); | ||
447 | /* Wait until gdb sends a response. */ | ||
448 | mi_output *mi_get_response_blk(mi_h *h); | ||
449 | /* Check if gdb sent a complete response. Use with mi_retire_response. */ | ||
450 | int mi_get_response(mi_h *h); | ||
451 | /* Get the last response. Use with mi_get_response. */ | ||
452 | mi_output *mi_retire_response(mi_h *h); | ||
453 | /* Look for a result record in gdb output. */ | ||
454 | mi_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. */ | ||
458 | int mi_get_async_stop_reason(mi_output *r, char **reason); | ||
459 | mi_stop *mi_get_stopped(mi_results *r); | ||
460 | mi_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. */ | ||
463 | int mi_res_simple_exit(mi_h *h); | ||
464 | int mi_res_simple_done(mi_h *h); | ||
465 | int mi_res_simple_running(mi_h *h); | ||
466 | int mi_res_simple_connected(mi_h *h); | ||
467 | /* It additionally extracts an specified variable. */ | ||
468 | mi_results *mi_res_done_var(mi_h *h, const char *var); | ||
469 | /* Extract a frames list from the response. */ | ||
470 | mi_frames *mi_res_frames_array(mi_h *h, const char *var); | ||
471 | mi_frames *mi_res_frames_list(mi_h *h); | ||
472 | mi_frames *mi_parse_frame(mi_results *c); | ||
473 | mi_frames *mi_res_frame(mi_h *h); | ||
474 | /* Create an auxiliar terminal using xterm. */ | ||
475 | mi_aux_term *gmi_start_xterm(); | ||
476 | /* Indicate the name of xterm exe. Default is /usr/bin/X11/xterm */ | ||
477 | void mi_set_xterm_exe(const char *name); | ||
478 | const char *mi_get_xterm_exe(); | ||
479 | /* Kill the auxiliar terminal and release the structure. */ | ||
480 | void gmi_end_aux_term(mi_aux_term *t); | ||
481 | /* Look for a free Linux VT for the child. */ | ||
482 | mi_aux_term *gmi_look_for_free_vt(); | ||
483 | /* Look for a free and usable Linux VT. */ | ||
484 | int mi_look_for_free_vt(); | ||
485 | /* Close master and release the structure. */ | ||
486 | void gmi_end_pty(mi_pty *p); | ||
487 | /* Look for a free pseudo terminal. */ | ||
488 | mi_pty *gmi_look_for_free_pty(); | ||
489 | /* Extract a list of thread IDs from response. */ | ||
490 | int mi_res_thread_ids(mi_h *h, int **list); | ||
491 | int mi_get_thread_ids(mi_output *res, int **list); | ||
492 | /* A variable response. */ | ||
493 | mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression); | ||
494 | enum mi_gvar_fmt mi_format_str_to_enum(const char *format); | ||
495 | const char *mi_format_enum_to_str(enum mi_gvar_fmt format); | ||
496 | char mi_format_enum_to_char(enum mi_gvar_fmt format); | ||
497 | enum mi_gvar_lang mi_lang_str_to_enum(const char *lang); | ||
498 | const char *mi_lang_enum_to_str(enum mi_gvar_lang lang); | ||
499 | int mi_res_changelist(mi_h *h, mi_gvar_chg **changed); | ||
500 | int mi_res_children(mi_h *h, mi_gvar *v); | ||
501 | mi_bkpt *mi_res_bkpt(mi_h *h); | ||
502 | mi_wp *mi_res_wp(mi_h *h); | ||
503 | char *mi_res_value(mi_h *h); | ||
504 | mi_stop *mi_res_stop(mi_h *h); | ||
505 | enum mi_stop_reason mi_reason_str_to_enum(const char *s); | ||
506 | const char *mi_reason_enum_to_str(enum mi_stop_reason r); | ||
507 | int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na, | ||
508 | unsigned long *addr); | ||
509 | mi_asm_insns *mi_get_asm_insns(mi_h *h); | ||
510 | /* Starting point of the program. */ | ||
511 | void mi_set_main_func(const char *name); | ||
512 | const char *mi_get_main_func(); | ||
513 | mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many); | ||
514 | int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l); | ||
515 | mi_chg_reg *mi_get_list_changed_regs(mi_h *h); | ||
516 | int mi_get_reg_values(mi_h *h, mi_chg_reg *l); | ||
517 | mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many); | ||
518 | int gmi_target_download(mi_h *h); | ||
519 | |||
520 | /* Allocation functions: */ | ||
521 | void *mi_calloc(size_t count, size_t sz); | ||
522 | void *mi_calloc1(size_t sz); | ||
523 | char *mi_malloc(size_t sz); | ||
524 | mi_results *mi_alloc_results(void); | ||
525 | mi_output *mi_alloc_output(void); | ||
526 | mi_frames *mi_alloc_frames(void); | ||
527 | mi_gvar *mi_alloc_gvar(void); | ||
528 | mi_gvar_chg *mi_alloc_gvar_chg(void); | ||
529 | mi_bkpt *mi_alloc_bkpt(void); | ||
530 | mi_wp *mi_alloc_wp(void); | ||
531 | mi_stop *mi_alloc_stop(void); | ||
532 | mi_asm_insns *mi_alloc_asm_insns(void); | ||
533 | mi_asm_insn *mi_alloc_asm_insn(void); | ||
534 | mi_chg_reg *mi_alloc_chg_reg(void); | ||
535 | void mi_free_output(mi_output *r); | ||
536 | void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r); | ||
537 | void mi_free_frames(mi_frames *f); | ||
538 | void mi_free_aux_term(mi_aux_term *t); | ||
539 | void mi_free_results(mi_results *r); | ||
540 | void mi_free_results_but(mi_results *r, mi_results *no); | ||
541 | void mi_free_gvar(mi_gvar *v); | ||
542 | void mi_free_gvar_chg(mi_gvar_chg *p); | ||
543 | void mi_free_wp(mi_wp *wp); | ||
544 | void mi_free_stop(mi_stop *s); | ||
545 | void mi_free_asm_insns(mi_asm_insns *i); | ||
546 | void mi_free_asm_insn(mi_asm_insn *i); | ||
547 | void mi_free_charp_list(char **l); | ||
548 | void mi_free_chg_reg(mi_chg_reg *r); | ||
549 | |||
550 | /* Porgram control: */ | ||
551 | /* Specify the executable and arguments for local debug. */ | ||
552 | int gmi_set_exec(mi_h *h, const char *file, const char *args); | ||
553 | /* Start running the executable. Remote sessions starts running. */ | ||
554 | int gmi_exec_run(mi_h *h); | ||
555 | /* Continue the execution after a "stop". */ | ||
556 | int gmi_exec_continue(mi_h *h); | ||
557 | /* Indicate which terminal will use the target program. For local sessions. */ | ||
558 | int gmi_target_terminal(mi_h *h, const char *tty_name); | ||
559 | /* Specify what's the local copy that have debug info. For remote sessions. */ | ||
560 | int 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. */ | ||
563 | int gmi_exec_finish(mi_h *h); | ||
564 | /* Stop the program using SIGINT. */ | ||
565 | int gmi_exec_interrupt(mi_h *h); | ||
566 | /* Next line of code. */ | ||
567 | int gmi_exec_next(mi_h *h); | ||
568 | /* Next count lines of code. */ | ||
569 | int gmi_exec_next_cnt(mi_h *h, int count); | ||
570 | /* Next line of assembler code. */ | ||
571 | int gmi_exec_next_instruction(mi_h *h); | ||
572 | /* Next line of code. Get inside functions. */ | ||
573 | int gmi_exec_step(mi_h *h); | ||
574 | /* Next count lines of code. Get inside functions. */ | ||
575 | int gmi_exec_step_cnt(mi_h *h, int count); | ||
576 | /* Next line of assembler code. Get inside calls. */ | ||
577 | int gmi_exec_step_instruction(mi_h *h); | ||
578 | /* Execute until location is reached. If file is NULL then is until next line. */ | ||
579 | int gmi_exec_until(mi_h *h, const char *file, int line); | ||
580 | int gmi_exec_until_addr(mi_h *h, void *addr); | ||
581 | /* Return to previous frame inmediatly. */ | ||
582 | mi_frames *gmi_exec_return(mi_h *h); | ||
583 | /* Just kill the program. Please read the notes in prg_control.c. */ | ||
584 | int gmi_exec_kill(mi_h *h); | ||
585 | |||
586 | /* Target manipulation: */ | ||
587 | /* Connect to a remote gdbserver using the specified methode. */ | ||
588 | int gmi_target_select(mi_h *h, const char *type, const char *params); | ||
589 | /* Attach to an already running process. */ | ||
590 | mi_frames *gmi_target_attach(mi_h *h, pid_t pid); | ||
591 | /* Detach from an attached process. */ | ||
592 | int gmi_target_detach(mi_h *h); | ||
593 | |||
594 | /* Miscellaneous commands: */ | ||
595 | /* Exit gdb killing the child is it is running. */ | ||
596 | void gmi_gdb_exit(mi_h *h); | ||
597 | /* Send the version to the console. */ | ||
598 | int gmi_gdb_version(mi_h *h); | ||
599 | /* Set a gdb variable. */ | ||
600 | int gmi_gdb_set(mi_h *h, const char *var, const char *val); | ||
601 | /* Get a gdb variable. */ | ||
602 | char *gmi_gdb_show(mi_h *h, const char *var); | ||
603 | |||
604 | /* Breakpoints manipulation: */ | ||
605 | /* Insert a breakpoint at file:line. */ | ||
606 | mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line); | ||
607 | /* Insert a breakpoint, all available options. */ | ||
608 | mi_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); | ||
611 | mi_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. */ | ||
615 | int gmi_break_delete(mi_h *h, int number); | ||
616 | /* Free the memory used for a breakpoint description. */ | ||
617 | void mi_free_bkpt(mi_bkpt *b); | ||
618 | /* Modify the "ignore" count for a breakpoint. */ | ||
619 | int gmi_break_set_times(mi_h *h, int number, int count); | ||
620 | /* Associate a condition with the breakpoint. */ | ||
621 | int gmi_break_set_condition(mi_h *h, int number, const char *condition); | ||
622 | /* Enable or disable a breakpoint. */ | ||
623 | int gmi_break_state(mi_h *h, int number, int enable); | ||
624 | /* Set a watchpoint. It doesn't work for remote targets! */ | ||
625 | mi_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. */ | ||
629 | char *gmi_data_evaluate_expression(mi_h *h, const char *expression); | ||
630 | /* Path for sources. */ | ||
631 | int gmi_dir(mi_h *h, const char *path); | ||
632 | /* A very limited "data read memory" implementation. */ | ||
633 | int gmi_read_memory(mi_h *h, const char *exp, unsigned size, | ||
634 | unsigned char *dest, int *na, int convAddr, | ||
635 | unsigned long *addr); | ||
636 | mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start, | ||
637 | const char *end, int mode); | ||
638 | mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line, | ||
639 | int lines, int mode); | ||
640 | mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many); | ||
641 | int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l); | ||
642 | mi_chg_reg *gmi_data_list_changed_registers(mi_h *h); | ||
643 | int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l); | ||
644 | mi_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. */ | ||
648 | mi_frames *gmi_stack_list_frames(mi_h *h); | ||
649 | /* List of frames. Indicating a range. */ | ||
650 | mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to); | ||
651 | /* List arguments. Only level and args filled. */ | ||
652 | mi_frames *gmi_stack_list_arguments(mi_h *h, int show); | ||
653 | /* List arguments. Indicating a range. Only level and args filled. */ | ||
654 | mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to); | ||
655 | /* Information about the current frame, including args. */ | ||
656 | mi_frames *gmi_stack_info_frame(mi_h *h); | ||
657 | /* Stack info depth. error => -1 */ | ||
658 | int gmi_stack_info_depth_get(mi_h *h); | ||
659 | /* Set stack info depth. error => -1 */ | ||
660 | int gmi_stack_info_depth(mi_h *h, int max_depth); | ||
661 | /* Change current frame. */ | ||
662 | int gmi_stack_select_frame(mi_h *h, int framenum); | ||
663 | /* List of local vars. */ | ||
664 | mi_results *gmi_stack_list_locals(mi_h *h, int show); | ||
665 | |||
666 | /* Thread. */ | ||
667 | /* List available thread ids. */ | ||
668 | int gmi_thread_list_ids(mi_h *h, int **list); | ||
669 | /* Select a thread. */ | ||
670 | mi_frames *gmi_thread_select(mi_h *h, int id); | ||
671 | /* List available threads. */ | ||
672 | mi_frames *gmi_thread_list_all_threads(mi_h *h); | ||
673 | |||
674 | /* Variable objects. */ | ||
675 | /* Create a variable object. */ | ||
676 | mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp); | ||
677 | mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp); | ||
678 | /* Create the variable and also fill the lang and attr fields. */ | ||
679 | mi_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. */ | ||
681 | int gmi_var_delete(mi_h *h, mi_gvar *var); | ||
682 | /* Set the format used to represent the result. */ | ||
683 | int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format); | ||
684 | /* Fill the format field with info from gdb. */ | ||
685 | int gmi_var_show_format(mi_h *h, mi_gvar *var); | ||
686 | /* Fill the numchild field with info from gdb. */ | ||
687 | int gmi_var_info_num_children(mi_h *h, mi_gvar *var); | ||
688 | /* Fill the type field with info from gdb. */ | ||
689 | int 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. */ | ||
692 | int 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. */ | ||
695 | int 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. */ | ||
698 | int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed); | ||
699 | /* Change variable. Fills the value field. */ | ||
700 | int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression); | ||
701 | /* Get current value for a variable. */ | ||
702 | int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var); | ||
703 | /* List children. It ONLY returns the first level information. :-( */ | ||
704 | int 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 | ||
9 | pointers. Alloc functions must set mi_error. @<p> | ||
10 | |||
11 | ***************************************************************************/ | ||
12 | |||
13 | #include "gdbmi.h" | ||
14 | |||
15 | void *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 | |||
23 | void *mi_calloc1(size_t sz) | ||
24 | { | ||
25 | return mi_calloc(1,sz); | ||
26 | } | ||
27 | |||
28 | char *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 | |||
36 | mi_results *mi_alloc_results(void) | ||
37 | { | ||
38 | return (mi_results *)mi_calloc1(sizeof(mi_results)); | ||
39 | } | ||
40 | |||
41 | mi_output *mi_alloc_output(void) | ||
42 | { | ||
43 | return (mi_output *)mi_calloc1(sizeof(mi_output)); | ||
44 | } | ||
45 | |||
46 | mi_frames *mi_alloc_frames(void) | ||
47 | { | ||
48 | return (mi_frames *)mi_calloc1(sizeof(mi_frames)); | ||
49 | } | ||
50 | |||
51 | mi_gvar *mi_alloc_gvar(void) | ||
52 | { | ||
53 | return (mi_gvar *)mi_calloc1(sizeof(mi_gvar)); | ||
54 | } | ||
55 | |||
56 | mi_gvar_chg *mi_alloc_gvar_chg(void) | ||
57 | { | ||
58 | return (mi_gvar_chg *)mi_calloc1(sizeof(mi_gvar_chg)); | ||
59 | } | ||
60 | |||
61 | mi_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 | |||
72 | mi_wp *mi_alloc_wp(void) | ||
73 | { | ||
74 | return (mi_wp *)mi_calloc1(sizeof(mi_wp)); | ||
75 | } | ||
76 | |||
77 | mi_stop *mi_alloc_stop(void) | ||
78 | { | ||
79 | return (mi_stop *)mi_calloc1(sizeof(mi_stop)); | ||
80 | } | ||
81 | |||
82 | mi_asm_insns *mi_alloc_asm_insns(void) | ||
83 | { | ||
84 | return (mi_asm_insns *)mi_calloc1(sizeof(mi_asm_insns)); | ||
85 | } | ||
86 | |||
87 | mi_asm_insn *mi_alloc_asm_insn(void) | ||
88 | { | ||
89 | return (mi_asm_insn *)mi_calloc1(sizeof(mi_asm_insn)); | ||
90 | } | ||
91 | |||
92 | mi_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 | |||
101 | void 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 | |||
117 | void 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 | |||
133 | void 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 | |||
151 | void 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 | |||
165 | void 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 | |||
197 | void mi_free_results(mi_results *r) | ||
198 | { | ||
199 | mi_free_results_but(r,NULL); | ||
200 | } | ||
201 | |||
202 | void 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 | |||
225 | void mi_free_output(mi_output *r) | ||
226 | { | ||
227 | mi_free_output_but(r,NULL,NULL); | ||
228 | } | ||
229 | |||
230 | void 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 | |||
245 | void 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 | |||
257 | void 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 | |||
271 | void 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 | |||
296 | void 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> | ||
11 | gdb 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 | ||
25 | be implemented when I have more time. @<p> | ||
26 | |||
27 | ***************************************************************************/ | ||
28 | |||
29 | #include "gdbmi.h" | ||
30 | |||
31 | /* Low level versions. */ | ||
32 | |||
33 | void 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 | |||
38 | void 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 | |||
69 | void 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 | |||
89 | void mi_break_delete(mi_h *h, int number) | ||
90 | { | ||
91 | mi_send(h,"-break-delete %d\n",number); | ||
92 | } | ||
93 | |||
94 | void mi_break_after(mi_h *h, int number, int count) | ||
95 | { | ||
96 | mi_send(h,"-break-after %d %d\n",number,count); | ||
97 | } | ||
98 | |||
99 | void 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 | |||
104 | void mi_break_enable(mi_h *h, int number) | ||
105 | { | ||
106 | mi_send(h,"-break-enable %d\n",number); | ||
107 | } | ||
108 | |||
109 | void mi_break_disable(mi_h *h, int number) | ||
110 | { | ||
111 | mi_send(h,"-break-disable %d\n",number); | ||
112 | } | ||
113 | |||
114 | void 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 | ||
131 | error. | ||
132 | |||
133 | ***************************************************************************/ | ||
134 | |||
135 | mi_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 | ||
148 | error. | ||
149 | |||
150 | ***************************************************************************/ | ||
151 | |||
152 | mi_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 | ||
167 | error. | ||
168 | |||
169 | ***************************************************************************/ | ||
170 | |||
171 | mi_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 | ||
186 | console. | ||
187 | |||
188 | ***************************************************************************/ | ||
189 | |||
190 | int 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 | ||
203 | console. | ||
204 | |||
205 | ***************************************************************************/ | ||
206 | |||
207 | int 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 | |||
223 | int 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 | ||
236 | console. | ||
237 | |||
238 | ***************************************************************************/ | ||
239 | |||
240 | int 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 | ||
256 | error. | ||
257 | |||
258 | ***************************************************************************/ | ||
259 | |||
260 | mi_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 | ||
9 | gdb. | ||
10 | @<p> | ||
11 | |||
12 | GDB Bug workaround for "file -readnow": I tried to workaround a bug using | ||
13 | it but looks like this option also have bugs!!!! so I have to use the | ||
14 | command line option --readnow. | ||
15 | It also have a bug!!!! when the binary is changed and gdb must reload it | ||
16 | this option is ignored. So it looks like we have no solution but 3 gdb bugs | ||
17 | in 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 | |||
45 | int mi_error=MI_OK; | ||
46 | char *mi_error_from_gdb=NULL; | ||
47 | static char *gdb_exe=NULL; | ||
48 | static char *xterm_exe=NULL; | ||
49 | static char *gdb_start=NULL; | ||
50 | static char *gdb_conn=NULL; | ||
51 | static char *main_func=NULL; | ||
52 | static char disable_psym_search_workaround=0; | ||
53 | |||
54 | mi_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 | |||
67 | int 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 | |||
83 | int mi_check_running(mi_h *h) | ||
84 | { | ||
85 | return !h->died && mi_check_running_pid(h->pid); | ||
86 | } | ||
87 | |||
88 | void 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 | |||
100 | void 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 | |||
127 | void 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 | |||
135 | int 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 | |||
165 | char *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 | |||
172 | int 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 | |||
257 | mi_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 | |||
264 | mi_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 | |||
318 | void 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 | |||
341 | void 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 | ||
350 | similar to a "FILE *" for stdio. | ||
351 | |||
352 | Return: A new mi_h structure or NULL on error. | ||
353 | |||
354 | ***************************************************************************/ | ||
355 | |||
356 | mi_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 | |||
438 | void 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 | |||
445 | void mi_set_console_cb(mi_h *h, stream_cb cb, void *data) | ||
446 | { | ||
447 | h->console=cb; | ||
448 | h->console_data=data; | ||
449 | } | ||
450 | |||
451 | void mi_set_target_cb(mi_h *h, stream_cb cb, void *data) | ||
452 | { | ||
453 | h->target=cb; | ||
454 | h->target_data=data; | ||
455 | } | ||
456 | |||
457 | void mi_set_log_cb(mi_h *h, stream_cb cb, void *data) | ||
458 | { | ||
459 | h->log=cb; | ||
460 | h->log_data=data; | ||
461 | } | ||
462 | |||
463 | stream_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 | |||
470 | stream_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 | |||
477 | stream_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 | |||
484 | void mi_set_async_cb(mi_h *h, async_cb cb, void *data) | ||
485 | { | ||
486 | h->async=cb; | ||
487 | h->async_data=data; | ||
488 | } | ||
489 | |||
490 | async_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 | |||
497 | void 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 | |||
503 | void 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 | |||
509 | stream_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 | |||
516 | stream_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 | |||
523 | void 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 | |||
529 | tm_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 | |||
536 | void mi_set_time_out(mi_h *h, int to) | ||
537 | { | ||
538 | h->time_out=to; | ||
539 | } | ||
540 | |||
541 | int mi_get_time_out(mi_h *h) | ||
542 | { | ||
543 | return h->time_out; | ||
544 | } | ||
545 | |||
546 | int 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 | |||
574 | void 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 | |||
588 | void 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 | |||
598 | void 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 | |||
605 | void 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 | |||
612 | void 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 | |||
619 | static | ||
620 | char *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 | |||
647 | const 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 | |||
658 | const char *mi_get_gdb_start() | ||
659 | { | ||
660 | return gdb_start; | ||
661 | } | ||
662 | |||
663 | const char *mi_get_gdb_conn() | ||
664 | { | ||
665 | return gdb_conn; | ||
666 | } | ||
667 | |||
668 | void 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 | |||
675 | const 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 | |||
686 | void 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 | |||
693 | const 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 | ||
706 | release it. | ||
707 | |||
708 | ***************************************************************************/ | ||
709 | |||
710 | mi_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 | |||
812 | void 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 | |||
827 | void 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 | ||
840 | force it manually. GDB 5.x implemented MI v1 and 6.x v2. | ||
841 | |||
842 | ***************************************************************************/ | ||
843 | |||
844 | void 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 | |||
857 | void 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 | |||
876 | int 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> | ||
13 | gdb 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 | |||
31 | Notes: @<p> | ||
32 | |||
33 | 1) -display* aren't implemented. You can use CLI command display, but the | ||
34 | results are sent to the console. So it looks like the best is to manually | ||
35 | use -data-evaluate-expression to emulate it. @<p> | ||
36 | |||
37 | 2) GDB bug mi/1770: Affects gdb<=6.2, when you ask for the names of the | ||
38 | registers you get it plus the name of the "pseudo-registers", but if you | ||
39 | try to get the value of a pseudo-register you get an error saying the | ||
40 | register number is invalid. I reported to gdb-patches@sources.redhat.com | ||
41 | on 2004/08/25 and as I didn't get any answer I filled a bug report on | ||
42 | 2004/09/02. The patch to fix this annoying bug is: | ||
43 | |||
44 | Index: gdb/mi/mi-main.c | ||
45 | =================================================================== | ||
46 | RCS file: /cvs/src/src/gdb/mi/mi-main.c,v | ||
47 | retrieving revision 1.64 | ||
48 | diff -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 | |||
62 | Note I had to remove an end of comment in the patch to include it here. | ||
63 | This bug forced me to create another set of functions. The only way is to | ||
64 | first get the values and then the names. | ||
65 | Fixed by Changelog entry: | ||
66 | |||
67 | 2004-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 | |||
81 | void mi_data_evaluate_expression(mi_h *h, const char *expression) | ||
82 | { | ||
83 | mi_send(h,"-data-evaluate-expression \"%s\"\n",expression); | ||
84 | } | ||
85 | |||
86 | void 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 | |||
101 | void 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 | |||
110 | void 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 | |||
116 | void 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 | |||
123 | void mi_data_list_register_names(mi_h *h) | ||
124 | { | ||
125 | mi_send(h,"-data-list-register-names\n"); | ||
126 | } | ||
127 | |||
128 | void 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 | |||
139 | void mi_data_list_changed_registers(mi_h *h) | ||
140 | { | ||
141 | mi_send(h,"-data-list-changed-registers\n"); | ||
142 | } | ||
143 | |||
144 | void 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 | |||
167 | char *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 | ||
177 | the program to debug. Only the MI v1 implementation is available. | ||
178 | |||
179 | Command: -environment-directory | ||
180 | Return: !=0 OK | ||
181 | |||
182 | ***************************************************************************/ | ||
183 | |||
184 | int gmi_dir(mi_h *h, const char *path) | ||
185 | { | ||
186 | mi_dir(h,path); | ||
187 | return mi_res_simple_done(h); | ||
188 | } | ||
189 | |||
190 | int 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 | |||
198 | mi_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 | |||
205 | mi_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 | ||
213 | mi_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 | |||
219 | int 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 | |||
225 | mi_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 | |||
232 | int 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 | |||
238 | mi_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 | |||
14 | static | ||
15 | const 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 | |||
33 | const 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 | |||
47 | int 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 | |||
65 | int 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 | |||
78 | int 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 | ||
90 | release it. | ||
91 | |||
92 | ***************************************************************************/ | ||
93 | |||
94 | mi_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 | |||
111 | void 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 | |||
126 | void 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 | ||
10 | created by Marek Habersack and then modified by George Foot. I addapted it | ||
11 | to 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 | |||
29 | int mi_look_for_free_vt() | ||
30 | { | ||
31 | return -1; | ||
32 | } | ||
33 | |||
34 | mi_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 | |||
53 | int 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 | ||
135 | release it. | ||
136 | |||
137 | ***************************************************************************/ | ||
138 | |||
139 | mi_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> | ||
11 | gdb command: Implemented? | ||
12 | |||
13 | -gdb-exit Yes | ||
14 | -gdb-set Yes | ||
15 | -gdb-show Yes | ||
16 | -gdb-version Yes | ||
17 | @</pre> | ||
18 | |||
19 | GDB Bug workaround for "-gdb-show architecture": gdb 6.1 and olders doesn't | ||
20 | report it in "value", but they give the output of "show architecture". In | ||
21 | 6.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 | |||
31 | void mi_gdb_exit(mi_h *h) | ||
32 | { | ||
33 | mi_send(h,"-gdb-exit\n"); | ||
34 | } | ||
35 | |||
36 | void mi_gdb_version(mi_h *h) | ||
37 | { | ||
38 | mi_send(h,"-gdb-version\n"); | ||
39 | } | ||
40 | |||
41 | void 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 | |||
46 | void 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 | |||
65 | void 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 | |||
81 | int 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 | |||
97 | int 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 | |||
113 | char *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 | ||
9 | tree (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 | |||
18 | mi_results *mi_get_result(const char *str, const char **end); | ||
19 | int 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""" | ||
24 | Afects gdb 2002-04-01-cvs and 6.1.1 for sure. | ||
25 | That's an heuristical workaround. | ||
26 | */ | ||
27 | static inline | ||
28 | int EndOfStr(const char *s) | ||
29 | { | ||
30 | if (*s=='"') | ||
31 | { | ||
32 | s++; | ||
33 | return !*s || *s==',' || *s==']' || *s=='}'; | ||
34 | } | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | int 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_- */ | ||
95 | inline | ||
96 | int mi_is_var_name_char(char c) | ||
97 | { | ||
98 | return isalnum(c) || c=='-' || c=='_'; | ||
99 | } | ||
100 | |||
101 | char *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 | |||
127 | int 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__ | ||
156 | int 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 | |||
192 | int 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 | |||
215 | int 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 | |||
250 | int 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 | |||
270 | int 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 | |||
285 | mi_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 | |||
311 | mi_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 | |||
341 | mi_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 | |||
380 | mi_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 | |||
402 | mi_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 | |||
408 | mi_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 | |||
414 | mi_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 | |||
420 | mi_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 | |||
433 | mi_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 | |||
439 | mi_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 | |||
445 | mi_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 | |||
451 | mi_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 | |||
483 | mi_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 | |||
496 | mi_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 | |||
507 | mi_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 | |||
514 | int 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 | |||
552 | mi_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 | |||
572 | int 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 | |||
588 | int mi_res_simple_done(mi_h *h) | ||
589 | { | ||
590 | return mi_res_simple(h,MI_CL_DONE,0); | ||
591 | } | ||
592 | |||
593 | int mi_res_simple_exit(mi_h *h) | ||
594 | { | ||
595 | return mi_res_simple(h,MI_CL_EXIT,1); | ||
596 | } | ||
597 | |||
598 | int mi_res_simple_running(mi_h *h) | ||
599 | { | ||
600 | return mi_res_simple(h,MI_CL_RUNNING,0); | ||
601 | } | ||
602 | |||
603 | int mi_res_simple_connected(mi_h *h) | ||
604 | { | ||
605 | return mi_res_simple(h,MI_CL_CONNECTED,0); | ||
606 | } | ||
607 | |||
608 | mi_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 | |||
625 | mi_results *mi_res_done_var(mi_h *h, const char *var) | ||
626 | { | ||
627 | return mi_res_var(h,var,MI_CL_DONE); | ||
628 | } | ||
629 | |||
630 | mi_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 | |||
674 | mi_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 | |||
685 | mi_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 | |||
722 | mi_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 | |||
754 | int 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 | |||
789 | int 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 | |||
802 | enum 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 | |||
816 | const 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 | |||
839 | enum 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 | |||
855 | const 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 | |||
885 | char 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 | |||
915 | mi_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 | |||
976 | mi_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 | |||
989 | mi_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 | |||
1028 | int 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 | |||
1120 | int 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 | |||
1184 | int 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 | |||
1216 | mi_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 | |||
1277 | mi_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 | |||
1288 | mi_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 | |||
1316 | mi_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 | |||
1344 | mi_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 | |||
1359 | char *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 | |||
1373 | mi_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 | |||
1385 | static | ||
1386 | char *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 | |||
1402 | static | ||
1403 | enum 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 | |||
1412 | static | ||
1413 | char *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 | |||
1429 | enum 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 | |||
1439 | const 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 | |||
1451 | mi_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 | |||
1539 | mi_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 | |||
1555 | int 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 | |||
1604 | mi_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 | |||
1654 | mi_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 | |||
1714 | mi_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 | |||
1725 | mi_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 | |||
1755 | mi_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 | |||
1766 | mi_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 | |||
1788 | mi_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 | |||
1799 | int 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 | |||
1836 | int 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 | |||
1847 | int 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 | |||
1864 | int 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 | |||
1875 | mi_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 | |||
1916 | mi_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> | ||
11 | gdb 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 | ||
36 | gmi_gdb_set("confirm","off") was called. @<p> | ||
37 | |||
38 | GDB Bug workaround for -file-exec-and-symbols and -file-symbol-file: This | ||
39 | is complex, but a real bug. When you set a breakpoint you never know the | ||
40 | name of the file as it appears in the debug info. So you can be specifying | ||
41 | an absolute file name or a relative file name. The reference point could be | ||
42 | different than the one used in the debug info. To solve all the combinations | ||
43 | gdb does a search trying various combinations. GDB isn't very smart so you | ||
44 | must at least specify the working directory and the directory where the | ||
45 | binary is located to get a good chance (+ user options to solve the rest). | ||
46 | Once 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). | ||
50 | This function calls openp indicating try_cwd_first. It makes the search file | ||
51 | if the psymtab file name have at least one dirseparator. It means that | ||
52 | psymtabs for files compiled with relative paths will fail. The search for | ||
53 | symtabs uses symtab_to_filename, it calls open_source_file which finally | ||
54 | calls openp without try_cwd_first.@* | ||
55 | To workaround this bug we must ensure gdb loads *all* the symtabs to memory. | ||
56 | And here comes another problem -file-exec-and-symbols doesn't support it | ||
57 | according to docs. In real life that's a wrapper for "file", but as nobody | ||
58 | can 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 | |||
67 | void 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 | |||
75 | void mi_exec_arguments(mi_h *h, const char *args) | ||
76 | { | ||
77 | mi_send(h,"-exec-arguments %s\n",args); | ||
78 | } | ||
79 | |||
80 | void mi_exec_run(mi_h *h) | ||
81 | { | ||
82 | mi_send(h,"-exec-run\n"); | ||
83 | } | ||
84 | |||
85 | void mi_exec_continue(mi_h *h) | ||
86 | { | ||
87 | mi_send(h,"-exec-continue\n"); | ||
88 | } | ||
89 | |||
90 | void mi_target_terminal(mi_h *h, const char *tty_name) | ||
91 | { | ||
92 | mi_send(h,"tty %s\n",tty_name); | ||
93 | } | ||
94 | |||
95 | void 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 | |||
103 | void mi_exec_finish(mi_h *h) | ||
104 | { | ||
105 | mi_send(h,"-exec-finish\n"); | ||
106 | } | ||
107 | |||
108 | void mi_exec_interrupt(mi_h *h) | ||
109 | { | ||
110 | mi_send(h,"-exec-interrupt\n"); | ||
111 | } | ||
112 | |||
113 | void 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 | |||
121 | void mi_exec_next_instruction(mi_h *h) | ||
122 | { | ||
123 | mi_send(h,"-exec-next-instruction\n"); | ||
124 | } | ||
125 | |||
126 | void 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 | |||
134 | void mi_exec_step_instruction(mi_h *h) | ||
135 | { | ||
136 | mi_send(h,"-exec-step-instruction\n"); | ||
137 | } | ||
138 | |||
139 | void 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 | |||
147 | void mi_exec_until_addr(mi_h *h, void *addr) | ||
148 | { | ||
149 | mi_send(h,"-exec-until *%p\n",addr); | ||
150 | } | ||
151 | |||
152 | void mi_exec_return(mi_h *h) | ||
153 | { | ||
154 | mi_send(h,"-exec-return\n"); | ||
155 | } | ||
156 | |||
157 | void 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 | |||
174 | int 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 | |||
195 | int 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 | |||
211 | int 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 | |||
228 | int 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 | |||
244 | int 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 | ||
254 | response. | ||
255 | |||
256 | Command: -exec-finish | ||
257 | Return: !=0 OK. | ||
258 | |||
259 | ***************************************************************************/ | ||
260 | |||
261 | int 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 | ||
272 | isn't really working. | ||
273 | |||
274 | Command: -exec-interrupt [replacement] | ||
275 | Return: Always 1 | ||
276 | Example: | ||
277 | |||
278 | ***************************************************************************/ | ||
279 | |||
280 | int 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 | |||
301 | int 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 | |||
317 | int 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 | |||
333 | int 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 | |||
349 | int 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 | |||
365 | int 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 | |||
381 | int 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 | ||
391 | line. | ||
392 | |||
393 | Command: -exec-until | ||
394 | Return: !=0 OK | ||
395 | |||
396 | ***************************************************************************/ | ||
397 | |||
398 | int 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 | |||
414 | int 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 | ||
427 | location. NULL on error. | ||
428 | |||
429 | ***************************************************************************/ | ||
430 | |||
431 | mi_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 | ||
441 | implemented by gdb. This implementation only works if the interactive mode | ||
442 | is disabled (gmi_gdb_set("confirm","off")). | ||
443 | |||
444 | Command: -exec-abort [using kill] | ||
445 | Return: !=0 OK | ||
446 | |||
447 | ***************************************************************************/ | ||
448 | |||
449 | int 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> | ||
11 | gdb 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 | |||
27 | void 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 | |||
35 | void 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 | |||
43 | void mi_stack_info_frame(mi_h *h) | ||
44 | { | ||
45 | mi_send(h,"frame\n"); | ||
46 | } | ||
47 | |||
48 | void 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 | |||
56 | void mi_stack_select_frame(mi_h *h, int framenum) | ||
57 | { | ||
58 | mi_send(h,"-stack-select-frame %d\n",framenum); | ||
59 | } | ||
60 | |||
61 | void 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 | |||
78 | mi_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 | |||
95 | mi_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 | |||
111 | mi_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 | ||
121 | frames 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 | |||
128 | mi_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 | |||
144 | mi_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 | |||
160 | int 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 | |||
186 | int 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 | |||
201 | int 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 | |||
217 | mi_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> | ||
11 | gdb 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 | |||
25 | Note:@p | ||
26 | |||
27 | Only 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 | |||
28 | void 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) */ | ||
34 | void mi_target_attach(mi_h *h, pid_t pid) | ||
35 | { | ||
36 | mi_send(h,"attach %d\n",pid); | ||
37 | } | ||
38 | |||
39 | void mi_target_detach(mi_h *h) | ||
40 | { | ||
41 | mi_send(h,"-target-detach\n"); | ||
42 | } | ||
43 | |||
44 | void 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 | |||
61 | int 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 | |||
80 | mi_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 | |||
97 | int 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 | |||
113 | int 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> | ||
11 | gdb 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 | |||
24 | void mi_thread_list_ids(mi_h *h) | ||
25 | { | ||
26 | mi_send(h,"-thread-list-ids\n"); | ||
27 | } | ||
28 | |||
29 | void mi_thread_select(mi_h *h, int id) | ||
30 | { | ||
31 | mi_send(h,"-thread-select %d\n",id); | ||
32 | } | ||
33 | |||
34 | void 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 | |||
51 | int 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 | |||
67 | mi_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 | ||
77 | thread". | ||
78 | |||
79 | Command: -thread-list-all-threads | ||
80 | Return: A kist of frames, NULL on error | ||
81 | |||
82 | ***************************************************************************/ | ||
83 | |||
84 | mi_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> | ||
12 | gdb 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 | |||
27 | Notes: @<p> | ||
28 | 1) I suggest letting gdb to choose the names for the variables.@* | ||
29 | 2) -var-list-children supports an optional "show values" argument in MI v2. | ||
30 | It 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 | |||
42 | void 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 | |||
52 | void mi_var_delete(mi_h *h, const char *name) | ||
53 | { | ||
54 | mi_send(h,"-var-delete %s\n",name); | ||
55 | } | ||
56 | |||
57 | void 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 | |||
62 | void mi_var_show_format(mi_h *h, const char *name) | ||
63 | { | ||
64 | mi_send(h,"-var-show-format \"%s\"\n",name); | ||
65 | } | ||
66 | |||
67 | void 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 | |||
72 | void mi_var_info_type(mi_h *h, const char *name) | ||
73 | { | ||
74 | mi_send(h,"-var-info-type \"%s\"\n",name); | ||
75 | } | ||
76 | |||
77 | void mi_var_info_expression(mi_h *h, const char *name) | ||
78 | { | ||
79 | mi_send(h,"-var-info-expression \"%s\"\n",name); | ||
80 | } | ||
81 | |||
82 | void mi_var_show_attributes(mi_h *h, const char *name) | ||
83 | { | ||
84 | mi_send(h,"-var-show-attributes \"%s\"\n",name); | ||
85 | } | ||
86 | |||
87 | void 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 | |||
95 | void 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 | |||
100 | void mi_var_evaluate_expression(mi_h *h, const char *name) | ||
101 | { | ||
102 | mi_send(h,"-var-evaluate-expression \"%s\"\n",name); | ||
103 | } | ||
104 | |||
105 | void 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 | ||
119 | gdb choose the names. | ||
120 | |||
121 | Command: -var-create | ||
122 | Return: A new mi_gvar strcture or NULL on error. | ||
123 | |||
124 | ***************************************************************************/ | ||
125 | |||
126 | mi_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 | |||
143 | mi_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 | |||
158 | int 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 | |||
174 | int 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 | |||
195 | int 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 | |||
211 | int 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 | |||
227 | int 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 | ||
237 | isn't filled during creation. | ||
238 | |||
239 | Command: -var-info-expression | ||
240 | Return: !=0 OK | ||
241 | |||
242 | ***************************************************************************/ | ||
243 | |||
244 | int 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 | ||
255 | during creation. | ||
256 | |||
257 | Command: -var-show-attributes | ||
258 | Return: !=0 OK | ||
259 | |||
260 | ***************************************************************************/ | ||
261 | |||
262 | int 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 | ||
272 | selected 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 | |||
279 | mi_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 | ||
294 | updated. | ||
295 | |||
296 | Command: -var-update | ||
297 | Return: !=0 OK. The changed list contains the list of changed vars. | ||
298 | |||
299 | ***************************************************************************/ | ||
300 | |||
301 | int 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 | |||
317 | int 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 | |||
341 | int 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 | |||
366 | int 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 | |||
33 | static const char *mode; | ||
34 | static const char *dumpFileName; | ||
35 | static const char *binaryName; | ||
36 | static const char *emailAddress; | ||
37 | static const char *edbFilePath; | ||
38 | static const char *gdbBinaryPath; | ||
39 | static const char *inspectExpression; | ||
40 | static const char *inspectFunction; | ||
41 | static 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 | */ | ||
51 | static void | ||
52 | run (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 | |||
153 | int | ||
154 | main (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 | |||
3 | int 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 | ||
32 | extern "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 | */ | ||
54 | struct 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 | |||
78 | int GNUNET_MONKEY_ACTION_report_file (struct GNUNET_MONKEY_ACTION_Context | ||
79 | *cntxt, const char *dumpFileName); | ||
80 | int GNUNET_MONKEY_ACTION_report_email (struct GNUNET_MONKEY_ACTION_Context | ||
81 | *cntxt); | ||
82 | int GNUNET_MONKEY_ACTION_inspect_expression_database (struct | ||
83 | GNUNET_MONKEY_ACTION_Context | ||
84 | *cntxt); | ||
85 | int GNUNET_MONKEY_ACTION_rerun_with_gdb (struct GNUNET_MONKEY_ACTION_Context | ||
86 | *cntxt); | ||
87 | int GNUNET_MONKEY_ACTION_rerun_with_valgrind (struct | ||
88 | GNUNET_MONKEY_ACTION_Context | ||
89 | *cntxt); | ||
90 | int GNUNET_MONKEY_ACTION_format_report (struct GNUNET_MONKEY_ACTION_Context | ||
91 | *cntxt); | ||
92 | int GNUNET_MONKEY_ACTION_delete_context(struct GNUNET_MONKEY_ACTION_Context *cntxt); | ||
93 | |||
94 | int 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 | ||
30 | extern "C" | ||
31 | { | ||
32 | #if 0 /* keep Emacsens' auto-indent happy */ | ||
33 | } | ||
34 | #endif | ||
35 | #endif | ||
36 | |||
37 | |||
38 | struct 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 | */ | ||
46 | struct 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 | */ | ||
56 | int GNUNET_MONKEY_EDB_disconnect (struct GNUNET_MONKEY_EDB_Context *cntxt); | ||
57 | |||
58 | |||
59 | typedef 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 | */ | ||
74 | int | ||
75 | GNUNET_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 = ∂ // 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 | */ | ||
105 | int | ||
106 | GNUNET_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 | |||
113 | int | ||
114 | GNUNET_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 | |||
21 | int | ||
22 | handle_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 | |||
86 | void 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 */ | ||
136 | void | ||
137 | print_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 | |||
147 | void 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 | ============================================= | ||
38 | 3/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 | |||
43 | 31/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 | |||
49 | 8/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 | |||
54 | PARSER_BEGIN(CParser) | ||
55 | |||
56 | import 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 | |||
96 | PARSER_END(CParser) | ||
97 | |||
98 | SKIP : { | ||
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 | |||
123 | TOKEN : { | ||
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 | |||
157 | TOKEN : { | ||
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 | |||
192 | TOKEN : { | ||
193 | <IDENTIFIER: <LETTER> (<LETTER> | <DIGIT>)*> | ||
194 | | <#LETTER: ["$","A"-"Z","_","a"-"z"]> | ||
195 | | <#DIGIT: ["0"-"9"]> | ||
196 | } | ||
197 | |||
198 | void TranslationUnit() : {} | ||
199 | { | ||
200 | (ExternalDeclaration())+ | ||
201 | <EOF> | ||
202 | } | ||
203 | |||
204 | void 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 | |||
216 | void FunctionDeclaration() : {} | ||
217 | { | ||
218 | TypeSpecifier () | ||
219 | <IDENTIFIER> | ||
220 | "(" [ ParameterList () ] ")" | ||
221 | ( ";" | CompoundStatement() ) | ||
222 | } | ||
223 | |||
224 | void StorageClassSpecifier() : {} | ||
225 | { | ||
226 | ( <STATIC> | <EXTERN> ) | ||
227 | } | ||
228 | |||
229 | void TypeDeclaration() : {} | ||
230 | { | ||
231 | <TYPEDEF> | ||
232 | ( LOOKAHEAD (DataType() ";") DataType () | FunctionType() ) ";" | ||
233 | } | ||
234 | |||
235 | void DataType() : {} | ||
236 | { | ||
237 | StructOrUnionSpecifier () <IDENTIFIER> | ||
238 | } | ||
239 | |||
240 | void FunctionType() : {} | ||
241 | { | ||
242 | TypeSpecifier () "(" "*" <IDENTIFIER> ")" "(" [ ParameterList() ] ")" | ||
243 | } | ||
244 | |||
245 | void ParameterList() : {} | ||
246 | { | ||
247 | ParameterDeclaration() ( LOOKAHEAD (2) "," ParameterDeclaration() )* [ "," "..." ] | ||
248 | } | ||
249 | |||
250 | void ParameterDeclaration() : {} | ||
251 | { | ||
252 | TypeSpecifier() [<IDENTIFIER> [ Array () ]] | ||
253 | } | ||
254 | |||
255 | void VariableDeclaration() : {} | ||
256 | { | ||
257 | VariableClassSpecifier () | ||
258 | TypeSpecifier () | ||
259 | InitDeclaratorList() ";" | ||
260 | } | ||
261 | |||
262 | void LocalVariableDeclaration() : {} | ||
263 | { | ||
264 | [ <STATIC> ] VariableDeclaration () | ||
265 | } | ||
266 | |||
267 | void VariableClassSpecifier() : {} | ||
268 | { | ||
269 | ( <AUTO> | <REGISTER> )* | ||
270 | } | ||
271 | |||
272 | void 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 */ | ||
297 | void 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 | |||
317 | void StructOrUnionSpecifier() : {} | ||
318 | { | ||
319 | LOOKAHEAD (3) | ||
320 | StructOrUnion() [ <IDENTIFIER> ] "{" StructDeclarationList() "}" | | ||
321 | StructOrUnion() <IDENTIFIER> | ||
322 | } | ||
323 | |||
324 | void StructOrUnion() : {} | ||
325 | { | ||
326 | ( <STRUCT> | <UNION> ) | ||
327 | } | ||
328 | |||
329 | void StructDeclarationList() : {} | ||
330 | { | ||
331 | (StructDeclaration())* | ||
332 | } | ||
333 | |||
334 | void InitDeclaratorList() : {} | ||
335 | { | ||
336 | InitDeclarator() ("," InitDeclarator())* | ||
337 | } | ||
338 | |||
339 | void InitDeclarator() : {} | ||
340 | { | ||
341 | <IDENTIFIER> [ Array () ] [ "=" Initializer() ] | ||
342 | } | ||
343 | |||
344 | void StructDeclaration() : {} | ||
345 | { | ||
346 | TypeSpecifier() <IDENTIFIER> [ Array() | ":" ConstantExpression() ] [ <IDENTIFIER> ] ";" | ||
347 | } | ||
348 | |||
349 | void EnumSpecifier() : {} | ||
350 | { | ||
351 | <ENUM> ( LOOKAHEAD(3) [ <IDENTIFIER> ] "{" EnumeratorList() "}" | <IDENTIFIER> ) | ||
352 | } | ||
353 | |||
354 | void EnumeratorList() : {} | ||
355 | { | ||
356 | Enumerator() ("," Enumerator())* | ||
357 | } | ||
358 | |||
359 | void Enumerator() : {} | ||
360 | { | ||
361 | <IDENTIFIER> [ "=" ConstantExpression() ] | ||
362 | } | ||
363 | |||
364 | void Pointer() : {} | ||
365 | { | ||
366 | "*" [ <CONST> ] [ Pointer() ] | ||
367 | } | ||
368 | |||
369 | void Initializer() : {} | ||
370 | { | ||
371 | ( AssignmentExpression() | | ||
372 | "{" InitializerList() [","] "}" ) | ||
373 | } | ||
374 | |||
375 | void InitializerList() : {} | ||
376 | { | ||
377 | Initializer() (LOOKAHEAD(2) "," Initializer())* | ||
378 | } | ||
379 | |||
380 | |||
381 | void Array() : {} | ||
382 | { | ||
383 | ("[" [ConstantExpression()] "]" )+ | ||
384 | } | ||
385 | |||
386 | void Statement() : {} | ||
387 | { | ||
388 | ( LOOKAHEAD(2) LabeledStatement() | | ||
389 | ExpressionStatement() | | ||
390 | CompoundStatement() | | ||
391 | SelectionStatement() | | ||
392 | IterationStatement() | | ||
393 | JumpStatement() ) | ||
394 | } | ||
395 | |||
396 | void LabeledStatement() : {} | ||
397 | { | ||
398 | ( <IDENTIFIER> ":" Statement() | | ||
399 | <CASE> ConstantExpression() ":" Statement() | | ||
400 | <DFLT> ":" Statement() ) | ||
401 | } | ||
402 | |||
403 | void ExpressionStatement() : {} | ||
404 | { | ||
405 | [ Expression() ] ";" | ||
406 | } | ||
407 | |||
408 | void CompoundStatement() : {} | ||
409 | { | ||
410 | "{" ( LOOKAHEAD (LocalVariableDeclaration()) LocalVariableDeclaration () | | ||
411 | Statement() )* | ||
412 | "}" | ||
413 | } | ||
414 | |||
415 | void SelectionStatement() : {} | ||
416 | { | ||
417 | ( IfStatement() | SwitchStatement() ) | ||
418 | } | ||
419 | |||
420 | void IfStatement() : {} | ||
421 | { | ||
422 | <IF> "(" Expression() ")" Statement() [ LOOKAHEAD(2) <ELSE> Statement() ] | ||
423 | } | ||
424 | |||
425 | void SwitchStatement() : {} | ||
426 | { | ||
427 | <SWITCH> "(" Expression() ")" Statement() | ||
428 | } | ||
429 | |||
430 | void IterationStatement() : {} | ||
431 | { | ||
432 | ( WhileStatement() | DoWhileStatement() | ForStatement() ) | ||
433 | } | ||
434 | void WhileStatement() : {} | ||
435 | { | ||
436 | <WHILE> "(" Expression() ")" Statement() | ||
437 | } | ||
438 | void DoWhileStatement() : {} | ||
439 | { | ||
440 | <DO> Statement() <WHILE> "(" Expression() ")" ";" | ||
441 | } | ||
442 | void ForStatement() : {} | ||
443 | { | ||
444 | <FOR> "(" [ Expression() ] ";" [ Expression() ] ";" [ Expression() ] ")" Statement() | ||
445 | } | ||
446 | |||
447 | void JumpStatement() : {} | ||
448 | { | ||
449 | ( <GOTO> <IDENTIFIER> ";" | | ||
450 | <CONTINUE> ";" | | ||
451 | <BREAK> ";" | | ||
452 | <RETURN> [ Expression() ] ";" ) | ||
453 | } | ||
454 | |||
455 | void Expression() : {} | ||
456 | { | ||
457 | AssignmentExpression() ( "," AssignmentExpression() )* | ||
458 | } | ||
459 | |||
460 | void AssignmentExpression() : {} | ||
461 | { | ||
462 | LOOKAHEAD(UnaryExpression() AssignmentOperator()) UnaryExpression() AssignmentOperator() AssignmentExpression() | | ||
463 | LOOKAHEAD(3) ConditionalExpression() | ||
464 | } | ||
465 | |||
466 | void AssignmentOperator() : {} | ||
467 | { | ||
468 | ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | "&=" | "^=" | "|=" ) | ||
469 | } | ||
470 | |||
471 | void ConditionalExpression() : {} | ||
472 | { | ||
473 | LogicalORExpression() [ "?" Expression() ":" ConditionalExpression() ] | ||
474 | } | ||
475 | |||
476 | void ConstantExpression() : {} | ||
477 | { | ||
478 | ConditionalExpression() | ||
479 | } | ||
480 | |||
481 | void LogicalORExpression() : {} | ||
482 | { | ||
483 | LogicalANDExpression() [ "||" LogicalORExpression() ] | ||
484 | } | ||
485 | |||
486 | void LogicalANDExpression() : {} | ||
487 | { | ||
488 | InclusiveORExpression() [ "&&" LogicalANDExpression() ] | ||
489 | } | ||
490 | |||
491 | void InclusiveORExpression() : {} | ||
492 | { | ||
493 | ExclusiveORExpression() [ "|" InclusiveORExpression() ] | ||
494 | } | ||
495 | |||
496 | void ExclusiveORExpression() : {} | ||
497 | { | ||
498 | ANDExpression() [ "^" ExclusiveORExpression() ] | ||
499 | } | ||
500 | |||
501 | void ANDExpression() : {} | ||
502 | { | ||
503 | EqualityExpression() [ "&" ANDExpression() ] | ||
504 | } | ||
505 | |||
506 | void EqualityExpression() : {} | ||
507 | { | ||
508 | RelationalExpression() [ ( "==" | "!=" ) EqualityExpression() ] | ||
509 | } | ||
510 | |||
511 | void RelationalExpression() : {} | ||
512 | { | ||
513 | ShiftExpression() [ ( "<" | ">" | "<=" | ">=" ) RelationalExpression() ] | ||
514 | } | ||
515 | |||
516 | void ShiftExpression() : {} | ||
517 | { | ||
518 | AdditiveExpression() [ ( "<<" | ">>" ) ShiftExpression() ] | ||
519 | } | ||
520 | |||
521 | void AdditiveExpression() : {} | ||
522 | { | ||
523 | MultiplicativeExpression() [ ( "+" | "-" ) AdditiveExpression() ] | ||
524 | } | ||
525 | |||
526 | void MultiplicativeExpression() : {} | ||
527 | { | ||
528 | CastExpression() [ ( "*" | "/" | "%" ) MultiplicativeExpression() ] | ||
529 | } | ||
530 | |||
531 | void CastExpression() : {} | ||
532 | { | ||
533 | ( LOOKAHEAD("(" TypeSpecifier() ")" CastExpression() ) "(" TypeSpecifier() ")" CastExpression() | | ||
534 | UnaryExpression() ) | ||
535 | } | ||
536 | |||
537 | void UnaryExpression() : {} | ||
538 | { | ||
539 | ( LOOKAHEAD(3) PostfixExpression() | | ||
540 | "++" UnaryExpression() | | ||
541 | "--" UnaryExpression() | | ||
542 | UnaryOperator() CastExpression() | | ||
543 | <SIZEOF> ( LOOKAHEAD(UnaryExpression() ) UnaryExpression() | "(" TypeSpecifier() ")" ) ) | ||
544 | } | ||
545 | |||
546 | void UnaryOperator() : {} | ||
547 | { | ||
548 | ( "&" | "*" | "+" | "-" | "~" | "!" ) | ||
549 | } | ||
550 | |||
551 | void PostfixExpression() : {} | ||
552 | { | ||
553 | PrimaryExpression() ( "[" Expression() "]" | | ||
554 | "(" [ LOOKAHEAD(ArgumentExpressionList() ) ArgumentExpressionList() ] ")" | | ||
555 | "." <IDENTIFIER> | | ||
556 | "->" <IDENTIFIER> | | ||
557 | "++" | | ||
558 | "--" )* | ||
559 | } | ||
560 | |||
561 | void PrimaryExpression() : {} | ||
562 | { | ||
563 | <IDENTIFIER> | | ||
564 | Constant() | | ||
565 | "(" Expression() ")" | ||
566 | } | ||
567 | |||
568 | void ArgumentExpressionList() : {} | ||
569 | { | ||
570 | AssignmentOrTypeExpression() ( "," AssignmentOrTypeExpression() )* | ||
571 | } | ||
572 | |||
573 | |||
574 | void AssignmentOrTypeExpression() : {} | ||
575 | { | ||
576 | NoIdentifierTypeSpecifier() | | ||
577 | AssignmentExpression() | ||
578 | } | ||
579 | |||
580 | void 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 @@ | |||
1 | all: | ||
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 | |||
13 | struct MyStruct { | ||
14 | int member; | ||
15 | struct MyStruct *part; | ||
16 | }; | ||
17 | |||
18 | |||
19 | enum MyEnum{ | ||
20 | enumMember1, | ||
21 | enumMember2, | ||
22 | enumMember3 | ||
23 | }; | ||
24 | |||
25 | |||
26 | static int fun(int arg1, int arg2) | ||
27 | { | ||
28 | return arg1 + arg2; | ||
29 | } | ||
30 | |||
31 | |||
32 | int 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 = ∂ | ||
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 @@ | |||
1 | package org.gnunet.seaspider; | ||
2 | |||
3 | import java.io.File; | ||
4 | import java.util.HashMap; | ||
5 | import java.util.Iterator; | ||
6 | import java.util.Stack; | ||
7 | import org.tmatesoft.sqljet.core.SqlJetException; | ||
8 | import org.tmatesoft.sqljet.core.SqlJetTransactionMode; | ||
9 | import org.tmatesoft.sqljet.core.table.ISqlJetTable; | ||
10 | import 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 | */ | ||
24 | public 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 @@ | |||
1 | package org.gnunet.seaspider; | ||
2 | |||
3 | import org.gnunet.seaspider.parser.nodes.ANDExpression; | ||
4 | import org.gnunet.seaspider.parser.nodes.AdditiveExpression; | ||
5 | import org.gnunet.seaspider.parser.nodes.ArgumentExpressionList; | ||
6 | import org.gnunet.seaspider.parser.nodes.AssignmentExpression; | ||
7 | import org.gnunet.seaspider.parser.nodes.AssignmentOperator; | ||
8 | import org.gnunet.seaspider.parser.nodes.CastExpression; | ||
9 | import org.gnunet.seaspider.parser.nodes.CompoundStatement; | ||
10 | import org.gnunet.seaspider.parser.nodes.ConditionalExpression; | ||
11 | import org.gnunet.seaspider.parser.nodes.ConstantExpression; | ||
12 | import org.gnunet.seaspider.parser.nodes.DoWhileStatement; | ||
13 | import org.gnunet.seaspider.parser.nodes.EqualityExpression; | ||
14 | import org.gnunet.seaspider.parser.nodes.ExclusiveORExpression; | ||
15 | import org.gnunet.seaspider.parser.nodes.Expression; | ||
16 | import org.gnunet.seaspider.parser.nodes.ExpressionStatement; | ||
17 | import org.gnunet.seaspider.parser.nodes.ForStatement; | ||
18 | import org.gnunet.seaspider.parser.nodes.FunctionDeclaration; | ||
19 | import org.gnunet.seaspider.parser.nodes.IfStatement; | ||
20 | import org.gnunet.seaspider.parser.nodes.InclusiveORExpression; | ||
21 | import org.gnunet.seaspider.parser.nodes.InitDeclarator; | ||
22 | import org.gnunet.seaspider.parser.nodes.InitDeclaratorList; | ||
23 | import org.gnunet.seaspider.parser.nodes.Initializer; | ||
24 | import org.gnunet.seaspider.parser.nodes.InitializerList; | ||
25 | import org.gnunet.seaspider.parser.nodes.JumpStatement; | ||
26 | import org.gnunet.seaspider.parser.nodes.LogicalANDExpression; | ||
27 | import org.gnunet.seaspider.parser.nodes.LogicalORExpression; | ||
28 | import org.gnunet.seaspider.parser.nodes.MultiplicativeExpression; | ||
29 | import org.gnunet.seaspider.parser.nodes.Node; | ||
30 | import org.gnunet.seaspider.parser.nodes.NodeChoice; | ||
31 | import org.gnunet.seaspider.parser.nodes.NodeSequence; | ||
32 | import org.gnunet.seaspider.parser.nodes.NodeToken; | ||
33 | import org.gnunet.seaspider.parser.nodes.ParameterDeclaration; | ||
34 | import org.gnunet.seaspider.parser.nodes.PostfixExpression; | ||
35 | import org.gnunet.seaspider.parser.nodes.PrimaryExpression; | ||
36 | import org.gnunet.seaspider.parser.nodes.RelationalExpression; | ||
37 | import org.gnunet.seaspider.parser.nodes.ShiftExpression; | ||
38 | import org.gnunet.seaspider.parser.nodes.StructOrUnionSpecifier; | ||
39 | import org.gnunet.seaspider.parser.nodes.SwitchStatement; | ||
40 | import org.gnunet.seaspider.parser.nodes.TranslationUnit; | ||
41 | import org.gnunet.seaspider.parser.nodes.TypeDeclaration; | ||
42 | import org.gnunet.seaspider.parser.nodes.UnaryExpression; | ||
43 | import org.gnunet.seaspider.parser.nodes.UnaryOperator; | ||
44 | import org.gnunet.seaspider.parser.nodes.VariableDeclaration; | ||
45 | import org.gnunet.seaspider.parser.nodes.WhileStatement; | ||
46 | import org.gnunet.seaspider.parser.visitors.DepthFirstVisitor; | ||
47 | import org.grothoff.LineNumberInfo; | ||
48 | |||
49 | /** | ||
50 | * @author grothoff | ||
51 | * | ||
52 | */ | ||
53 | public 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 @@ | |||
1 | package org.gnunet.seaspider; | ||
2 | |||
3 | import java.io.File; | ||
4 | import java.io.FileInputStream; | ||
5 | import java.io.FileNotFoundException; | ||
6 | import java.io.FilenameFilter; | ||
7 | |||
8 | import org.gnunet.seaspider.parser.CParser; | ||
9 | import org.gnunet.seaspider.parser.ParseException; | ||
10 | import org.gnunet.seaspider.parser.TokenMgrError; | ||
11 | import org.gnunet.seaspider.parser.nodes.Node; | ||
12 | |||
13 | public 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 @@ | |||
1 | package org.grothoff; | ||
2 | |||
3 | import java.lang.reflect.Field; | ||
4 | import java.util.Enumeration; | ||
5 | import 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 | */ | ||
32 | public 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 | |||
42 | static int | ||
43 | check () | ||
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 | |||
55 | int | ||
56 | main (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 | |||
3 | rm -rf /tmp/test-gnunetd-monkey/ | ||
4 | exe="./gnunet-monkey -c test_monkey_api_data.conf" | ||
5 | out=`mktemp /tmp/test-gnunet-monkey-logXXXXXXXX` | ||
6 | arm="gnunet-arm -c test_monkey_api_data.conf $DEBUG" | ||
7 | #DEBUG="-L DEBUG" | ||
8 | # ----------------------------------- | ||
9 | echo -n "Preparing: Starting service..." | ||
10 | |||
11 | $arm -s > /dev/null | ||
12 | sleep 1 | ||
13 | $arm -i monkey > /dev/null | ||
14 | sleep 1 | ||
15 | echo "DONE" | ||
16 | |||
17 | # ---------------------------------------------------------------------------------- | ||
18 | echo -n "TEST: Bad argument checking..." | ||
19 | |||
20 | if $exe -x 2> /dev/null; then | ||
21 | echo "FAIL: error running $exe" | ||
22 | $arm -e | ||
23 | exit 1 | ||
24 | fi | ||
25 | echo "PASS" | ||
26 | |||
27 | # ---------------------------------------------------------------------------------- | ||
28 | echo -n "TEST: Set value..." | ||
29 | |||
30 | if ! $exe $DEBUG -n test -s subsystem 42 ; then | ||
31 | echo "FAIL: error running $exe" | ||
32 | $arm -e | ||
33 | exit 1 | ||
34 | fi | ||
35 | echo "PASS" | ||
36 | |||
37 | # ---------------------------------------------------------------------------------- | ||
38 | echo -n "TEST: Set another value..." | ||
39 | |||
40 | if ! $exe $DEBUG -n other -s osystem 43 ; then | ||
41 | echo "FAIL: error running $exe" | ||
42 | $arm -e | ||
43 | exit 1 | ||
44 | fi | ||
45 | echo "PASS" | ||
46 | |||
47 | # ---------------------------------------------------------------------------------- | ||
48 | echo -n "TEST: viewing all stats..." | ||
49 | |||
50 | if ! $exe $DEBUG > $out; then | ||
51 | echo "FAIL: error running $exe" | ||
52 | $arm -e | ||
53 | exit 1 | ||
54 | fi | ||
55 | LINES=`cat $out | wc -l` | ||
56 | if test $LINES -ne 2; then | ||
57 | echo "FAIL: unexpected output" | ||
58 | $arm -e | ||
59 | exit 1 | ||
60 | fi | ||
61 | echo "PASS" | ||
62 | |||
63 | # ---------------------------------------------------------------------------------- | ||
64 | echo -n "TEST: viewing stats by name..." | ||
65 | |||
66 | if ! $exe $DEBUG -n other > $out; then | ||
67 | echo "FAIL: error running $exe" | ||
68 | $arm -e | ||
69 | exit 1 | ||
70 | fi | ||
71 | LINES=`cat $out | grep 43 | wc -l` | ||
72 | if test $LINES -ne 1; then | ||
73 | echo "FAIL: unexpected output" | ||
74 | $arm -e | ||
75 | exit 1 | ||
76 | fi | ||
77 | echo "PASS" | ||
78 | |||
79 | # ---------------------------------------------------------------------------------- | ||
80 | echo -n "TEST: viewing stats by subsystem..." | ||
81 | |||
82 | if ! $exe $DEBUG -s subsystem > $out; then | ||
83 | echo "FAIL: error running $exe" | ||
84 | $arm -e | ||
85 | exit 1 | ||
86 | fi | ||
87 | LINES=`cat $out | grep 42 | wc -l` | ||
88 | if test $LINES -ne 1; then | ||
89 | echo "FAIL: unexpected output" | ||
90 | $arm -e | ||
91 | exit 1 | ||
92 | fi | ||
93 | echo "PASS" | ||
94 | |||
95 | |||
96 | # ---------------------------------------------------------------------------------- | ||
97 | echo -n "TEST: Set persistent value..." | ||
98 | |||
99 | if ! $exe $DEBUG -n lasting -s subsystem 40 -p; then | ||
100 | echo "FAIL: error running $exe" | ||
101 | $arm -e | ||
102 | exit 1 | ||
103 | fi | ||
104 | if ! $exe $DEBUG > $out; then | ||
105 | echo "FAIL: error running $exe" | ||
106 | $arm -e | ||
107 | exit 1 | ||
108 | fi | ||
109 | LINES=`cat $out | grep 40 | wc -l` | ||
110 | if test $LINES -ne 1; then | ||
111 | echo "FAIL: unexpected output" | ||
112 | cat $out | ||
113 | $arm -e | ||
114 | exit 1 | ||
115 | fi | ||
116 | echo "PASS" | ||
117 | |||
118 | # ----------------------------------- | ||
119 | echo -n "Restarting service..." | ||
120 | $arm -k monkey > /dev/null | ||
121 | sleep 1 | ||
122 | $arm -i monkey > /dev/null | ||
123 | sleep 1 | ||
124 | echo "DONE" | ||
125 | |||
126 | # ---------------------------------------------------------------------------------- | ||
127 | echo -n "TEST: checking persistence..." | ||
128 | |||
129 | if ! $exe $DEBUG > $out; then | ||
130 | echo "FAIL: error running $exe" | ||
131 | $arm -e | ||
132 | exit 1 | ||
133 | fi | ||
134 | LINES=`cat $out | grep 40 | wc -l` | ||
135 | if test $LINES -ne 1; then | ||
136 | echo "FAIL: unexpected output" | ||
137 | cat $out | ||
138 | $arm -e | ||
139 | exit 1 | ||
140 | fi | ||
141 | echo "PASS" | ||
142 | |||
143 | |||
144 | |||
145 | # ---------------------------------------------------------------------------------- | ||
146 | echo -n "TEST: Removing persistence..." | ||
147 | |||
148 | if ! $exe $DEBUG -n lasting -s subsystem 40; then | ||
149 | echo "FAIL: error running $exe" | ||
150 | $arm -e | ||
151 | exit 1 | ||
152 | fi | ||
153 | if ! $exe $DEBUG > $out; then | ||
154 | echo "FAIL: error running $exe" | ||
155 | $arm -e | ||
156 | exit 1 | ||
157 | fi | ||
158 | LINES=`cat $out | grep \! | wc -l` | ||
159 | if test $LINES -ne 0; then | ||
160 | echo "FAIL: unexpected output" | ||
161 | cat $out | ||
162 | $arm -e | ||
163 | exit 1 | ||
164 | fi | ||
165 | echo "PASS" | ||
166 | |||
167 | |||
168 | # ----------------------------------- | ||
169 | echo -n "Restarting service..." | ||
170 | $arm -k monkey > /dev/null | ||
171 | sleep 1 | ||
172 | $arm -i monkey > /dev/null | ||
173 | sleep 1 | ||
174 | echo "DONE" | ||
175 | |||
176 | # ---------------------------------------------------------------------------------- | ||
177 | echo -n "TEST: checking removed persistence..." | ||
178 | |||
179 | if ! $exe $DEBUG > $out; then | ||
180 | echo "FAIL: error running $exe" | ||
181 | $arm -e | ||
182 | exit 1 | ||
183 | fi | ||
184 | LINES=`cat $out | grep 40 | wc -l` | ||
185 | if test $LINES -ne 0; then | ||
186 | echo "FAIL: unexpected output" | ||
187 | cat $out | ||
188 | $arm -e | ||
189 | exit 1 | ||
190 | fi | ||
191 | echo "PASS" | ||
192 | |||
193 | # ----------------------------------- | ||
194 | echo -n "Stopping service..." | ||
195 | $arm -e > /dev/null | ||
196 | sleep 1 | ||
197 | echo "DONE" | ||
198 | rm -f $out | ||
199 | rm -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] | ||
2 | SERVICEHOME = /tmp/test-gnunetd-arm/ | ||
3 | DEFAULTCONFIG = test_arm_api_data.conf | ||
4 | |||
5 | [arm] | ||
6 | PORT = 23354 | ||
7 | DEFAULTSERVICES = | ||
8 | BINARY = gnunet-service-arm | ||
9 | OPTIONS = -L ERROR | ||
10 | # DEBUG = YES | ||
11 | #PREFIX = valgrind --tool=memcheck --leak-check=yes | ||
12 | |||
13 | [gnunet-monkey] | ||
14 | # DEBUG = YES | ||
15 | PORT = 23355 | ||
16 | BINARY = gnunet-monkey | ||
17 | # PREFIX = valgrind | ||
18 | |||
19 | |||
20 | [fs] | ||
21 | AUTOSTART = NO | ||
22 | |||
23 | [datastore] | ||
24 | AUTOSTART = NO | ||
25 | |||
26 | [core] | ||
27 | AUTOSTART = NO | ||
28 | |||
29 | [transport] | ||
30 | AUTOSTART = NO | ||
31 | |||
32 | [peerinfo] | ||
33 | AUTOSTART = NO | ||
34 | |||
35 | [statistics] | ||
36 | AUTOSTART = YES | ||
37 | # DEBUG = NO | ||
38 | |||
39 | |||
40 | [dns] | ||
41 | AUTOSTART = 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 | |||
29 | static 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 | |||
35 | static int refCount = 0; | ||
36 | static int ret = 1; | ||
37 | |||
38 | int | ||
39 | expressionIterator (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 | |||
53 | int | ||
54 | main (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 | ||
2 | echo -n "Test Monkey with Bug - Null Pointer Exception -" | ||
3 | gnunet-monkey --mode text --binary bug_null_pointer_exception --output npe.out && exit 0 | ||
4 | grep "Bug detected in file:bug_null_pointer_exception.c" npe.out > /dev/null || exit 1 | ||
5 | grep "function:crashFunction" npe.out > /dev/null || exit 1 | ||
6 | grep "line:8" npe.out > /dev/null || exit 1 | ||
7 | grep "reason:Signal received" npe.out > /dev/null || exit 1 | ||
8 | grep "received signal:EXC_BAD_ACCESS" npe.out > /dev/null || exit 1 | ||
9 | grep "Could not access memory" npe.out > /dev/null || exit 1 | ||
10 | rm -f npe.out | ||
11 | echo "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) | ||