+#ifndef NDEBUG
+ if (debug_property_callbacks)
+ grob_property_callback_stack = scm_cons (scm_list_3 (self_scm (), 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 = get_property_data (sym);
+ assert (value == SCM_EOL || value == marker);
+ if (value == marker)
+ *alist = scm_assq_remove_x (*alist, marker);
+ }
+ else
+ {
+#ifndef NDEBUG
+ if (ly_is_procedure (cache_callback))
+ scm_apply_0 (cache_callback,
+ scm_list_n (self_scm (),
+ sym,
+ proc,
+ value,
+ SCM_UNDEFINED));
+#endif
+ internal_set_value_on_alist (alist, sym, value);
+ }
+
+ return value;
+}