gdbint.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* GDB interface for Guile
  2. * Copyright (C) 1996,1997,1999,2000,2001 Free Software Foundation, Inc.
  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, Inc., 51 Franklin Street, Fifth Floor,
  17. * Boston, MA 02110-1301 USA
  18. *
  19. * As a special exception, the Free Software Foundation gives permission
  20. * for additional uses of the text contained in its release of GUILE.
  21. *
  22. * The exception is that, if you link the GUILE library with other files
  23. * to produce an executable, this does not by itself cause the
  24. * resulting executable to be covered by the GNU General Public License.
  25. * Your use of that executable is in no way restricted on account of
  26. * linking the GUILE library code into it.
  27. *
  28. * This exception does not however invalidate any other reasons why
  29. * the executable file might be covered by the GNU General Public License.
  30. *
  31. * This exception applies only to the code released by the
  32. * Free Software Foundation under the name GUILE. If you copy
  33. * code from other Free Software Foundation releases into a copy of
  34. * GUILE, as the General Public License permits, the exception does
  35. * not apply to the code that you add in this way. To avoid misleading
  36. * anyone as to the status of such modified files, you must delete
  37. * this exception notice from them.
  38. *
  39. * If you write modifications of your own for GUILE, it is your choice
  40. * whether to permit this exception to apply to your modifications.
  41. * If you do not wish that, delete this exception notice.
  42. *
  43. * The author can be reached at djurfeldt@nada.kth.se
  44. * Mikael Djurfeldt, SANS/NADA KTH, 10044 STOCKHOLM, SWEDEN */
  45. #include "libguile/_scm.h"
  46. #include <stdio.h>
  47. #include <string.h>
  48. #ifdef HAVE_UNISTD_H
  49. #include <unistd.h>
  50. #endif
  51. #include "libguile/strports.h"
  52. #include "libguile/read.h"
  53. #include "libguile/eval.h"
  54. #include "libguile/chars.h"
  55. #include "libguile/modules.h"
  56. #include "libguile/ports.h"
  57. #include "libguile/fluids.h"
  58. #include "libguile/strings.h"
  59. #include "libguile/init.h"
  60. #include "libguile/gdbint.h"
  61. /* {Support for debugging with gdb}
  62. *
  63. * TODO:
  64. *
  65. * 1. Redirect outputs
  66. * 2. Catch errors
  67. * 3. Prevent print from causing segmentation fault when given broken pairs
  68. */
  69. #define GDB_TYPE SCM
  70. #include "libguile/gdb_interface.h"
  71. /* Be carefull when this macro is true.
  72. scm_gc_running_p is set during gc.
  73. */
  74. #define SCM_GC_P (scm_gc_running_p)
  75. /* Macros that encapsulate blocks of code which can be called by the
  76. * debugger.
  77. */
  78. #define SCM_BEGIN_FOREIGN_BLOCK \
  79. do { \
  80. old_ints = scm_ints_disabled; scm_ints_disabled = 1; \
  81. old_gc = scm_block_gc; scm_block_gc = 1; \
  82. scm_print_carefully_p = 1; \
  83. } while (0)
  84. #define SCM_END_FOREIGN_BLOCK \
  85. do { \
  86. scm_print_carefully_p = 0; \
  87. scm_block_gc = old_gc; \
  88. scm_ints_disabled = old_ints; \
  89. } while (0)
  90. #define RESET_STRING { gdb_output_length = 0; }
  91. #define SEND_STRING(str) \
  92. do { \
  93. gdb_output = (char *) (str); \
  94. gdb_output_length = strlen ((const char *) (str)); \
  95. } while (0)
  96. /* {Gdb interface}
  97. */
  98. unsigned short gdb_options = GDB_HAVE_BINDINGS;
  99. char *gdb_language = "lisp/c";
  100. SCM gdb_result;
  101. char *gdb_output;
  102. int gdb_output_length;
  103. int scm_print_carefully_p;
  104. static SCM gdb_input_port;
  105. static int port_mark_p, stream_mark_p, string_mark_p;
  106. static SCM tok_buf;
  107. static int tok_buf_mark_p;
  108. static SCM gdb_output_port;
  109. static int old_ints, old_gc;
  110. static void
  111. unmark_port (SCM port)
  112. {
  113. SCM stream, string;
  114. port_mark_p = SCM_GCMARKP (port);
  115. SCM_CLRGCMARK (port);
  116. stream = SCM_PACK (SCM_STREAM (port));
  117. stream_mark_p = SCM_GCMARKP (stream);
  118. SCM_CLRGCMARK (stream);
  119. string = SCM_CDR (stream);
  120. string_mark_p = SCM_GCMARKP (string);
  121. SCM_CLRGCMARK (string);
  122. }
  123. static void
  124. remark_port (SCM port)
  125. {
  126. SCM stream = SCM_PACK (SCM_STREAM (port));
  127. SCM string = SCM_CDR (stream);
  128. if (string_mark_p) SCM_SETGCMARK (string);
  129. if (stream_mark_p) SCM_SETGCMARK (stream);
  130. if (port_mark_p) SCM_SETGCMARK (port);
  131. }
  132. int
  133. gdb_maybe_valid_type_p (SCM value)
  134. {
  135. return SCM_IMP (value) || scm_cellp (value);
  136. }
  137. int
  138. gdb_read (char *str)
  139. {
  140. SCM ans;
  141. int status = 0;
  142. RESET_STRING;
  143. /* Need to be restrictive about what to read? */
  144. if (SCM_GC_P)
  145. {
  146. char *p;
  147. for (p = str; *p != '\0'; ++p)
  148. switch (*p)
  149. {
  150. case '(':
  151. case '\'':
  152. case '"':
  153. SEND_STRING ("Can't read this kind of expressions during gc");
  154. return -1;
  155. case '#':
  156. if (*++p == '\0')
  157. goto premature;
  158. if (*p == '\\')
  159. {
  160. if (*++p != '\0')
  161. continue;
  162. premature:
  163. SEND_STRING ("Premature end of lisp expression");
  164. return -1;
  165. }
  166. default:
  167. continue;
  168. }
  169. }
  170. SCM_BEGIN_FOREIGN_BLOCK;
  171. unmark_port (gdb_input_port);
  172. scm_seek (gdb_input_port, SCM_INUM0, SCM_MAKINUM (SEEK_SET));
  173. scm_puts (str, gdb_input_port);
  174. scm_truncate_file (gdb_input_port, SCM_UNDEFINED);
  175. scm_seek (gdb_input_port, SCM_INUM0, SCM_MAKINUM (SEEK_SET));
  176. /* Read one object */
  177. tok_buf_mark_p = SCM_GCMARKP (tok_buf);
  178. SCM_CLRGCMARK (tok_buf);
  179. ans = scm_lreadr (&tok_buf, gdb_input_port, &ans);
  180. if (SCM_GC_P)
  181. {
  182. if (SCM_NIMP (ans))
  183. {
  184. SEND_STRING ("Non-immediate created during gc. Memory may be trashed.");
  185. status = -1;
  186. goto exit;
  187. }
  188. }
  189. gdb_result = ans;
  190. /* Protect answer from future GC */
  191. if (SCM_NIMP (ans))
  192. scm_permanent_object (ans);
  193. exit:
  194. if (tok_buf_mark_p)
  195. SCM_SETGCMARK (tok_buf);
  196. remark_port (gdb_input_port);
  197. SCM_END_FOREIGN_BLOCK;
  198. return status;
  199. }
  200. int
  201. gdb_eval (SCM exp)
  202. {
  203. RESET_STRING;
  204. if (SCM_IMP (exp))
  205. {
  206. gdb_result = exp;
  207. return 0;
  208. }
  209. if (SCM_GC_P)
  210. {
  211. SEND_STRING ("Can't evaluate lisp expressions during gc");
  212. return -1;
  213. }
  214. SCM_BEGIN_FOREIGN_BLOCK;
  215. {
  216. SCM env = scm_top_level_env (SCM_TOP_LEVEL_LOOKUP_CLOSURE);
  217. gdb_result = scm_permanent_object (scm_ceval (exp, env));
  218. }
  219. SCM_END_FOREIGN_BLOCK;
  220. return 0;
  221. }
  222. int
  223. gdb_print (SCM obj)
  224. {
  225. if (!scm_initialized_p)
  226. SEND_STRING ("*** Guile not initialized ***");
  227. else
  228. {
  229. RESET_STRING;
  230. SCM_BEGIN_FOREIGN_BLOCK;
  231. /* Reset stream */
  232. scm_seek (gdb_output_port, SCM_INUM0, SCM_MAKINUM (SEEK_SET));
  233. scm_write (obj, gdb_output_port);
  234. scm_truncate_file (gdb_output_port, SCM_UNDEFINED);
  235. {
  236. scm_t_port *pt = SCM_PTAB_ENTRY (gdb_output_port);
  237. scm_flush (gdb_output_port);
  238. *(pt->write_buf + pt->read_buf_size) = 0;
  239. SEND_STRING (pt->read_buf);
  240. }
  241. SCM_END_FOREIGN_BLOCK;
  242. }
  243. return 0;
  244. }
  245. int
  246. gdb_binding (SCM name, SCM value)
  247. {
  248. RESET_STRING;
  249. if (SCM_GC_P)
  250. {
  251. SEND_STRING ("Can't create new bindings during gc");
  252. return -1;
  253. }
  254. SCM_BEGIN_FOREIGN_BLOCK;
  255. {
  256. SCM var = scm_sym2var (name, SCM_TOP_LEVEL_LOOKUP_CLOSURE, SCM_BOOL_T);
  257. SCM_VARIABLE_SET (var, value);
  258. }
  259. SCM_END_FOREIGN_BLOCK;
  260. return 0;
  261. }
  262. void
  263. scm_init_gdbint ()
  264. {
  265. static char *s = "scm_init_gdb_interface";
  266. SCM port;
  267. scm_print_carefully_p = 0;
  268. port = scm_mkstrport (SCM_INUM0,
  269. scm_make_string (SCM_MAKINUM (0), SCM_UNDEFINED),
  270. SCM_OPN | SCM_WRTNG,
  271. s);
  272. gdb_output_port = scm_permanent_object (port);
  273. port = scm_mkstrport (SCM_INUM0,
  274. scm_make_string (SCM_MAKINUM (0), SCM_UNDEFINED),
  275. SCM_OPN | SCM_RDNG | SCM_WRTNG,
  276. s);
  277. gdb_input_port = scm_permanent_object (port);
  278. tok_buf = scm_permanent_object (scm_allocate_string (30));
  279. }
  280. /*
  281. Local Variables:
  282. c-file-style: "gnu"
  283. End:
  284. */