2 lily-guile.cc -- implement assorted guile functions
4 source file of the GNU LilyPond music typesetter
6 (c) 1998--1999 Jan Nieuwenhuizen <janneke@gnu.org>
8 Han-Wen Nienhuys <hanwen@cs.uu.nl>
12 #include "libc-extension.hh"
13 #include "lily-guile.hh"
15 #include "simple-file-storage.hh"
16 #include "file-path.hh"
21 scm_m_quote doesn't use any env, but needs one for a good signature in GUILE.
23 Why there is no gh_quote () in GUILE beats me.
29 return scm_cons2 (scm_i_quote, s, SCM_EOL);
33 See: libguile/symbols.c
36 scm_string_to_symbol(s)
40 ly_symbol (String name)
42 return gh_car (scm_intern (name.ch_C(), name.length_i()));
46 symbol_to_string (SCM s)
48 return String((Byte*)SCM_CHARS (s), (int) SCM_LENGTH(s));
52 ly_set_scm (String name, SCM val)
54 return scm_sysintern (name.ch_C(), val);
59 Read a file, and shove it down GUILE. GUILE also has file read
60 functions, but you can't fiddle with the path of those.
64 read_lily_scm_file (String fn)
66 String s = global_path.find (fn);
69 String e = _f ("Can not find file `%s\'", fn);
71 e += _f ("(Load path is `%s\'", global_path.str ());
78 Simple_file_storage f(s);
80 gh_eval_str ((char *) f.ch_C());
81 *mlog << ']' << flush;
86 ly_display_scm (SCM s)
96 char * p = gh_scm2newstr (s , &len);
106 (key . (left_child . right_child))
108 SCM_EOL is the nil-pointer (should use SCM_NIMP() ?)
111 #define left_child(s) SCM_CADR((s))
112 #define right_child(s) SCM_CDDR((s))
113 #define key(s) SCM_CAR((s))
116 Garble pointers, to prevent unbalanced tree due to ordered inserts.
122 const int SHIFT = 18;
123 return (unsigned int)(s << (32-SHIFT) | s >> SHIFT );
127 ly_new_bintree_node (SCM val)
129 return gh_cons (val, gh_cons (SCM_EOL, SCM_EOL));
134 add VAL to TREE. TREE must be non-nil
137 ly_addto_bintree (SCM *tree, SCM val)
139 while(*tree != SCM_EOL)
141 if (munge (val) <= munge (key (*tree)))
142 tree = &left_child (*tree);
144 tree = &right_child (*tree);
147 *tree = ly_new_bintree_node (val);
152 find the address of a node in the tree represented by *NODE with key VAL
155 ly_find_in_bintree (SCM *node, SCM val)
157 while (*node != SCM_EOL)
159 if (munge (val) < munge (key(*node) ))
160 node = &left_child(*node);
161 else if (munge (val) > munge (key (*node)))
162 node = &right_child (*node);
170 ly_remove_from_bintree (SCM *node)
172 SCM r = right_child (*node);
173 SCM l = left_child (*node);
179 else if (l == SCM_EOL)
185 /*deleting from binary trees. See Knuth's TAOCP.
188 SCM *left_t = &left_child (*t);
191 INV: LEFT_T is the left child of T
193 while (*left_t != SCM_EOL)
196 left_t = &left_child (*t);
200 POST: T is the leftmost right child of NODE which has no left child,
202 leftchild (LASTT) == T
204 key(*node) = key(*t);
205 *left_t = right_child (*t);
210 static SCM protect_tree_root;
213 ly_protect_scm (SCM s)
215 ly_addto_bintree (&protect_tree_root, s);
220 ly_unprotect_scm (SCM s)
222 SCM *to_remove = ly_find_in_bintree (&protect_tree_root, s);
225 this shouldn't happen, according to me. But it does.
227 if (*to_remove != SCM_EOL)
228 ly_remove_from_bintree (to_remove);
233 ly_init_protection ()
235 protect_tree_root = scm_protect_object (ly_new_bintree_node(SCM_EOL));
236 key (protect_tree_root) = protect_tree_root;
241 ly_count_elements (SCM tree)
246 return 1 + ly_count_elements (left_child (tree)) + ly_count_elements (right_child( tree));
250 ly_tree_depth (SCM tree)
255 return 1 + (ly_tree_depth (left_child (tree)) >? ly_tree_depth (right_child(tree)));
259 ly_print_bintree (SCM node)
264 DOUT << "{val = " << key(node) << " \nleft = ";
265 ly_print_bintree (left_child (node));
266 DOUT << "\n right =";
267 ly_print_bintree (right_child (node));
273 struct Imbalance { int imbalance; int total; };
276 ly_calc_imbalance (SCM node)
286 Imbalance l = ly_calc_imbalance (left_child (node));
287 Imbalance r = ly_calc_imbalance (right_child (node));
289 t.total = l.total + r.total + 1;
290 int dif = l.total - r.total;
293 t.imbalance = l.imbalance + r.imbalance + dif;