]> git.donarmstrong.com Git - lilypond.git/blob - guile18/libguile/srcprop.c
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / libguile / srcprop.c
1 /* Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002, 2006, 2008 Free Software Foundation
2  * 
3  * This library is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 2.1 of the License, or (at your option) any later version.
7  *
8  * This library is distributed in the hope that it will be useful,
9  * but 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.
12  *
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 02110-1301 USA
16  */
17
18
19 \f
20 #ifdef HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include <errno.h>
25
26 #include "libguile/_scm.h"
27 #include "libguile/async.h"
28 #include "libguile/smob.h"
29 #include "libguile/alist.h"
30 #include "libguile/debug.h"
31 #include "libguile/hashtab.h"
32 #include "libguile/hash.h"
33 #include "libguile/ports.h"
34 #include "libguile/root.h"
35 #include "libguile/weaks.h"
36
37 #include "libguile/validate.h"
38 #include "libguile/srcprop.h"
39 \f
40 /* {Source Properties}
41  *
42  * Properties of source list expressions.
43  * Five of these have special meaning:
44  *
45  * filename    string   The name of the source file.
46  * copy        list     A copy of the list expression.
47  * line        integer  The source code line number.
48  * column      integer  The source code column number.
49  * breakpoint  boolean  Sets a breakpoint on this form.
50  *
51  * Most properties above can be set by the reader.
52  *
53  */
54
55 SCM_GLOBAL_SYMBOL (scm_sym_filename, "filename");
56 SCM_GLOBAL_SYMBOL (scm_sym_copy, "copy");
57 SCM_GLOBAL_SYMBOL (scm_sym_line, "line");
58 SCM_GLOBAL_SYMBOL (scm_sym_column, "column");
59 SCM_GLOBAL_SYMBOL (scm_sym_breakpoint, "breakpoint");
60
61
62
63 /*
64  *  Source properties are stored as double cells with the
65  *  following layout:
66   
67  * car = tag
68  * cbr = pos
69  * ccr = copy
70  * cdr = plist 
71  */
72
73 #define SRCPROPSP(p) (SCM_SMOB_PREDICATE (scm_tc16_srcprops, (p)))
74 #define SRCPROPBRK(p) (SCM_SMOB_FLAGS (p) & SCM_SOURCE_PROPERTY_FLAG_BREAK)
75 #define SRCPROPPOS(p) (SCM_CELL_WORD(p,1))
76 #define SRCPROPLINE(p) (SRCPROPPOS(p) >> 12)
77 #define SRCPROPCOL(p) (SRCPROPPOS(p) & 0x0fffL)
78 #define SRCPROPCOPY(p) (SCM_CELL_OBJECT(p,2))
79 #define SRCPROPPLIST(p) (SCM_CELL_OBJECT_3(p))
80 #define SETSRCPROPBRK(p) \
81  (SCM_SET_SMOB_FLAGS ((p), \
82                       SCM_SMOB_FLAGS (p) | SCM_SOURCE_PROPERTY_FLAG_BREAK))
83 #define CLEARSRCPROPBRK(p)  \
84  (SCM_SET_SMOB_FLAGS ((p), \
85                       SCM_SMOB_FLAGS (p) & ~SCM_SOURCE_PROPERTY_FLAG_BREAK))
86 #define SRCPROPMAKPOS(l, c) (((l) << 12) + (c))
87 #define SETSRCPROPPOS(p, l, c) (SCM_SET_CELL_WORD(p,1, SRCPROPMAKPOS (l, c)))
88 #define SETSRCPROPLINE(p, l) SETSRCPROPPOS (p, l, SRCPROPCOL (p))
89 #define SETSRCPROPCOL(p, c) SETSRCPROPPOS (p, SRCPROPLINE (p), c)
90
91
92
93 scm_t_bits scm_tc16_srcprops;
94
95 static SCM
96 srcprops_mark (SCM obj)
97 {
98   scm_gc_mark (SRCPROPCOPY (obj));
99   return SRCPROPPLIST (obj);
100 }
101
102 static int
103 srcprops_print (SCM obj, SCM port, scm_print_state *pstate)
104 {
105   int writingp = SCM_WRITINGP (pstate);
106   scm_puts ("#<srcprops ", port);
107   SCM_SET_WRITINGP (pstate, 1);
108   scm_iprin1 (scm_srcprops_to_plist (obj), port, pstate);
109   SCM_SET_WRITINGP (pstate, writingp);
110   scm_putc ('>', port);
111   return 1;
112 }
113
114
115 int
116 scm_c_source_property_breakpoint_p (SCM form)
117 {
118   SCM obj = scm_whash_lookup (scm_source_whash, form);
119   return SRCPROPSP (obj) && SRCPROPBRK (obj);
120 }
121
122
123 /*
124  * We remember the last file name settings, so we can share that plist
125  * entry.  This works because scm_set_source_property_x does not use
126  * assoc-set! for modifying the plist.
127  *
128  * This variable contains a protected cons, whose cdr is the cached
129  * plist
130  */
131 static SCM scm_last_plist_filename;
132
133 SCM
134 scm_make_srcprops (long line, int col, SCM filename, SCM copy, SCM plist)
135 {
136   if (!SCM_UNBNDP (filename))
137     {
138       SCM old_plist = plist;
139
140       /*
141         have to extract the acons, and operate on that, for
142         thread safety.
143        */
144       SCM last_acons = SCM_CDR (scm_last_plist_filename);
145       if (old_plist == SCM_EOL
146           && SCM_CDAR (last_acons) == filename)
147         {
148           plist = last_acons;
149         }
150       else
151         {
152           plist = scm_acons (scm_sym_filename, filename, plist);
153           if (old_plist == SCM_EOL)
154             SCM_SETCDR (scm_last_plist_filename, plist);
155         }
156     }
157   
158   SCM_RETURN_NEWSMOB3 (scm_tc16_srcprops,
159                        SRCPROPMAKPOS (line, col),
160                        copy,
161                        plist);
162 }
163
164
165 SCM
166 scm_srcprops_to_plist (SCM obj)
167 {
168   SCM plist = SRCPROPPLIST (obj);
169   if (!SCM_UNBNDP (SRCPROPCOPY (obj)))
170     plist = scm_acons (scm_sym_copy, SRCPROPCOPY (obj), plist);
171   plist = scm_acons (scm_sym_column, scm_from_int (SRCPROPCOL (obj)), plist);
172   plist = scm_acons (scm_sym_line, scm_from_int (SRCPROPLINE (obj)), plist);
173   plist = scm_acons (scm_sym_breakpoint, scm_from_bool (SRCPROPBRK (obj)), plist);
174   return plist;
175 }
176
177 SCM_DEFINE (scm_source_properties, "source-properties", 1, 0, 0, 
178             (SCM obj),
179             "Return the source property association list of @var{obj}.")
180 #define FUNC_NAME s_scm_source_properties
181 {
182   SCM p;
183   SCM_VALIDATE_NIM (1, obj);
184   if (SCM_MEMOIZEDP (obj))
185     obj = SCM_MEMOIZED_EXP (obj);
186   else if (!scm_is_pair (obj))
187     SCM_WRONG_TYPE_ARG (1, obj);
188   p = scm_hashq_ref (scm_source_whash, obj, SCM_EOL);
189   if (SRCPROPSP (p))
190     return scm_srcprops_to_plist (p);
191   else
192     /* list from set-source-properties!, or SCM_EOL for not found */
193     return p;
194 }
195 #undef FUNC_NAME
196
197 /* Perhaps this procedure should look through an alist
198    and try to make a srcprops-object...? */
199 SCM_DEFINE (scm_set_source_properties_x, "set-source-properties!", 2, 0, 0,
200             (SCM obj, SCM plist),
201             "Install the association list @var{plist} as the source property\n"
202             "list for @var{obj}.")
203 #define FUNC_NAME s_scm_set_source_properties_x
204 {
205   SCM handle;
206   SCM_VALIDATE_NIM (1, obj);
207   if (SCM_MEMOIZEDP (obj))
208     obj = SCM_MEMOIZED_EXP (obj);
209   else if (!scm_is_pair (obj))
210     SCM_WRONG_TYPE_ARG(1, obj);
211   handle = scm_hashq_create_handle_x (scm_source_whash, obj, plist);
212   SCM_SETCDR (handle, plist);
213   return plist;
214 }
215 #undef FUNC_NAME
216
217 SCM_DEFINE (scm_source_property, "source-property", 2, 0, 0,
218             (SCM obj, SCM key),
219             "Return the source property specified by @var{key} from\n"
220             "@var{obj}'s source property list.")
221 #define FUNC_NAME s_scm_source_property
222 {
223   SCM p;
224   SCM_VALIDATE_NIM (1, obj);
225   if (SCM_MEMOIZEDP (obj))
226     obj = SCM_MEMOIZED_EXP (obj);
227   else if (!scm_is_pair (obj))
228     SCM_WRONG_TYPE_ARG (1, obj);
229   p = scm_hashq_ref (scm_source_whash, obj, SCM_EOL);
230   if (!SRCPROPSP (p))
231     goto plist;
232   if      (scm_is_eq (scm_sym_breakpoint, key)) p = scm_from_bool (SRCPROPBRK (p));
233   else if (scm_is_eq (scm_sym_line,       key)) p = scm_from_int (SRCPROPLINE (p));
234   else if (scm_is_eq (scm_sym_column,     key)) p = scm_from_int (SRCPROPCOL (p));
235   else if (scm_is_eq (scm_sym_copy,       key)) p = SRCPROPCOPY (p);
236   else
237     {
238       p = SRCPROPPLIST (p);
239     plist:
240       p = scm_assoc (key, p);
241       return (SCM_NIMP (p) ? SCM_CDR (p) : SCM_BOOL_F);
242     }
243   return SCM_UNBNDP (p) ? SCM_BOOL_F : p;
244 }
245 #undef FUNC_NAME
246
247 SCM_DEFINE (scm_set_source_property_x, "set-source-property!", 3, 0, 0,
248             (SCM obj, SCM key, SCM datum),
249             "Set the source property of object @var{obj}, which is specified by\n"
250             "@var{key} to @var{datum}.  Normally, the key will be a symbol.")
251 #define FUNC_NAME s_scm_set_source_property_x
252 {
253   scm_whash_handle h;
254   SCM p;
255   SCM_VALIDATE_NIM (1, obj);
256   if (SCM_MEMOIZEDP (obj))
257     obj = SCM_MEMOIZED_EXP (obj);
258   else if (!scm_is_pair (obj))
259     SCM_WRONG_TYPE_ARG (1, obj);
260   h = scm_whash_get_handle (scm_source_whash, obj);
261   if (SCM_WHASHFOUNDP (h))
262     p = SCM_WHASHREF (scm_source_whash, h);
263   else
264     {
265       h = scm_whash_create_handle (scm_source_whash, obj);
266       p = SCM_EOL;
267     }
268   if (scm_is_eq (scm_sym_breakpoint, key))
269     {
270       if (SRCPROPSP (p))
271         {
272           if (scm_is_false (datum))
273             CLEARSRCPROPBRK (p);
274           else
275             SETSRCPROPBRK (p);
276         }
277       else
278         {
279           SCM sp = scm_make_srcprops (0, 0, SCM_UNDEFINED, SCM_UNDEFINED, p);
280           SCM_WHASHSET (scm_source_whash, h, sp);
281           if (scm_is_false (datum))
282             CLEARSRCPROPBRK (sp);
283           else
284             SETSRCPROPBRK (sp);
285         }
286     }
287   else if (scm_is_eq (scm_sym_line, key))
288     {
289       if (SRCPROPSP (p))
290         SETSRCPROPLINE (p, scm_to_int (datum));
291       else
292         SCM_WHASHSET (scm_source_whash, h,
293                       scm_make_srcprops (scm_to_int (datum), 0,
294                                          SCM_UNDEFINED, SCM_UNDEFINED, p));
295     }
296   else if (scm_is_eq (scm_sym_column, key))
297     {
298       if (SRCPROPSP (p))
299         SETSRCPROPCOL (p, scm_to_int (datum));
300       else
301         SCM_WHASHSET (scm_source_whash, h,
302                       scm_make_srcprops (0, scm_to_int (datum),
303                                          SCM_UNDEFINED, SCM_UNDEFINED, p));
304     }
305   else if (scm_is_eq (scm_sym_copy, key))
306     {
307       if (SRCPROPSP (p))
308         SRCPROPCOPY (p) = datum;
309       else
310         SCM_WHASHSET (scm_source_whash, h, scm_make_srcprops (0, 0, SCM_UNDEFINED, datum, p));
311     }
312   else
313     {
314       if (SRCPROPSP (p))
315         SRCPROPPLIST (p) = scm_acons (key, datum, SRCPROPPLIST (p));
316       else
317         SCM_WHASHSET (scm_source_whash, h, scm_acons (key, datum, p));
318     }
319   return SCM_UNSPECIFIED;
320 }
321 #undef FUNC_NAME
322
323
324 void
325 scm_init_srcprop ()
326 {
327   scm_tc16_srcprops = scm_make_smob_type ("srcprops", 0);
328   scm_set_smob_mark (scm_tc16_srcprops, srcprops_mark);
329   scm_set_smob_print (scm_tc16_srcprops, srcprops_print);
330
331   scm_source_whash = scm_make_weak_key_hash_table (scm_from_int (2047));
332   scm_c_define ("source-whash", scm_source_whash);
333
334   scm_last_plist_filename
335     = scm_permanent_object (scm_cons (SCM_EOL,
336                                       scm_acons (SCM_EOL, SCM_EOL, SCM_EOL)));
337
338 #include "libguile/srcprop.x"
339 }
340
341
342 /*
343   Local Variables:
344   c-file-style: "gnu"
345   End:
346 */