+ again:
+
+
+ Score_element *sc = unsmob_element (src);
+ if (sc)
+ {
+ if (criterion == SCM_UNDEFINED)
+ return SCM_UNDEFINED;
+ else if (gh_number_p (criterion))
+ {
+ Item * i = dynamic_cast<Item*> (sc);
+ Direction d = to_dir (criterion);
+ if (i && i->break_status_dir () != d)
+ {
+ Item *br = i->find_broken_piece (d);
+ return (br) ? br->self_scm_ : SCM_UNDEFINED;
+ }
+ }
+ else
+ {
+ Score_element * ln = unsmob_element ( criterion);
+ Line_of_score * line = dynamic_cast<Line_of_score*> (ln);
+ Score_element * br =0;
+ Line_of_score * dep_line = sc->line_l ();
+ if (dep_line != line)
+ {
+ br = sc->find_broken_piece (line);
+ return (br) ? br->self_scm_ : SCM_UNDEFINED;
+ }
+ if (!dep_line)
+ return SCM_UNDEFINED;
+ }
+ }
+ else if (gh_pair_p (src))
+ {
+ /*
+ UGH! breaks on circular lists.
+ */
+ SCM car = handle_broken_smobs (gh_car (src), criterion);
+ SCM cdr = gh_cdr (src);
+
+ if (car == SCM_UNDEFINED
+ && (gh_pair_p (cdr) || cdr == SCM_EOL))
+ {
+ /*
+ This is tail-recursion, ie.
+
+ return handle_broken_smobs (cdr, criterion);
+
+ We don't want to rely on the compiler to do this. */
+ src = cdr;
+ goto again;
+ }
+
+ return gh_cons (car, handle_broken_smobs (cdr, criterion));
+ }
+ else
+ return src;
+
+ return src;