X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Ftext-interface.cc;h=47171b0949c2fbc5ccd9ac35f92c426edb8e6af0;hb=eab0f50d56e9d2b622a5024bb30c706c92860ef3;hp=53d5af4232165e94920b506d092c9fbe6f933375;hpb=28d8d9ac38857927790af5759c393adeff1ceb82;p=lilypond.git diff --git a/lily/text-interface.cc b/lily/text-interface.cc index 53d5af4232..47171b0949 100644 --- a/lily/text-interface.cc +++ b/lily/text-interface.cc @@ -28,6 +28,8 @@ #include "modified-font-metric.hh" #include "output-def.hh" #include "pango-font.hh" +#include "program-option.hh" +#include "international.hh" #include "warn.hh" static void @@ -36,27 +38,23 @@ replace_special_characters (string *str, SCM props) vsize i = 0; SCM replacement_alist = ly_chain_assoc_get (ly_symbol2scm ("replacement-alist"), props, - SCM_BOOL_F); - - if (!to_boolean (scm_list_p (replacement_alist)) - || to_boolean (scm_null_p (replacement_alist))) - return; + SCM_EOL); int max_length = 0; for (SCM s = replacement_alist; scm_is_pair (s); s = scm_cdr (s)) { max_length = max (max_length, scm_to_int - (scm_string_length (scm_caar (s)))); + (scm_string_length (scm_caar (s)))); } while (i <= str->size ()) { - for (int j = max_length; j > 0; j--) + for (vsize j = max_length + 1; j--;) { string dummy = str->substr (i, j); string ligature = robust_scm2string - (ly_assoc_get (ly_string2scm (dummy), - replacement_alist, SCM_BOOL_F), ""); + (ly_assoc_get (ly_string2scm (dummy), + replacement_alist, SCM_BOOL_F), ""); if (ligature != "") str->replace (i, j, ligature); } @@ -114,7 +112,40 @@ Text_interface::interpret_markup (SCM layout_smob, SCM props, SCM markup) if (!is_markup (markup)) programming_error ("markup head has no markup signature"); - return scm_apply_2 (func, layout_smob, props, args); + /* Use a hare/tortoise algorithm to detect whether we are in a cycle, + * i.e. whether we have already encountered the same markup in the + * current branch of the markup tree structure. */ + static vector encountered_markups; + size_t depth = encountered_markups.size (); + if (depth > 0) + { + int slow = depth / 2; + if (ly_is_equal (encountered_markups[slow], markup)) + { + string name = ly_symbol2string (scm_procedure_name (func)); + // TODO: Also print the arguments of the markup! + non_fatal_error (_f ("Cyclic markup detected: %s", name)); + return Stencil ().smobbed_copy (); + } + } + + /* Check for non-terminating markups, e.g. recursive calls with + * changing arguments */ + SCM opt_depth = ly_get_option (ly_symbol2scm ("max-markup-depth")); + size_t max_depth = robust_scm2int (opt_depth, 1024); + if (depth > max_depth) + { + string name = ly_symbol2string (scm_procedure_name (func)); + // TODO: Also print the arguments of the markup! + non_fatal_error (_f ("Markup depth exceeds maximal value of %d; " + "Markup: %s", max_depth, name.c_str ())); + return Stencil ().smobbed_copy (); + } + + encountered_markups.push_back (markup); + SCM retval = scm_apply_2 (func, layout_smob, props, args); + encountered_markups.pop_back (); + return retval; } else { @@ -123,12 +154,7 @@ Text_interface::interpret_markup (SCM layout_smob, SCM props, SCM markup) scm_display (markup, scm_current_error_port ()); scm_puts ("\n", scm_current_error_port ()); - Box b; - b[X_AXIS].set_empty (); - b[Y_AXIS].set_empty (); - - Stencil s (b, SCM_EOL); - return s.smobbed_copy (); + return Stencil ().smobbed_copy (); } }