gdbint.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /* GDB interface for Guile
  2. * Copyright (C) 1996,1997,1999,2000,2001,2002,2004
  3. * Free Software Foundation, Inc.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22. #include "libguile/_scm.h"
  23. #include <stdio.h>
  24. #include <string.h>
  25. #ifdef HAVE_UNISTD_H
  26. #include <unistd.h>
  27. #endif
  28. #include "libguile/strports.h"
  29. #include "libguile/read.h"
  30. #include "libguile/eval.h"
  31. #include "libguile/chars.h"
  32. #include "libguile/modules.h"
  33. #include "libguile/ports.h"
  34. #include "libguile/fluids.h"
  35. #include "libguile/strings.h"
  36. #include "libguile/init.h"
  37. #include "libguile/gdbint.h"
  38. /* {Support for debugging with gdb}
  39. *
  40. * TODO:
  41. *
  42. * 1. Redirect outputs
  43. * 2. Catch errors
  44. * 3. Prevent print from causing segmentation fault when given broken pairs
  45. */
  46. #define GDB_TYPE SCM
  47. #include "libguile/gdb_interface.h"
  48. /* Be carefull when this macro is true.
  49. scm_gc_running_p is set during gc.
  50. */
  51. #define SCM_GC_P (scm_gc_running_p)
  52. /* Macros that encapsulate blocks of code which can be called by the
  53. * debugger.
  54. */
  55. #define SCM_BEGIN_FOREIGN_BLOCK \
  56. do { \
  57. scm_print_carefully_p = 1; \
  58. } while (0)
  59. #define SCM_END_FOREIGN_BLOCK \
  60. do { \
  61. scm_print_carefully_p = 0; \
  62. } while (0)
  63. #define RESET_STRING { gdb_output_length = 0; }
  64. #define SEND_STRING(str) \
  65. do { \
  66. gdb_output = (char *) (str); \
  67. gdb_output_length = strlen ((const char *) (str)); \
  68. } while (0)
  69. /* {Gdb interface}
  70. */
  71. unsigned short gdb_options = GDB_HAVE_BINDINGS;
  72. char *gdb_language = "lisp/c";
  73. SCM gdb_result;
  74. char *gdb_output;
  75. int gdb_output_length;
  76. int scm_print_carefully_p;
  77. static SCM gdb_input_port;
  78. static int port_mark_p, stream_mark_p, string_mark_p;
  79. static SCM gdb_output_port;
  80. static void
  81. unmark_port (SCM port)
  82. {
  83. SCM stream, string;
  84. port_mark_p = SCM_GC_MARK_P (port);
  85. SCM_CLEAR_GC_MARK (port);
  86. stream = SCM_PACK (SCM_STREAM (port));
  87. stream_mark_p = SCM_GC_MARK_P (stream);
  88. SCM_CLEAR_GC_MARK (stream);
  89. string = SCM_CDR (stream);
  90. string_mark_p = SCM_GC_MARK_P (string);
  91. SCM_CLEAR_GC_MARK (string);
  92. }
  93. static void
  94. remark_port (SCM port)
  95. {
  96. SCM stream = SCM_PACK (SCM_STREAM (port));
  97. SCM string = SCM_CDR (stream);
  98. if (string_mark_p)
  99. SCM_SET_GC_MARK (string);
  100. if (stream_mark_p)
  101. SCM_SET_GC_MARK (stream);
  102. if (port_mark_p)
  103. SCM_SET_GC_MARK (port);
  104. }
  105. int
  106. gdb_maybe_valid_type_p (SCM value)
  107. {
  108. return SCM_IMP (value) || scm_in_heap_p (value);
  109. }
  110. int
  111. gdb_read (char *str)
  112. {
  113. SCM ans;
  114. int status = 0;
  115. RESET_STRING;
  116. /* Need to be restrictive about what to read? */
  117. if (SCM_GC_P)
  118. {
  119. char *p;
  120. for (p = str; *p != '\0'; ++p)
  121. switch (*p)
  122. {
  123. case '(':
  124. case '\'':
  125. case '"':
  126. SEND_STRING ("Can't read this kind of expressions during gc");
  127. return -1;
  128. case '#':
  129. if (*++p == '\0')
  130. goto premature;
  131. if (*p == '\\')
  132. {
  133. if (*++p != '\0')
  134. continue;
  135. premature:
  136. SEND_STRING ("Premature end of lisp expression");
  137. return -1;
  138. }
  139. default:
  140. continue;
  141. }
  142. }
  143. SCM_BEGIN_FOREIGN_BLOCK;
  144. unmark_port (gdb_input_port);
  145. scm_seek (gdb_input_port, SCM_INUM0, scm_from_int (SEEK_SET));
  146. scm_puts (str, gdb_input_port);
  147. scm_truncate_file (gdb_input_port, SCM_UNDEFINED);
  148. scm_seek (gdb_input_port, SCM_INUM0, scm_from_int (SEEK_SET));
  149. /* Read one object */
  150. ans = scm_read (gdb_input_port);
  151. if (SCM_GC_P)
  152. {
  153. if (SCM_NIMP (ans))
  154. {
  155. SEND_STRING ("Non-immediate created during gc. Memory may be trashed.");
  156. status = -1;
  157. goto exit;
  158. }
  159. }
  160. gdb_result = ans;
  161. /* Protect answer from future GC */
  162. if (SCM_NIMP (ans))
  163. scm_permanent_object (ans);
  164. exit:
  165. remark_port (gdb_input_port);
  166. SCM_END_FOREIGN_BLOCK;
  167. return status;
  168. }
  169. int
  170. gdb_eval (SCM exp)
  171. {
  172. RESET_STRING;
  173. if (SCM_GC_P)
  174. {
  175. SEND_STRING ("Can't evaluate lisp expressions during gc");
  176. return -1;
  177. }
  178. SCM_BEGIN_FOREIGN_BLOCK;
  179. {
  180. SCM env = scm_top_level_env (SCM_TOP_LEVEL_LOOKUP_CLOSURE);
  181. gdb_result = scm_permanent_object (scm_i_eval_x (exp, env));
  182. }
  183. SCM_END_FOREIGN_BLOCK;
  184. return 0;
  185. }
  186. int
  187. gdb_print (SCM obj)
  188. {
  189. if (!scm_initialized_p)
  190. SEND_STRING ("*** Guile not initialized ***");
  191. else
  192. {
  193. RESET_STRING;
  194. SCM_BEGIN_FOREIGN_BLOCK;
  195. /* Reset stream */
  196. scm_seek (gdb_output_port, SCM_INUM0, scm_from_int (SEEK_SET));
  197. scm_write (obj, gdb_output_port);
  198. scm_truncate_file (gdb_output_port, SCM_UNDEFINED);
  199. {
  200. scm_t_port *pt = SCM_PTAB_ENTRY (gdb_output_port);
  201. scm_flush (gdb_output_port);
  202. *(pt->write_buf + pt->read_buf_size) = 0;
  203. SEND_STRING (pt->read_buf);
  204. }
  205. SCM_END_FOREIGN_BLOCK;
  206. }
  207. return 0;
  208. }
  209. int
  210. gdb_binding (SCM name, SCM value)
  211. {
  212. RESET_STRING;
  213. if (SCM_GC_P)
  214. {
  215. SEND_STRING ("Can't create new bindings during gc");
  216. return -1;
  217. }
  218. SCM_BEGIN_FOREIGN_BLOCK;
  219. {
  220. SCM var = scm_sym2var (name, SCM_TOP_LEVEL_LOOKUP_CLOSURE, SCM_BOOL_T);
  221. SCM_VARIABLE_SET (var, value);
  222. }
  223. SCM_END_FOREIGN_BLOCK;
  224. return 0;
  225. }
  226. void
  227. scm_init_gdbint ()
  228. {
  229. static char *s = "scm_init_gdb_interface";
  230. SCM port;
  231. scm_print_carefully_p = 0;
  232. port = scm_mkstrport (SCM_INUM0,
  233. scm_c_make_string (0, SCM_UNDEFINED),
  234. SCM_OPN | SCM_WRTNG,
  235. s);
  236. gdb_output_port = scm_permanent_object (port);
  237. port = scm_mkstrport (SCM_INUM0,
  238. scm_c_make_string (0, SCM_UNDEFINED),
  239. SCM_OPN | SCM_RDNG | SCM_WRTNG,
  240. s);
  241. gdb_input_port = scm_permanent_object (port);
  242. }
  243. /*
  244. Local Variables:
  245. c-file-style: "gnu"
  246. End:
  247. */