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"
38 #include "libguile/validate.h"
39 #include "libguile/srcprop.h"
41 /* {Source Properties}
43 * Properties of source list expressions.
44 * Five of these have special meaning:
46 * filename string The name of the source file.
47 * copy list A copy of the list expression.
48 * line integer The source code line number.
49 * column integer The source code column number.
50 * breakpoint boolean Sets a breakpoint on this form.
52 * Most properties above can be set by the reader.
56 SCM_GLOBAL_SYMBOL (scm_sym_filename
, "filename");
57 SCM_GLOBAL_SYMBOL (scm_sym_copy
, "copy");
58 SCM_GLOBAL_SYMBOL (scm_sym_line
, "line");
59 SCM_GLOBAL_SYMBOL (scm_sym_column
, "column");
60 SCM_GLOBAL_SYMBOL (scm_sym_breakpoint
, "breakpoint");
65 * Source properties are stored as double cells with the
74 #define SRCPROPSP(p) (SCM_SMOB_PREDICATE (scm_tc16_srcprops, (p)))
75 #define SRCPROPBRK(p) (SCM_SMOB_FLAGS (p) & SCM_SOURCE_PROPERTY_FLAG_BREAK)
76 #define SRCPROPPOS(p) (SCM_CELL_WORD(p,1))
77 #define SRCPROPLINE(p) (SRCPROPPOS(p) >> 12)
78 #define SRCPROPCOL(p) (SRCPROPPOS(p) & 0x0fffL)
79 #define SRCPROPCOPY(p) (SCM_CELL_OBJECT(p,2))
80 #define SRCPROPALIST(p) (SCM_CELL_OBJECT_3(p))
81 #define SETSRCPROPBRK(p) \
82 (SCM_SET_SMOB_FLAGS ((p), \
83 SCM_SMOB_FLAGS (p) | SCM_SOURCE_PROPERTY_FLAG_BREAK))
84 #define CLEARSRCPROPBRK(p) \
85 (SCM_SET_SMOB_FLAGS ((p), \
86 SCM_SMOB_FLAGS (p) & ~SCM_SOURCE_PROPERTY_FLAG_BREAK))
87 #define SRCPROPMAKPOS(l, c) (((l) << 12) + (c))
88 #define SETSRCPROPPOS(p, l, c) (SCM_SET_CELL_WORD(p,1, SRCPROPMAKPOS (l, c)))
89 #define SETSRCPROPLINE(p, l) SETSRCPROPPOS (p, l, SRCPROPCOL (p))
90 #define SETSRCPROPCOL(p, c) SETSRCPROPPOS (p, SRCPROPLINE (p), c)
91 #define SETSRCPROPCOPY(p, c) (SCM_SET_CELL_WORD(p, 2, c))
92 #define SETSRCPROPALIST(p, l) (SCM_SET_CELL_WORD(p, 3, l))
95 static SCM
scm_srcprops_to_alist (SCM obj
);
98 scm_t_bits scm_tc16_srcprops
;
101 srcprops_mark (SCM obj
)
103 scm_gc_mark (SRCPROPCOPY (obj
));
104 return SRCPROPALIST (obj
);
108 srcprops_print (SCM obj
, SCM port
, scm_print_state
*pstate
)
110 int writingp
= SCM_WRITINGP (pstate
);
111 scm_puts ("#<srcprops ", port
);
112 SCM_SET_WRITINGP (pstate
, 1);
113 scm_iprin1 (scm_srcprops_to_alist (obj
), port
, pstate
);
114 SCM_SET_WRITINGP (pstate
, writingp
);
115 scm_putc ('>', port
);
121 scm_c_source_property_breakpoint_p (SCM form
)
123 SCM obj
= scm_whash_lookup (scm_source_whash
, form
);
124 return SRCPROPSP (obj
) && SRCPROPBRK (obj
);
129 * We remember the last file name settings, so we can share that alist
130 * entry. This works because scm_set_source_property_x does not use
131 * assoc-set! for modifying the alist.
133 * This variable contains a protected cons, whose cdr is the cached
136 static SCM scm_last_alist_filename
;
139 scm_make_srcprops (long line
, int col
, SCM filename
, SCM copy
, SCM alist
)
141 if (!SCM_UNBNDP (filename
))
143 SCM old_alist
= alist
;
146 have to extract the acons, and operate on that, for
149 SCM last_acons
= SCM_CDR (scm_last_alist_filename
);
150 if (old_alist
== SCM_EOL
151 && SCM_CDAR (last_acons
) == filename
)
157 alist
= scm_acons (scm_sym_filename
, filename
, alist
);
158 if (old_alist
== SCM_EOL
)
159 SCM_SETCDR (scm_last_alist_filename
, alist
);
163 SCM_RETURN_NEWSMOB3 (scm_tc16_srcprops
,
164 SRCPROPMAKPOS (line
, col
),
171 scm_srcprops_to_alist (SCM obj
)
173 SCM alist
= SRCPROPALIST (obj
);
174 if (!SCM_UNBNDP (SRCPROPCOPY (obj
)))
175 alist
= scm_acons (scm_sym_copy
, SRCPROPCOPY (obj
), alist
);
176 alist
= scm_acons (scm_sym_column
, scm_from_int (SRCPROPCOL (obj
)), alist
);
177 alist
= scm_acons (scm_sym_line
, scm_from_int (SRCPROPLINE (obj
)), alist
);
178 alist
= scm_acons (scm_sym_breakpoint
, scm_from_bool (SRCPROPBRK (obj
)), alist
);
182 SCM_DEFINE (scm_source_properties
, "source-properties", 1, 0, 0,
184 "Return the source property association list of @var{obj}.")
185 #define FUNC_NAME s_scm_source_properties
188 SCM_VALIDATE_NIM (1, obj
);
189 if (SCM_MEMOIZEDP (obj
))
190 obj
= SCM_MEMOIZED_EXP (obj
);
191 else if (!scm_is_pair (obj
))
192 SCM_WRONG_TYPE_ARG (1, obj
);
193 p
= scm_hashq_ref (scm_source_whash
, obj
, SCM_EOL
);
195 return scm_srcprops_to_alist (p
);
197 /* list from set-source-properties!, or SCM_EOL for not found */
202 /* Perhaps this procedure should look through an alist
203 and try to make a srcprops-object...? */
204 SCM_DEFINE (scm_set_source_properties_x
, "set-source-properties!", 2, 0, 0,
205 (SCM obj
, SCM alist
),
206 "Install the association list @var{alist} as the source property\n"
207 "list for @var{obj}.")
208 #define FUNC_NAME s_scm_set_source_properties_x
211 long line
= 0, col
= 0;
212 SCM fname
= SCM_UNDEFINED
, copy
= SCM_UNDEFINED
, breakpoint
= SCM_BOOL_F
;
213 SCM others
= SCM_EOL
;
214 SCM
*others_cdrloc
= &others
;
215 int need_srcprops
= 0;
218 SCM_VALIDATE_NIM (1, obj
);
219 if (SCM_MEMOIZEDP (obj
))
220 obj
= SCM_MEMOIZED_EXP (obj
);
221 else if (!scm_is_pair (obj
))
222 SCM_WRONG_TYPE_ARG(1, obj
);
225 while (!scm_is_null (tail
))
227 key
= SCM_CAAR (tail
);
228 if (scm_is_eq (key
, scm_sym_line
))
230 line
= scm_to_long (SCM_CDAR (tail
));
233 else if (scm_is_eq (key
, scm_sym_column
))
235 col
= scm_to_long (SCM_CDAR (tail
));
238 else if (scm_is_eq (key
, scm_sym_filename
))
240 fname
= SCM_CDAR (tail
);
243 else if (scm_is_eq (key
, scm_sym_copy
))
245 copy
= SCM_CDAR (tail
);
248 else if (scm_is_eq (key
, scm_sym_breakpoint
))
250 breakpoint
= SCM_CDAR (tail
);
255 /* Do we allocate here, or clobber the caller's alist?
257 Source properties aren't supposed to be used for anything
258 except the special properties above, so the mainline case
259 is that we never execute this else branch, and hence it
262 We choose allocation here, as that seems safer.
264 *others_cdrloc
= scm_cons (scm_cons (key
, SCM_CDAR (tail
)),
266 others_cdrloc
= SCM_CDRLOC (*others_cdrloc
);
268 tail
= SCM_CDR (tail
);
272 alist
= scm_make_srcprops (line
, col
, fname
, copy
, others
);
273 if (scm_is_true (breakpoint
))
274 SETSRCPROPBRK (alist
);
279 handle
= scm_hashq_create_handle_x (scm_source_whash
, obj
, alist
);
280 SCM_SETCDR (handle
, alist
);
285 SCM_DEFINE (scm_source_property
, "source-property", 2, 0, 0,
287 "Return the source property specified by @var{key} from\n"
288 "@var{obj}'s source property list.")
289 #define FUNC_NAME s_scm_source_property
292 SCM_VALIDATE_NIM (1, obj
);
293 if (SCM_MEMOIZEDP (obj
))
294 obj
= SCM_MEMOIZED_EXP (obj
);
295 else if (!scm_is_pair (obj
))
296 SCM_WRONG_TYPE_ARG (1, obj
);
297 p
= scm_hashq_ref (scm_source_whash
, obj
, SCM_EOL
);
300 if (scm_is_eq (scm_sym_breakpoint
, key
)) p
= scm_from_bool (SRCPROPBRK (p
));
301 else if (scm_is_eq (scm_sym_line
, key
)) p
= scm_from_int (SRCPROPLINE (p
));
302 else if (scm_is_eq (scm_sym_column
, key
)) p
= scm_from_int (SRCPROPCOL (p
));
303 else if (scm_is_eq (scm_sym_copy
, key
)) p
= SRCPROPCOPY (p
);
306 p
= SRCPROPALIST (p
);
308 p
= scm_assoc (key
, p
);
309 return (SCM_NIMP (p
) ? SCM_CDR (p
) : SCM_BOOL_F
);
311 return SCM_UNBNDP (p
) ? SCM_BOOL_F
: p
;
315 SCM_DEFINE (scm_set_source_property_x
, "set-source-property!", 3, 0, 0,
316 (SCM obj
, SCM key
, SCM datum
),
317 "Set the source property of object @var{obj}, which is specified by\n"
318 "@var{key} to @var{datum}. Normally, the key will be a symbol.")
319 #define FUNC_NAME s_scm_set_source_property_x
323 SCM_VALIDATE_NIM (1, obj
);
324 if (SCM_MEMOIZEDP (obj
))
325 obj
= SCM_MEMOIZED_EXP (obj
);
326 else if (!scm_is_pair (obj
))
327 SCM_WRONG_TYPE_ARG (1, obj
);
328 h
= scm_whash_get_handle (scm_source_whash
, obj
);
329 if (SCM_WHASHFOUNDP (h
))
330 p
= SCM_WHASHREF (scm_source_whash
, h
);
333 h
= scm_whash_create_handle (scm_source_whash
, obj
);
336 if (scm_is_eq (scm_sym_breakpoint
, key
))
340 if (scm_is_false (datum
))
347 SCM sp
= scm_make_srcprops (0, 0, SCM_UNDEFINED
, SCM_UNDEFINED
, p
);
348 SCM_WHASHSET (scm_source_whash
, h
, sp
);
349 if (scm_is_false (datum
))
350 CLEARSRCPROPBRK (sp
);
355 else if (scm_is_eq (scm_sym_line
, key
))
358 SETSRCPROPLINE (p
, scm_to_int (datum
));
360 SCM_WHASHSET (scm_source_whash
, h
,
361 scm_make_srcprops (scm_to_int (datum
), 0,
362 SCM_UNDEFINED
, SCM_UNDEFINED
, p
));
364 else if (scm_is_eq (scm_sym_column
, key
))
367 SETSRCPROPCOL (p
, scm_to_int (datum
));
369 SCM_WHASHSET (scm_source_whash
, h
,
370 scm_make_srcprops (0, scm_to_int (datum
),
371 SCM_UNDEFINED
, SCM_UNDEFINED
, p
));
373 else if (scm_is_eq (scm_sym_copy
, key
))
376 SETSRCPROPCOPY (p
, datum
);
378 SCM_WHASHSET (scm_source_whash
, h
, scm_make_srcprops (0, 0, SCM_UNDEFINED
, datum
, p
));
383 SETSRCPROPALIST (p
, scm_acons (key
, datum
, SRCPROPALIST (p
)));
385 SCM_WHASHSET (scm_source_whash
, h
, scm_acons (key
, datum
, p
));
387 return SCM_UNSPECIFIED
;
395 scm_tc16_srcprops
= scm_make_smob_type ("srcprops", 0);
396 scm_set_smob_mark (scm_tc16_srcprops
, srcprops_mark
);
397 scm_set_smob_print (scm_tc16_srcprops
, srcprops_print
);
399 scm_source_whash
= scm_make_weak_key_hash_table (scm_from_int (2047));
400 scm_c_define ("source-whash", scm_source_whash
);
402 scm_last_alist_filename
403 = scm_permanent_object (scm_cons (SCM_EOL
,
404 scm_acons (SCM_EOL
, SCM_EOL
, SCM_EOL
)));
406 #include "libguile/srcprop.x"