+Protected_scm grob_property_callback_stack = SCM_EOL;
+bool debug_property_callbacks = 0;
+#endif
+
+SCM
+Grob::try_callback (SCM sym, SCM proc)
+{
+ SCM marker = ly_symbol2scm ("calculation-in-progress");
+ /*
+ need to put a value in SYM to ensure that we don't get a
+ cyclic call chain.
+ */
+ mutable_property_alist_
+ = scm_assq_set_x (mutable_property_alist_, sym, marker);
+
+#ifndef NDEBUG
+ if (debug_property_callbacks)
+ grob_property_callback_stack = scm_acons (sym, proc, grob_property_callback_stack);
+#endif
+
+ SCM value = SCM_EOL;
+ if (ly_is_procedure (proc))
+ value = scm_call_1 (proc, self_scm ());
+ else if (is_simple_closure (proc))
+ {
+ value = evaluate_with_simple_closure (self_scm (),
+ simple_closure_expression (proc),
+ false, 0, 0);
+ }
+#ifndef NDEBUG
+ if (debug_property_callbacks)
+ grob_property_callback_stack = scm_cdr (grob_property_callback_stack);
+#endif
+
+ /*
+ If the function returns SCM_UNSPECIFIED, we assume the
+ property has been set with an explicit set_property()
+ call.
+ */
+ if (value == SCM_UNSPECIFIED)
+ {
+ value = internal_get_property (sym);
+ if (value == marker)
+ mutable_property_alist_ = scm_assq_remove_x (mutable_property_alist_, marker);
+ }
+ else
+ set_property (sym, value);
+
+ return value;