1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2006, 2008 Free Software Foundation
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public License
5 * as published by the Free Software Foundation; either version 3 of
6 * the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include "libguile/_scm.h"
28 #include "libguile/async.h"
29 #include "libguile/smob.h"
30 #include "libguile/alist.h"
31 #include "libguile/debug.h"
32 #include "libguile/hashtab.h"
33 #include "libguile/hash.h"
34 #include "libguile/ports.h"
35 #include "libguile/root.h"
36 #include "libguile/weaks.h"
37 #include "libguile/gc.h"
39 #include "libguile/validate.h"
40 #include "libguile/srcprop.h"
42 /* {Source Properties}
44 * Properties of source list expressions.
45 * Five of these have special meaning:
47 * filename string The name of the source file.
48 * copy list A copy of the list expression.
49 * line integer The source code line number.
50 * column integer The source code column number.
51 * breakpoint boolean Sets a breakpoint on this form.
53 * Most properties above can be set by the reader.
57 SCM_GLOBAL_SYMBOL (scm_sym_filename
, "filename");
58 SCM_GLOBAL_SYMBOL (scm_sym_copy
, "copy");
59 SCM_GLOBAL_SYMBOL (scm_sym_line
, "line");
60 SCM_GLOBAL_SYMBOL (scm_sym_column
, "column");
61 SCM_GLOBAL_SYMBOL (scm_sym_breakpoint
, "breakpoint");
66 * Source properties are stored as double cells with the
75 #define SRCPROPSP(p) (SCM_SMOB_PREDICATE (scm_tc16_srcprops, (p)))
76 #define SRCPROPBRK(p) (SCM_SMOB_FLAGS (p) & SCM_SOURCE_PROPERTY_FLAG_BREAK)
77 #define SRCPROPPOS(p) (SCM_CELL_WORD(p,1))
78 #define SRCPROPLINE(p) (SRCPROPPOS(p) >> 12)
79 #define SRCPROPCOL(p) (SRCPROPPOS(p) & 0x0fffL)
80 #define SRCPROPCOPY(p) (SCM_CELL_OBJECT(p,2))
81 #define SRCPROPALIST(p) (SCM_CELL_OBJECT_3(p))
82 #define SETSRCPROPBRK(p) \
83 (SCM_SET_SMOB_FLAGS ((p), \
84 SCM_SMOB_FLAGS (p) | SCM_SOURCE_PROPERTY_FLAG_BREAK))
85 #define CLEARSRCPROPBRK(p) \
86 (SCM_SET_SMOB_FLAGS ((p), \
87 SCM_SMOB_FLAGS (p) & ~SCM_SOURCE_PROPERTY_FLAG_BREAK))
88 #define SRCPROPMAKPOS(l, c) (((l) << 12) + (c))
89 #define SETSRCPROPPOS(p, l, c) (SCM_SET_CELL_WORD(p,1, SRCPROPMAKPOS (l, c)))
90 #define SETSRCPROPLINE(p, l) SETSRCPROPPOS (p, l, SRCPROPCOL (p))
91 #define SETSRCPROPCOL(p, c) SETSRCPROPPOS (p, SRCPROPLINE (p), c)
92 #define SETSRCPROPCOPY(p, c) (SCM_SET_CELL_WORD(p, 2, c))
93 #define SETSRCPROPALIST(p, l) (SCM_SET_CELL_WORD(p, 3, l))
96 static SCM
scm_srcprops_to_alist (SCM obj
);
99 scm_t_bits scm_tc16_srcprops
;
102 srcprops_print (SCM obj
, SCM port
, scm_print_state
*pstate
)
104 int writingp
= SCM_WRITINGP (pstate
);
105 scm_puts ("#<srcprops ", port
);
106 SCM_SET_WRITINGP (pstate
, 1);
107 scm_iprin1 (scm_srcprops_to_alist (obj
), port
, pstate
);
108 SCM_SET_WRITINGP (pstate
, writingp
);
109 scm_putc ('>', port
);
115 scm_c_source_property_breakpoint_p (SCM form
)
117 SCM obj
= scm_whash_lookup (scm_source_whash
, form
);
118 return SRCPROPSP (obj
) && SRCPROPBRK (obj
);
123 * We remember the last file name settings, so we can share that alist
124 * entry. This works because scm_set_source_property_x does not use
125 * assoc-set! for modifying the alist.
127 * This variable contains a protected cons, whose cdr is the cached
130 static SCM scm_last_alist_filename
;
133 scm_make_srcprops (long line
, int col
, SCM filename
, SCM copy
, SCM alist
)
135 if (!SCM_UNBNDP (filename
))
137 SCM old_alist
= alist
;
140 have to extract the acons, and operate on that, for
143 SCM last_acons
= SCM_CDR (scm_last_alist_filename
);
144 if (old_alist
== SCM_EOL
145 && SCM_CDAR (last_acons
) == filename
)
151 alist
= scm_acons (scm_sym_filename
, filename
, alist
);
152 if (old_alist
== SCM_EOL
)
153 SCM_SETCDR (scm_last_alist_filename
, alist
);
157 SCM_RETURN_NEWSMOB3 (scm_tc16_srcprops
,
158 SRCPROPMAKPOS (line
, col
),
165 scm_srcprops_to_alist (SCM obj
)
167 SCM alist
= SRCPROPALIST (obj
);
168 if (!SCM_UNBNDP (SRCPROPCOPY (obj
)))
169 alist
= scm_acons (scm_sym_copy
, SRCPROPCOPY (obj
), alist
);
170 alist
= scm_acons (scm_sym_column
, scm_from_int (SRCPROPCOL (obj
)), alist
);
171 alist
= scm_acons (scm_sym_line
, scm_from_int (SRCPROPLINE (obj
)), alist
);
172 alist
= scm_acons (scm_sym_breakpoint
, scm_from_bool (SRCPROPBRK (obj
)), alist
);
176 SCM_DEFINE (scm_source_properties
, "source-properties", 1, 0, 0,
178 "Return the source property association list of @var{obj}.")
179 #define FUNC_NAME s_scm_source_properties
182 SCM_VALIDATE_NIM (1, obj
);
183 if (SCM_MEMOIZEDP (obj
))
184 obj
= SCM_MEMOIZED_EXP (obj
);
185 else if (!scm_is_pair (obj
))
186 SCM_WRONG_TYPE_ARG (1, obj
);
187 p
= scm_hashq_ref (scm_source_whash
, obj
, SCM_EOL
);
189 return scm_srcprops_to_alist (p
);
191 /* list from set-source-properties!, or SCM_EOL for not found */
196 /* Perhaps this procedure should look through an alist
197 and try to make a srcprops-object...? */
198 SCM_DEFINE (scm_set_source_properties_x
, "set-source-properties!", 2, 0, 0,
199 (SCM obj
, SCM alist
),
200 "Install the association list @var{alist} as the source property\n"
201 "list for @var{obj}.")
202 #define FUNC_NAME s_scm_set_source_properties_x
205 long line
= 0, col
= 0;
206 SCM fname
= SCM_UNDEFINED
, copy
= SCM_UNDEFINED
, breakpoint
= SCM_BOOL_F
;
207 SCM others
= SCM_EOL
;
208 SCM
*others_cdrloc
= &others
;
209 int need_srcprops
= 0;
212 SCM_VALIDATE_NIM (1, obj
);
213 if (SCM_MEMOIZEDP (obj
))
214 obj
= SCM_MEMOIZED_EXP (obj
);
215 else if (!scm_is_pair (obj
))
216 SCM_WRONG_TYPE_ARG(1, obj
);
219 while (!scm_is_null (tail
))
221 key
= SCM_CAAR (tail
);
222 if (scm_is_eq (key
, scm_sym_line
))
224 line
= scm_to_long (SCM_CDAR (tail
));
227 else if (scm_is_eq (key
, scm_sym_column
))
229 col
= scm_to_long (SCM_CDAR (tail
));
232 else if (scm_is_eq (key
, scm_sym_filename
))
234 fname
= SCM_CDAR (tail
);
237 else if (scm_is_eq (key
, scm_sym_copy
))
239 copy
= SCM_CDAR (tail
);
242 else if (scm_is_eq (key
, scm_sym_breakpoint
))
244 breakpoint
= SCM_CDAR (tail
);
249 /* Do we allocate here, or clobber the caller's alist?
251 Source properties aren't supposed to be used for anything
252 except the special properties above, so the mainline case
253 is that we never execute this else branch, and hence it
256 We choose allocation here, as that seems safer.
258 *others_cdrloc
= scm_cons (scm_cons (key
, SCM_CDAR (tail
)),
260 others_cdrloc
= SCM_CDRLOC (*others_cdrloc
);
262 tail
= SCM_CDR (tail
);
266 alist
= scm_make_srcprops (line
, col
, fname
, copy
, others
);
267 if (scm_is_true (breakpoint
))
268 SETSRCPROPBRK (alist
);
273 handle
= scm_hashq_create_handle_x (scm_source_whash
, obj
, alist
);
274 SCM_SETCDR (handle
, alist
);
279 SCM_DEFINE (scm_source_property
, "source-property", 2, 0, 0,
281 "Return the source property specified by @var{key} from\n"
282 "@var{obj}'s source property list.")
283 #define FUNC_NAME s_scm_source_property
286 SCM_VALIDATE_NIM (1, obj
);
287 if (SCM_MEMOIZEDP (obj
))
288 obj
= SCM_MEMOIZED_EXP (obj
);
289 else if (!scm_is_pair (obj
))
290 SCM_WRONG_TYPE_ARG (1, obj
);
291 p
= scm_hashq_ref (scm_source_whash
, obj
, SCM_EOL
);
294 if (scm_is_eq (scm_sym_breakpoint
, key
)) p
= scm_from_bool (SRCPROPBRK (p
));
295 else if (scm_is_eq (scm_sym_line
, key
)) p
= scm_from_int (SRCPROPLINE (p
));
296 else if (scm_is_eq (scm_sym_column
, key
)) p
= scm_from_int (SRCPROPCOL (p
));
297 else if (scm_is_eq (scm_sym_copy
, key
)) p
= SRCPROPCOPY (p
);
300 p
= SRCPROPALIST (p
);
302 p
= scm_assoc (key
, p
);
303 return (SCM_NIMP (p
) ? SCM_CDR (p
) : SCM_BOOL_F
);
305 return SCM_UNBNDP (p
) ? SCM_BOOL_F
: p
;
309 SCM_DEFINE (scm_set_source_property_x
, "set-source-property!", 3, 0, 0,
310 (SCM obj
, SCM key
, SCM datum
),
311 "Set the source property of object @var{obj}, which is specified by\n"
312 "@var{key} to @var{datum}. Normally, the key will be a symbol.")
313 #define FUNC_NAME s_scm_set_source_property_x
317 SCM_VALIDATE_NIM (1, obj
);
318 if (SCM_MEMOIZEDP (obj
))
319 obj
= SCM_MEMOIZED_EXP (obj
);
320 else if (!scm_is_pair (obj
))
321 SCM_WRONG_TYPE_ARG (1, obj
);
322 h
= scm_whash_get_handle (scm_source_whash
, obj
);
323 if (SCM_WHASHFOUNDP (h
))
324 p
= SCM_WHASHREF (scm_source_whash
, h
);
327 h
= scm_whash_create_handle (scm_source_whash
, obj
);
330 if (scm_is_eq (scm_sym_breakpoint
, key
))
334 if (scm_is_false (datum
))
341 SCM sp
= scm_make_srcprops (0, 0, SCM_UNDEFINED
, SCM_UNDEFINED
, p
);
342 SCM_WHASHSET (scm_source_whash
, h
, sp
);
343 if (scm_is_false (datum
))
344 CLEARSRCPROPBRK (sp
);
349 else if (scm_is_eq (scm_sym_line
, key
))
352 SETSRCPROPLINE (p
, scm_to_int (datum
));
354 SCM_WHASHSET (scm_source_whash
, h
,
355 scm_make_srcprops (scm_to_int (datum
), 0,
356 SCM_UNDEFINED
, SCM_UNDEFINED
, p
));
358 else if (scm_is_eq (scm_sym_column
, key
))
361 SETSRCPROPCOL (p
, scm_to_int (datum
));
363 SCM_WHASHSET (scm_source_whash
, h
,
364 scm_make_srcprops (0, scm_to_int (datum
),
365 SCM_UNDEFINED
, SCM_UNDEFINED
, p
));
367 else if (scm_is_eq (scm_sym_copy
, key
))
370 SETSRCPROPCOPY (p
, datum
);
372 SCM_WHASHSET (scm_source_whash
, h
, scm_make_srcprops (0, 0, SCM_UNDEFINED
, datum
, p
));
377 SETSRCPROPALIST (p
, scm_acons (key
, datum
, SRCPROPALIST (p
)));
379 SCM_WHASHSET (scm_source_whash
, h
, scm_acons (key
, datum
, p
));
381 return SCM_UNSPECIFIED
;
389 scm_tc16_srcprops
= scm_make_smob_type ("srcprops", 0);
390 scm_set_smob_print (scm_tc16_srcprops
, srcprops_print
);
392 scm_source_whash
= scm_make_weak_key_hash_table (scm_from_int (2047));
393 scm_c_define ("source-whash", scm_source_whash
);
395 scm_last_alist_filename
396 = scm_permanent_object (scm_cons (SCM_EOL
,
397 scm_acons (SCM_EOL
, SCM_EOL
, SCM_EOL
)));
399 #include "libguile/srcprop.x"