debug.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. /* Debugging extensions for Guile
  2. * Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008, 2009 Free Software Foundation
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public License
  6. * as published by the Free Software Foundation; either version 3 of
  7. * the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301 USA
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. # include <config.h>
  21. #endif
  22. #ifdef HAVE_GETRLIMIT
  23. #include <sys/time.h>
  24. #include <sys/resource.h>
  25. #endif
  26. #include "libguile/_scm.h"
  27. #include "libguile/async.h"
  28. #include "libguile/eval.h"
  29. #include "libguile/list.h"
  30. #include "libguile/stackchk.h"
  31. #include "libguile/throw.h"
  32. #include "libguile/macros.h"
  33. #include "libguile/smob.h"
  34. #include "libguile/procprop.h"
  35. #include "libguile/srcprop.h"
  36. #include "libguile/alist.h"
  37. #include "libguile/continuations.h"
  38. #include "libguile/strports.h"
  39. #include "libguile/read.h"
  40. #include "libguile/feature.h"
  41. #include "libguile/dynwind.h"
  42. #include "libguile/modules.h"
  43. #include "libguile/ports.h"
  44. #include "libguile/root.h"
  45. #include "libguile/fluids.h"
  46. #include "libguile/objects.h"
  47. #include "libguile/programs.h"
  48. #include "libguile/validate.h"
  49. #include "libguile/debug.h"
  50. #include "libguile/private-options.h"
  51. /* {Run time control of the debugging evaluator}
  52. */
  53. SCM_DEFINE (scm_debug_options, "debug-options-interface", 0, 1, 0,
  54. (SCM setting),
  55. "Option interface for the debug options. Instead of using\n"
  56. "this procedure directly, use the procedures @code{debug-enable},\n"
  57. "@code{debug-disable}, @code{debug-set!} and @code{debug-options}.")
  58. #define FUNC_NAME s_scm_debug_options
  59. {
  60. SCM ans;
  61. scm_dynwind_begin (0);
  62. scm_dynwind_critical_section (SCM_BOOL_F);
  63. ans = scm_options (setting, scm_debug_opts, FUNC_NAME);
  64. if (!(1 <= SCM_N_FRAMES && SCM_N_FRAMES <= SCM_MAX_FRAME_SIZE))
  65. {
  66. scm_options (ans, scm_debug_opts, FUNC_NAME);
  67. SCM_OUT_OF_RANGE (1, setting);
  68. }
  69. SCM_RESET_DEBUG_MODE;
  70. #ifdef STACK_CHECKING
  71. scm_stack_checking_enabled_p = SCM_STACK_CHECKING_P;
  72. #endif
  73. scm_debug_eframe_size = 2 * SCM_N_FRAMES;
  74. scm_dynwind_end ();
  75. return ans;
  76. }
  77. #undef FUNC_NAME
  78. static void
  79. with_traps_before (void *data)
  80. {
  81. int *trap_flag = data;
  82. *trap_flag = SCM_TRAPS_P;
  83. SCM_TRAPS_P = 1;
  84. }
  85. static void
  86. with_traps_after (void *data)
  87. {
  88. int *trap_flag = data;
  89. SCM_TRAPS_P = *trap_flag;
  90. }
  91. static SCM
  92. with_traps_inner (void *data)
  93. {
  94. SCM thunk = SCM_PACK ((scm_t_bits) data);
  95. return scm_call_0 (thunk);
  96. }
  97. SCM_DEFINE (scm_with_traps, "with-traps", 1, 0, 0,
  98. (SCM thunk),
  99. "Call @var{thunk} with traps enabled.")
  100. #define FUNC_NAME s_scm_with_traps
  101. {
  102. int trap_flag;
  103. SCM_VALIDATE_THUNK (1, thunk);
  104. return scm_internal_dynamic_wind (with_traps_before,
  105. with_traps_inner,
  106. with_traps_after,
  107. (void *) SCM_UNPACK (thunk),
  108. &trap_flag);
  109. }
  110. #undef FUNC_NAME
  111. SCM_SYMBOL (scm_sym_procname, "procname");
  112. SCM_SYMBOL (scm_sym_dots, "...");
  113. SCM_SYMBOL (scm_sym_source, "source");
  114. /* {Memoized Source}
  115. */
  116. scm_t_bits scm_tc16_memoized;
  117. static int
  118. memoized_print (SCM obj, SCM port, scm_print_state *pstate)
  119. {
  120. int writingp = SCM_WRITINGP (pstate);
  121. scm_puts ("#<memoized ", port);
  122. SCM_SET_WRITINGP (pstate, 1);
  123. scm_iprin1 (SCM_MEMOIZED_EXP (obj), port, pstate);
  124. SCM_SET_WRITINGP (pstate, writingp);
  125. scm_putc ('>', port);
  126. return 1;
  127. }
  128. SCM_DEFINE (scm_memoized_p, "memoized?", 1, 0, 0,
  129. (SCM obj),
  130. "Return @code{#t} if @var{obj} is memoized.")
  131. #define FUNC_NAME s_scm_memoized_p
  132. {
  133. return scm_from_bool(SCM_MEMOIZEDP (obj));
  134. }
  135. #undef FUNC_NAME
  136. SCM
  137. scm_make_memoized (SCM exp, SCM env)
  138. {
  139. /* *fixme* Check that env is a valid environment. */
  140. SCM_RETURN_NEWSMOB (scm_tc16_memoized, SCM_UNPACK (scm_cons (exp, env)));
  141. }
  142. #ifdef GUILE_DEBUG
  143. /*
  144. * Some primitives for construction of memoized code
  145. *
  146. * - procedure: memcons CAR CDR [ENV]
  147. *
  148. * Construct a pair, encapsulated in a memoized object.
  149. *
  150. * The CAR and CDR can be either normal or memoized. If ENV isn't
  151. * specified, the top-level environment of the current module will
  152. * be assumed. All environments must match.
  153. *
  154. * - procedure: make-iloc FRAME BINDING CDRP
  155. *
  156. * Return an iloc referring to frame no. FRAME, binding
  157. * no. BINDING. If CDRP is non-#f, the iloc is referring to a
  158. * frame consisting of a single pair, with the value stored in the
  159. * CDR.
  160. *
  161. * - procedure: iloc? OBJECT
  162. *
  163. * Return #t if OBJECT is an iloc.
  164. *
  165. * - procedure: mem->proc MEMOIZED
  166. *
  167. * Construct a closure from the memoized lambda expression MEMOIZED
  168. *
  169. * WARNING! The code is not copied!
  170. *
  171. * - procedure: proc->mem CLOSURE
  172. *
  173. * Turn the closure CLOSURE into a memoized object.
  174. *
  175. * WARNING! The code is not copied!
  176. *
  177. * - constant: SCM_IM_AND
  178. * - constant: SCM_IM_BEGIN
  179. * - constant: SCM_IM_CASE
  180. * - constant: SCM_IM_COND
  181. * - constant: SCM_IM_DO
  182. * - constant: SCM_IM_IF
  183. * - constant: SCM_IM_LAMBDA
  184. * - constant: SCM_IM_LET
  185. * - constant: SCM_IM_LETSTAR
  186. * - constant: SCM_IM_LETREC
  187. * - constant: SCM_IM_OR
  188. * - constant: SCM_IM_QUOTE
  189. * - constant: SCM_IM_SET
  190. * - constant: SCM_IM_DEFINE
  191. * - constant: SCM_IM_APPLY
  192. * - constant: SCM_IM_CONT
  193. * - constant: SCM_IM_DISPATCH
  194. */
  195. #include "libguile/variable.h"
  196. #include "libguile/procs.h"
  197. SCM_DEFINE (scm_memcons, "memcons", 2, 1, 0,
  198. (SCM car, SCM cdr, SCM env),
  199. "Return a new memoized cons cell with @var{car} and @var{cdr}\n"
  200. "as members and @var{env} as the environment.")
  201. #define FUNC_NAME s_scm_memcons
  202. {
  203. if (SCM_MEMOIZEDP (car))
  204. {
  205. /*fixme* environments may be two different but equal top-level envs */
  206. if (!SCM_UNBNDP (env) && SCM_MEMOIZED_ENV (car) != env)
  207. SCM_MISC_ERROR ("environment mismatch arg1 <-> arg3",
  208. scm_list_2 (car, env));
  209. else
  210. env = SCM_MEMOIZED_ENV (car);
  211. car = SCM_MEMOIZED_EXP (car);
  212. }
  213. if (SCM_MEMOIZEDP (cdr))
  214. {
  215. if (!SCM_UNBNDP (env) && SCM_MEMOIZED_ENV (cdr) != env)
  216. SCM_MISC_ERROR ("environment mismatch arg2 <-> arg3",
  217. scm_list_2 (cdr, env));
  218. else
  219. env = SCM_MEMOIZED_ENV (cdr);
  220. cdr = SCM_MEMOIZED_EXP (cdr);
  221. }
  222. if (SCM_UNBNDP (env))
  223. env = scm_top_level_env (SCM_TOP_LEVEL_LOOKUP_CLOSURE);
  224. else
  225. SCM_VALIDATE_NULLORCONS (3, env);
  226. return scm_make_memoized (scm_cons (car, cdr), env);
  227. }
  228. #undef FUNC_NAME
  229. SCM_DEFINE (scm_mem_to_proc, "mem->proc", 1, 0, 0,
  230. (SCM obj),
  231. "Convert a memoized object (which must represent a body)\n"
  232. "to a procedure.")
  233. #define FUNC_NAME s_scm_mem_to_proc
  234. {
  235. SCM env;
  236. SCM_VALIDATE_MEMOIZED (1, obj);
  237. env = SCM_MEMOIZED_ENV (obj);
  238. obj = SCM_MEMOIZED_EXP (obj);
  239. return scm_closure (obj, env);
  240. }
  241. #undef FUNC_NAME
  242. SCM_DEFINE (scm_proc_to_mem, "proc->mem", 1, 0, 0,
  243. (SCM obj),
  244. "Convert a procedure to a memoized object.")
  245. #define FUNC_NAME s_scm_proc_to_mem
  246. {
  247. SCM_VALIDATE_CLOSURE (1, obj);
  248. return scm_make_memoized (SCM_CODE (obj), SCM_ENV (obj));
  249. }
  250. #undef FUNC_NAME
  251. #endif /* GUILE_DEBUG */
  252. SCM_DEFINE (scm_i_unmemoize_expr, "unmemoize-expr", 1, 0, 0,
  253. (SCM m),
  254. "Unmemoize the memoized expression @var{m},")
  255. #define FUNC_NAME s_scm_i_unmemoize_expr
  256. {
  257. SCM_VALIDATE_MEMOIZED (1, m);
  258. return scm_i_unmemocopy_expr (SCM_MEMOIZED_EXP (m), SCM_MEMOIZED_ENV (m));
  259. }
  260. #undef FUNC_NAME
  261. SCM_DEFINE (scm_memoized_environment, "memoized-environment", 1, 0, 0,
  262. (SCM m),
  263. "Return the environment of the memoized expression @var{m}.")
  264. #define FUNC_NAME s_scm_memoized_environment
  265. {
  266. SCM_VALIDATE_MEMOIZED (1, m);
  267. return SCM_MEMOIZED_ENV (m);
  268. }
  269. #undef FUNC_NAME
  270. SCM_DEFINE (scm_procedure_name, "procedure-name", 1, 0, 0,
  271. (SCM proc),
  272. "Return the name of the procedure @var{proc}")
  273. #define FUNC_NAME s_scm_procedure_name
  274. {
  275. SCM_VALIDATE_PROC (1, proc);
  276. switch (SCM_TYP7 (proc)) {
  277. case scm_tcs_subrs:
  278. return SCM_SUBR_NAME (proc);
  279. default:
  280. {
  281. SCM name = scm_procedure_property (proc, scm_sym_name);
  282. #if 0
  283. /* Source property scm_sym_procname not implemented yet... */
  284. SCM name = scm_source_property (SCM_CAR (SCM_CLOSURE_BODY (proc)), scm_sym_procname);
  285. if (scm_is_false (name))
  286. name = scm_procedure_property (proc, scm_sym_name);
  287. #endif
  288. if (scm_is_false (name) && SCM_CLOSUREP (proc))
  289. name = scm_reverse_lookup (SCM_ENV (proc), proc);
  290. if (scm_is_false (name) && SCM_PROGRAM_P (proc))
  291. name = scm_program_name (proc);
  292. return name;
  293. }
  294. }
  295. }
  296. #undef FUNC_NAME
  297. SCM_DEFINE (scm_procedure_source, "procedure-source", 1, 0, 0,
  298. (SCM proc),
  299. "Return the source of the procedure @var{proc}.")
  300. #define FUNC_NAME s_scm_procedure_source
  301. {
  302. SCM_VALIDATE_NIM (1, proc);
  303. again:
  304. switch (SCM_TYP7 (proc)) {
  305. case scm_tcs_closures:
  306. {
  307. const SCM formals = SCM_CLOSURE_FORMALS (proc);
  308. const SCM body = SCM_CLOSURE_BODY (proc);
  309. const SCM src = scm_source_property (body, scm_sym_copy);
  310. if (scm_is_true (src))
  311. {
  312. return scm_cons2 (scm_sym_lambda, formals, src);
  313. }
  314. else
  315. {
  316. const SCM env = SCM_EXTEND_ENV (formals, SCM_EOL, SCM_ENV (proc));
  317. return scm_cons2 (scm_sym_lambda,
  318. scm_i_finite_list_copy (formals),
  319. scm_i_unmemocopy_body (body, env));
  320. }
  321. }
  322. case scm_tcs_struct:
  323. if (!SCM_I_OPERATORP (proc))
  324. break;
  325. goto procprop;
  326. case scm_tc7_smob:
  327. if (!SCM_SMOB_DESCRIPTOR (proc).apply)
  328. break;
  329. case scm_tcs_subrs:
  330. procprop:
  331. /* It would indeed be a nice thing if we supplied source even for
  332. built in procedures! */
  333. return scm_procedure_property (proc, scm_sym_source);
  334. case scm_tc7_pws:
  335. {
  336. SCM src = scm_procedure_property (proc, scm_sym_source);
  337. if (scm_is_true (src))
  338. return src;
  339. proc = SCM_PROCEDURE (proc);
  340. goto again;
  341. }
  342. default:
  343. ;
  344. }
  345. SCM_WRONG_TYPE_ARG (1, proc);
  346. return SCM_BOOL_F; /* not reached */
  347. }
  348. #undef FUNC_NAME
  349. SCM_DEFINE (scm_procedure_environment, "procedure-environment", 1, 0, 0,
  350. (SCM proc),
  351. "Return the environment of the procedure @var{proc}.")
  352. #define FUNC_NAME s_scm_procedure_environment
  353. {
  354. SCM_VALIDATE_NIM (1, proc);
  355. switch (SCM_TYP7 (proc)) {
  356. case scm_tcs_closures:
  357. return SCM_ENV (proc);
  358. case scm_tcs_subrs:
  359. return SCM_EOL;
  360. default:
  361. SCM_WRONG_TYPE_ARG (1, proc);
  362. /* not reached */
  363. }
  364. }
  365. #undef FUNC_NAME
  366. SCM_DEFINE (scm_procedure_module, "procedure-module", 1, 0, 0,
  367. (SCM proc),
  368. "Return the module that was current when @var{proc} was defined.")
  369. #define FUNC_NAME s_scm_procedure_module
  370. {
  371. SCM_VALIDATE_PROC (SCM_ARG1, proc);
  372. if (scm_is_true (scm_program_p (proc)))
  373. return scm_program_module (proc);
  374. else
  375. return scm_env_module (scm_procedure_environment (proc));
  376. }
  377. #undef FUNC_NAME
  378. /* Eval in a local environment. We would like to have the ability to
  379. * evaluate in a specified local environment, but due to the
  380. * memoization this isn't normally possible. We solve it by copying
  381. * the code before evaluating. One solution would be to have eval.c
  382. * generate yet another evaluator. They are not very big actually.
  383. */
  384. SCM_DEFINE (scm_local_eval, "local-eval", 1, 1, 0,
  385. (SCM exp, SCM env),
  386. "Evaluate @var{exp} in its environment. If @var{env} is supplied,\n"
  387. "it is the environment in which to evaluate @var{exp}. Otherwise,\n"
  388. "@var{exp} must be a memoized code object (in which case, its environment\n"
  389. "is implicit).")
  390. #define FUNC_NAME s_scm_local_eval
  391. {
  392. if (SCM_UNBNDP (env))
  393. {
  394. SCM_VALIDATE_MEMOIZED (1, exp);
  395. return scm_i_eval_x (SCM_MEMOIZED_EXP (exp), SCM_MEMOIZED_ENV (exp));
  396. }
  397. return scm_i_eval (exp, env);
  398. }
  399. #undef FUNC_NAME
  400. #if 0
  401. SCM_REGISTER_PROC (s_reverse_lookup, "reverse-lookup", 2, 0, 0, scm_reverse_lookup);
  402. #endif
  403. SCM
  404. scm_reverse_lookup (SCM env, SCM data)
  405. {
  406. while (scm_is_pair (env) && scm_is_pair (SCM_CAR (env)))
  407. {
  408. SCM names = SCM_CAAR (env);
  409. SCM values = SCM_CDAR (env);
  410. while (scm_is_pair (names))
  411. {
  412. if (scm_is_eq (SCM_CAR (values), data))
  413. return SCM_CAR (names);
  414. names = SCM_CDR (names);
  415. values = SCM_CDR (values);
  416. }
  417. if (!scm_is_null (names) && scm_is_eq (values, data))
  418. return names;
  419. env = SCM_CDR (env);
  420. }
  421. return SCM_BOOL_F;
  422. }
  423. SCM_DEFINE (scm_sys_start_stack, "%start-stack", 2, 0, 0,
  424. (SCM id, SCM thunk),
  425. "Call @var{thunk} on an evaluator stack tagged with @var{id}.")
  426. #define FUNC_NAME s_scm_sys_start_stack
  427. {
  428. SCM answer;
  429. scm_t_debug_frame vframe;
  430. scm_t_debug_info vframe_vect_body;
  431. vframe.prev = scm_i_last_debug_frame ();
  432. vframe.status = SCM_VOIDFRAME;
  433. vframe.vect = &vframe_vect_body;
  434. vframe.vect[0].id = id;
  435. scm_i_set_last_debug_frame (&vframe);
  436. answer = scm_call_0 (thunk);
  437. scm_i_set_last_debug_frame (vframe.prev);
  438. return answer;
  439. }
  440. #undef FUNC_NAME
  441. /* {Debug Objects}
  442. *
  443. * The debugging evaluator throws these on frame traps.
  444. */
  445. scm_t_bits scm_tc16_debugobj;
  446. static int
  447. debugobj_print (SCM obj, SCM port, scm_print_state *pstate SCM_UNUSED)
  448. {
  449. scm_puts ("#<debug-object ", port);
  450. scm_intprint ((long) SCM_DEBUGOBJ_FRAME (obj), 16, port);
  451. scm_putc ('>', port);
  452. return 1;
  453. }
  454. SCM_DEFINE (scm_debug_object_p, "debug-object?", 1, 0, 0,
  455. (SCM obj),
  456. "Return @code{#t} if @var{obj} is a debug object.")
  457. #define FUNC_NAME s_scm_debug_object_p
  458. {
  459. return scm_from_bool(SCM_DEBUGOBJP (obj));
  460. }
  461. #undef FUNC_NAME
  462. SCM
  463. scm_make_debugobj (scm_t_debug_frame *frame)
  464. {
  465. return scm_cell (scm_tc16_debugobj, (scm_t_bits) frame);
  466. }
  467. /* Undocumented debugging procedure */
  468. #ifdef GUILE_DEBUG
  469. SCM_DEFINE (scm_debug_hang, "debug-hang", 0, 1, 0,
  470. (SCM obj),
  471. "Go into an endless loop, which can be only terminated with\n"
  472. "a debugger.")
  473. #define FUNC_NAME s_scm_debug_hang
  474. {
  475. int go = 0;
  476. while (!go) ;
  477. return SCM_UNSPECIFIED;
  478. }
  479. #undef FUNC_NAME
  480. #endif
  481. static void
  482. init_stack_limit (void)
  483. {
  484. #ifdef HAVE_GETRLIMIT
  485. struct rlimit lim;
  486. if (getrlimit (RLIMIT_STACK, &lim) == 0)
  487. {
  488. rlim_t bytes = lim.rlim_cur;
  489. /* set our internal stack limit to 80% of the rlimit. */
  490. if (bytes == RLIM_INFINITY)
  491. bytes = lim.rlim_max;
  492. if (bytes != RLIM_INFINITY)
  493. SCM_STACK_LIMIT = bytes * 8 / 10 / sizeof (scm_t_bits);
  494. }
  495. errno = 0;
  496. #endif
  497. }
  498. void
  499. scm_init_debug ()
  500. {
  501. init_stack_limit ();
  502. scm_init_opts (scm_debug_options, scm_debug_opts);
  503. scm_tc16_memoized = scm_make_smob_type ("memoized", 0);
  504. scm_set_smob_mark (scm_tc16_memoized, scm_markcdr);
  505. scm_set_smob_print (scm_tc16_memoized, memoized_print);
  506. scm_tc16_debugobj = scm_make_smob_type ("debug-object", 0);
  507. scm_set_smob_print (scm_tc16_debugobj, debugobj_print);
  508. #ifdef GUILE_DEBUG
  509. scm_c_define ("SCM_IM_AND", SCM_IM_AND);
  510. scm_c_define ("SCM_IM_BEGIN", SCM_IM_BEGIN);
  511. scm_c_define ("SCM_IM_CASE", SCM_IM_CASE);
  512. scm_c_define ("SCM_IM_COND", SCM_IM_COND);
  513. scm_c_define ("SCM_IM_DO", SCM_IM_DO);
  514. scm_c_define ("SCM_IM_IF", SCM_IM_IF);
  515. scm_c_define ("SCM_IM_LAMBDA", SCM_IM_LAMBDA);
  516. scm_c_define ("SCM_IM_LET", SCM_IM_LET);
  517. scm_c_define ("SCM_IM_LETSTAR", SCM_IM_LETSTAR);
  518. scm_c_define ("SCM_IM_LETREC", SCM_IM_LETREC);
  519. scm_c_define ("SCM_IM_OR", SCM_IM_OR);
  520. scm_c_define ("SCM_IM_QUOTE", SCM_IM_QUOTE);
  521. scm_c_define ("SCM_IM_SET_X", SCM_IM_SET_X);
  522. scm_c_define ("SCM_IM_DEFINE", SCM_IM_DEFINE);
  523. scm_c_define ("SCM_IM_APPLY", SCM_IM_APPLY);
  524. scm_c_define ("SCM_IM_CONT", SCM_IM_CONT);
  525. scm_c_define ("SCM_IM_DISPATCH", SCM_IM_DISPATCH);
  526. #endif
  527. scm_add_feature ("debug-extensions");
  528. #include "libguile/debug.x"
  529. }
  530. /*
  531. Local Variables:
  532. c-file-style: "gnu"
  533. End:
  534. */