* fports.c (scm_open_file): Don't call scm_makfrom0str on a scheme
[bpt/guile.git] / libguile / gdbint.c
CommitLineData
4907ff5a
MD
1/* GDB interface for Guile
2 * Copyright (C) 1996 Mikael Djurfeldt
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; see the file COPYING. If not, write to
16 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17 *
18 * As a special exception, the Free Software Foundation gives permission
19 * for additional uses of the text contained in its release of GUILE.
20 *
21 * The exception is that, if you link the GUILE library with other files
22 * to produce an executable, this does not by itself cause the
23 * resulting executable to be covered by the GNU General Public License.
24 * Your use of that executable is in no way restricted on account of
25 * linking the GUILE library code into it.
26 *
27 * This exception does not however invalidate any other reasons why
28 * the executable file might be covered by the GNU General Public License.
29 *
30 * This exception applies only to the code released by the
31 * Free Software Foundation under the name GUILE. If you copy
32 * code from other Free Software Foundation releases into a copy of
33 * GUILE, as the General Public License permits, the exception does
34 * not apply to the code that you add in this way. To avoid misleading
35 * anyone as to the status of such modified files, you must delete
36 * this exception notice from them.
37 *
38 * If you write modifications of your own for GUILE, it is your choice
39 * whether to permit this exception to apply to your modifications.
40 * If you do not wish that, delete this exception notice.
41 *
42 * The author can be reached at djurfeldt@nada.kth.se
43 * Mikael Djurfeldt, SANS/NADA KTH, 10044 STOCKHOLM, SWEDEN
44 */
45
46#include <stdio.h>
47#include "_scm.h"
20e6290e
JB
48#include "tag.h"
49#include "strports.h"
50#include "read.h"
51#include "print.h"
52#include "eval.h"
53#include "chars.h"
4907ff5a 54
20e6290e 55#include "gdbint.h"
4907ff5a
MD
56\f
57/* {Support for debugging with gdb}
58 *
59 * TODO:
60 *
61 * 1. Redirect outputs
62 * 2. Catch errors
63 * 3. Prevent print from causing segmentation fault when given broken pairs
64 */
65
66#include <stdio.h>
67#include "_scm.h"
68
69#define GDB_TYPE SCM
70
71#include "gdb_interface.h"
72
73\f
74
75/* Be carefull when this macro is true.
76 scm_gc_heap_lock is set during gc.
77 */
78#define SCM_GC_P (scm_gc_heap_lock)
79
80/* Macros that encapsulate blocks of code which can be called by the
81 * debugger.
82 */
83#define SCM_BEGIN_FOREIGN_BLOCK \
84{ \
85 old_ints = scm_ints_disabled; scm_ints_disabled = 1; \
86 old_gc = scm_block_gc; scm_block_gc = 1; \
87 scm_print_carefully_p = 1; \
88} \
89
90
91#define SCM_END_FOREIGN_BLOCK \
92{ \
93 scm_print_carefully_p = 0; \
94 scm_block_gc = old_gc; \
95 scm_ints_disabled = old_ints; \
96} \
97
98
99#define RESET_STRING { gdb_output_length = 0; }
100
101#define SEND_STRING(str) \
102{ \
103 gdb_output = str; \
104 gdb_output_length = strlen (str); \
380b6b4c
MD
105} \
106
4907ff5a
MD
107
108/* {Gdb interface}
109 */
110
111unsigned short gdb_options = GDB_HAVE_BINDINGS;
112
113char *gdb_language = "lisp/c";
114
115SCM gdb_result;
116
117char *gdb_output;
118
119int gdb_output_length;
120
121int scm_print_carefully_p;
122
123static SCM gdb_input_port;
380b6b4c
MD
124static int port_mark_p, stream_mark_p, string_mark_p;
125
126static SCM tok_buf;
127static int tok_buf_mark_p;
128
4907ff5a
MD
129static SCM gdb_output_port;
130static int old_ints, old_gc;
131
380b6b4c
MD
132#ifdef __STDC__
133static void
134unmark_port (SCM port)
135#else
136static void
137unmark_port (port)
138 SCM port;
139#endif
140{
141 SCM stream, string;
142 port_mark_p = SCM_GC8MARKP (port);
143 SCM_CLRGC8MARK (port);
144 stream = SCM_STREAM (port);
145 stream_mark_p = SCM_GCMARKP (stream);
146 SCM_CLRGCMARK (stream);
147 string = SCM_CDR (stream);
148 string_mark_p = SCM_GC8MARKP (string);
149 SCM_CLRGC8MARK (string);
150}
151
152#ifdef __STDC__
153static void
154remark_port (SCM port)
155#else
156static void
157remark_port (port)
158 SCM port;
159#endif
160{
161 SCM stream = SCM_STREAM (port);
162 SCM string = SCM_CDR (stream);
163 if (string_mark_p) SCM_SETGC8MARK (string);
164 if (stream_mark_p) SCM_SETGCMARK (stream);
165 if (port_mark_p) SCM_SETGC8MARK (port);
166}
167
4907ff5a
MD
168#ifdef __STDC__
169int
170gdb_maybe_valid_type_p (SCM value)
171#else
172int
173gdb_maybe_valid_type_p (value)
174 SCM value;
175#endif
176{
177 if (SCM_IMP (value) || scm_cellp (value))
178 return scm_tag (value) != SCM_MAKINUM (-1);
179 return 0;
180}
181
182#ifdef __STDC__
183int
184gdb_read (char *str)
185#else
186int
187gdb_read (str)
188 char *str;
189#endif
190{
191 SCM ans;
192 int status = 0;
193 RESET_STRING;
194 /* Need to be restrictive about what to read? */
195 if (SCM_GC_P)
196 {
197 char *p;
198 for (p = str; *p != '\0'; ++p)
199 switch (*p)
200 {
201 case '(':
202 case '\'':
203 case '"':
204 SEND_STRING ("Can't read this kind of expressions during gc");
205 return -1;
206 case '#':
207 if (*++p == '\0')
208 goto premature;
209 if (*p == '\\')
210 {
211 if (*++p != '\0')
212 continue;
213 premature:
214 SEND_STRING ("Premature end of lisp expression");
215 return -1;
216 }
217 default:
218 continue;
219 }
220 }
221 SCM_BEGIN_FOREIGN_BLOCK;
380b6b4c 222 unmark_port (gdb_input_port);
4907ff5a
MD
223 /* Replace string in input port and reset stream */
224 ans = SCM_CDR (SCM_STREAM (gdb_input_port));
225 SCM_SETCHARS (ans, str);
226 SCM_SETLENGTH (ans, strlen (str), scm_tc7_string);
227 SCM_SETCAR (SCM_STREAM (gdb_input_port), SCM_INUM0);
228 /* Read one object */
380b6b4c
MD
229 tok_buf_mark_p = SCM_GC8MARKP (tok_buf);
230 SCM_CLRGC8MARK (tok_buf);
231 ans = scm_lreadr (&tok_buf, gdb_input_port, 0, SCM_BOOL_F);
4907ff5a
MD
232 if (SCM_GC_P)
233 {
380b6b4c 234 if (SCM_NIMP (ans))
4907ff5a
MD
235 {
236 SEND_STRING ("Non-immediate created during gc. Memory may be trashed.");
237 status = -1;
238 goto exit;
239 }
240 }
380b6b4c 241 gdb_result = ans;
4907ff5a 242 /* Protect answer from future GC */
380b6b4c
MD
243 if (SCM_NIMP (ans))
244 scm_permanent_object (ans);
4907ff5a 245exit:
380b6b4c
MD
246 if (tok_buf_mark_p)
247 SCM_SETGC8MARK (tok_buf);
248 remark_port (gdb_input_port);
4907ff5a
MD
249 SCM_END_FOREIGN_BLOCK;
250 return status;
251}
252
253#ifdef __STDC__
254int
255gdb_eval (SCM exp)
256#else
257int
258gdb_eval (exp)
259 SCM exp;
260#endif
261{
262 RESET_STRING;
263 if (SCM_IMP (exp))
264 {
265 gdb_result = exp;
266 return 0;
267 }
268 if (SCM_GC_P)
269 {
270 SEND_STRING ("Can't evaluate lisp expressions during gc");
271 return -1;
272 }
273 SCM_BEGIN_FOREIGN_BLOCK;
274 {
275 SCM env = scm_top_level_env (SCM_CDR (scm_top_level_lookup_thunk_var));
276 gdb_result = scm_permanent_object (scm_ceval (exp, env));
277 }
278 SCM_END_FOREIGN_BLOCK;
279 return 0;
280}
281
282#ifdef __STDC__
283int
284gdb_print (SCM obj)
285#else
286int
287gdb_print (obj)
288 SCM obj;
289#endif
290{
291 RESET_STRING;
292 SCM_BEGIN_FOREIGN_BLOCK;
293 /* Reset stream */
294 SCM_SETCAR (SCM_STREAM (gdb_output_port), SCM_INUM0);
295 scm_write (obj, gdb_output_port);
296 scm_display (SCM_MAKICHR (0), gdb_output_port);
297 SEND_STRING (SCM_CHARS (SCM_CDR (SCM_STREAM (gdb_output_port))));
298 SCM_END_FOREIGN_BLOCK;
299 return 0;
300}
301
302#ifdef __STDC__
303int
304gdb_binding (SCM name, SCM value)
305#else
306int
307gdb_binding (name, value)
308 SCM name;
309 SCM value;
310#endif
311{
312 RESET_STRING;
313 if (SCM_GC_P)
314 {
315 SEND_STRING ("Can't create new bindings during gc");
316 return -1;
317 }
318 SCM_BEGIN_FOREIGN_BLOCK;
319 {
320 SCM vcell = scm_sym2vcell (name,
321 SCM_CDR (scm_top_level_lookup_thunk_var),
322 SCM_BOOL_T);
323 SCM_SETCDR (vcell, value);
324 }
325 SCM_END_FOREIGN_BLOCK;
326 return 0;
327}
328
329void
330scm_init_gdbint ()
331{
332 static char *s = "scm_init_gdb_interface";
333 SCM port;
334
335 scm_print_carefully_p = 0;
336
337 port = scm_mkstrport (SCM_INUM0,
338 scm_make_string (SCM_MAKINUM (80), SCM_UNDEFINED),
339 SCM_OPN | SCM_WRTNG,
340 s);
341 gdb_output_port = scm_permanent_object (port);
342
343 port = scm_mkstrport (SCM_INUM0,
344 scm_make_string (SCM_MAKINUM (0), SCM_UNDEFINED),
345 SCM_OPN | SCM_RDNG,
346 s);
347 gdb_input_port = scm_permanent_object (port);
380b6b4c
MD
348
349 tok_buf = scm_permanent_object (scm_makstr (30L, 0));
4907ff5a 350}