+ return val;
+}
+
+/* Unlike internal_get_property, this function does no caching. Use it, therefore, with caution. */
+SCM
+Grob::internal_get_pure_property (SCM sym, int start, int end) const
+{
+ SCM val = internal_get_property_data (sym);
+ if (ly_is_procedure (val))
+ return call_pure_function (val, scm_list_1 (self_scm ()), start, end);
+
+ if (Unpure_pure_container *upc = unsmob<Unpure_pure_container> (val)) {
+ // Do cache, if the function ignores 'start' and 'end'
+ if (upc->is_unchanging ())
+ return internal_get_property (sym);
+ else
+ return call_pure_function (val, scm_list_1 (self_scm ()), start, end);
+ }
+
+ return val;
+}
+
+SCM
+Grob::internal_get_maybe_pure_property (SCM sym, bool pure, int start, int end) const
+{
+ return pure ? internal_get_pure_property (sym, start, end) : internal_get_property (sym);
+}
+
+SCM
+Grob::try_callback_on_alist (SCM *alist, 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.
+ */
+ *alist = scm_assq_set_x (*alist, sym, marker);
+
+#ifdef DEBUG
+ 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 ());
+
+#ifdef DEBUG
+ if (debug_property_callbacks)
+ grob_property_callback_stack = scm_cdr (grob_property_callback_stack);
+#endif
+
+ if (scm_is_eq (value, SCM_UNSPECIFIED))
+ {
+ value = get_property_data (sym);
+ assert (scm_is_null (value) || scm_is_eq (value, marker));
+ if (scm_is_eq (value, marker))
+ *alist = scm_assq_remove_x (*alist, sym);
+ }
+ else
+ {
+#ifdef DEBUG
+ if (ly_is_procedure (cache_callback))
+ scm_call_4 (cache_callback,
+ self_scm (),
+ sym,
+ proc,
+ value);
+#endif
+ internal_set_value_on_alist (alist, sym, value);
+ }
+
+ return value;
+}
+
+void
+Grob::internal_set_object (SCM s, SCM v)
+{
+ /* Perhaps we simply do the assq_set, but what the heck. */
+ if (!is_live ())
+ return;
+
+ object_alist_ = scm_assq_set_x (object_alist_, s, v);