1 /* Copyright 2013-2014,2018
2 Free Software Foundation, Inc.
3
4 This file is part of Guile.
5
6 Guile is free software: you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Guile is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with Guile. If not, see
18 <https://www.gnu.org/licenses/>. */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #undef NDEBUG
25
26 #include <assert.h>
27 #include <libguile.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #define SMOBS_COUNT (10000)
32
33 struct x_tag
34 {
35 SCM scm_value;
36 int c_value;
37 };
38
39 typedef struct x_tag x_t;
40
41 unsigned int mark_call_count = 0;
42
43 static scm_t_bits x_tag;
44 static SCM make_x (void);
45 static SCM mark_x (SCM x);
46 static int print_x (SCM x, SCM port, scm_print_state * pstate);
47 static size_t free_x (SCM x);
48 static void init_smob_type (void);
49 static void test_scm_smob_mark (void);
50
51 static SCM
make_x()52 make_x ()
53 {
54 static int i = 0;
55 SCM s_x;
56 x_t *c_x;
57
58 i++;
59 c_x = (x_t *) scm_gc_malloc (sizeof (x_t), "x");
60 c_x->scm_value = scm_from_int (i);
61 c_x->c_value = i;
62 SCM_NEWSMOB (s_x, x_tag, c_x);
63 return s_x;
64 }
65
66 static SCM
mark_x(SCM x)67 mark_x (SCM x)
68 {
69 x_t *c_x;
70 c_x = (x_t *) SCM_SMOB_DATA (x);
71 scm_gc_mark (c_x->scm_value);
72 mark_call_count++;
73 return SCM_BOOL_F;
74 }
75
76 static size_t
free_x(SCM x)77 free_x (SCM x)
78 {
79 x_t *c_x;
80 c_x = (x_t *) SCM_SMOB_DATA (x);
81 scm_gc_free (c_x, sizeof (x_t), "x");
82 c_x = NULL;
83 return 0;
84 }
85
86 static int
print_x(SCM x,SCM port,scm_print_state * pstate SCM_UNUSED)87 print_x (SCM x, SCM port, scm_print_state * pstate SCM_UNUSED)
88 {
89 x_t *c_x = (x_t *) SCM_SMOB_DATA (x);
90 scm_puts ("#<x ", port);
91 if (c_x == (x_t *) NULL)
92 scm_puts ("(freed)", port);
93 else
94 scm_write (c_x->scm_value, port);
95 scm_puts (">", port);
96
97 return 1;
98 }
99
100 static void
test_scm_smob_mark()101 test_scm_smob_mark ()
102 {
103 int i;
104 mark_call_count = 0;
105 for (i = 0; i < SMOBS_COUNT; i++)
106 make_x ();
107 scm_gc ();
108 if (mark_call_count < SMOBS_COUNT)
109 {
110 fprintf (stderr, "FAIL: SMOB mark function called for each SMOB\n");
111 exit (EXIT_FAILURE);
112 }
113 }
114
115 static void
init_smob_type()116 init_smob_type ()
117 {
118 x_tag = scm_make_smob_type ("x", sizeof (x_t));
119 scm_set_smob_free (x_tag, free_x);
120 scm_set_smob_print (x_tag, print_x);
121 scm_set_smob_mark (x_tag, mark_x);
122 }
123
124 static void
tests(void * data,int argc,char ** argv)125 tests (void *data, int argc, char **argv)
126 {
127 init_smob_type ();
128 test_scm_smob_mark ();
129 }
130
131 int
main(int argc,char * argv[])132 main (int argc, char *argv[])
133 {
134 scm_boot_guile (argc, argv, tests, NULL);
135 return 0;
136 }
137