]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
77d0f18b6ebe26e20fe1b90367f96a4a4f587bb0
[lilypond.git] / lily / translator-group.cc
1 /*
2   Translator_group.cc -- implement Translator_group
3
4   source file of the GNU LilyPond music typesetter
5
6   (c)  1997--1998 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8
9 #include "music-output-def.hh"
10 #include "translator-group.hh"
11 #include "translator.hh"
12 #include "debug.hh"
13 #include "pcursor.hh"
14 #include "rational.hh"
15
16 Translator_group::Translator_group (Translator_group const&s)
17   : Translator(s)
18 {
19   consists_str_arr_ = s.consists_str_arr_;
20   accepts_str_arr_ = s.accepts_str_arr_;
21   iterator_count_ =0;
22 }
23
24 Translator_group::~Translator_group ()
25 {
26   assert (removable_b());
27 }
28
29
30 Translator_group::Translator_group()
31 {
32   iterator_count_  = 0;
33 }
34
35 void
36 Translator_group::check_removal()
37 {
38   Link_array<Translator_group> groups (group_l_arr ());
39   
40   for (int i =0; i < groups.size(); i++)
41     {
42       groups[i]->check_removal();
43       if (groups[i]->removable_b())
44         terminate_translator (groups[i]);
45     }
46 }
47
48
49
50 IMPLEMENT_IS_TYPE_B1(Translator_group, Translator);
51
52 void
53 Translator_group::add_translator (Translator *trans_p)
54 {
55   trans_p_list_.bottom().add (trans_p);
56   trans_p->daddy_trans_l_ = this;
57   trans_p->output_def_l_ = output_def_l_;
58   trans_p->add_processing ();
59 }
60
61 void
62 Translator_group::set_acceptor (String accepts, bool add)
63 {
64   if (add)
65     accepts_str_arr_.push (accepts);
66   else
67     for (int i=accepts_str_arr_.size (); i--; )
68       if (accepts_str_arr_[i] == accepts)
69         accepts_str_arr_.del (i);
70 }
71
72 void
73 Translator_group::set_element (String s, bool add)
74 {
75   if (!get_translator_l (s))
76     error ("Program has no such type");
77
78   if (add)
79     consists_str_arr_.push (s);
80   else
81     for (int i=consists_str_arr_.size (); i--; )
82       if (consists_str_arr_[i] == s)
83         consists_str_arr_.del (i);
84 }
85
86 bool
87 Translator_group::removable_b() const
88 {
89   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
90     {
91       if (i->access_Translator_group ())
92         return false;
93     }
94
95   return !iterator_count_;
96 }
97
98 Translator_group *
99 Translator_group::find_existing_translator_l (String n, String id)
100 {
101   if (is_alias_b (n) && (id_str_ == id || id.empty_b ()))
102     return this;
103
104   Link_array<Translator_group> groups (group_l_arr ());
105   Translator_group* r = 0;
106   for (int i =0; !r && i < groups.size(); i++)
107     {
108       r = groups[i]->find_existing_translator_l (n,id);
109     }
110
111   return r;
112 }
113
114 Link_array<Translator_group>
115 Translator_group::path_to_acceptable_translator (String type) const
116 {
117  Link_array<Translator_group> accepted_arr;
118   for (int i=0; i < accepts_str_arr_.size (); i++)
119     {
120       Translator *t = output_def_l ()->find_translator_l (accepts_str_arr_[i]);
121       if (!t || !t->access_Translator_group ())
122         continue;
123       accepted_arr.push (t->access_Translator_group ());
124     }
125
126
127  for (int i=0; i < accepted_arr.size (); i++)
128     if (accepted_arr[i]->type_str_ == type)
129       {
130         Link_array<Translator_group> retval;
131         retval.push (accepted_arr[i]);
132         return retval;
133       }
134
135   Link_array<Translator_group> best_result;
136   int best_depth= INT_MAX;
137   for (int i=0; i < accepted_arr.size (); i++)
138     {
139       Translator_group * g = accepted_arr[i];
140
141       Link_array<Translator_group> result
142         = g->path_to_acceptable_translator (type);
143       if (result.size () && result.size () < best_depth)
144         {
145           result.insert (g,0);
146           best_result = result;
147         }
148     }
149
150   return best_result;
151 }
152
153 Translator_group*
154 Translator_group::find_create_translator_l (String n, String id)
155 {
156   Translator_group * existing = find_existing_translator_l (n,id);
157   if (existing)
158     return existing;
159
160   Link_array<Translator_group> path = path_to_acceptable_translator (n);
161
162   if (path.size ())
163     {
164       Translator_group * current = this;
165
166       // start at 1.  The first one (index 0) will be us.
167       for (int i=0; i < path.size (); i++)
168         {
169           Translator_group * new_group = path[i]->clone ()->access_Translator_group ();
170           current->add_translator (new_group);
171           current = new_group;
172         }
173       current->id_str_ = id;
174       return current;
175     }
176
177   Translator_group *ret = 0;
178   if (daddy_trans_l_)
179     ret = daddy_trans_l_->find_create_translator_l (n,id);
180   else
181     {
182       warning (_f ("can't find or create `%s\' called `%s\'", n, id));
183       ret =0;
184     }
185   return ret;
186 }
187
188
189 bool
190 Translator_group::do_try_request (Request* req_l)
191 {
192   bool hebbes_b =false;
193
194   Link_array<Translator> nongroups (nongroup_l_arr ());
195   
196   for (int i =0; !hebbes_b && i < nongroups.size() ; i++)
197     hebbes_b =nongroups[i]->try_request (req_l);
198   if (!hebbes_b && daddy_trans_l_)
199     hebbes_b = daddy_trans_l_->try_request (req_l);
200   return hebbes_b ;
201 }
202
203 int
204 Translator_group::depth_i() const
205 {
206   return (daddy_trans_l_) ? daddy_trans_l_->depth_i()  + 1 : 0;
207 }
208
209 Translator_group*
210 Translator_group::ancestor_l (int level)
211 {
212   if (!level || !daddy_trans_l_)
213     return this;
214
215   return daddy_trans_l_->ancestor_l (level-1);
216 }
217
218 Link_array<Translator_group>
219 Translator_group::group_l_arr () const
220 {
221   Link_array<Translator_group> groups;
222   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
223     {
224       if (i->access_Translator_group ())
225         groups.push (i->access_Translator_group ());
226     }
227   return groups;
228 }
229
230 Link_array<Translator>
231 Translator_group::nongroup_l_arr () const
232 {
233   Link_array<Translator> groups;
234   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
235     {
236       if (!i->access_Translator_group ())
237         groups.push (i.ptr ());
238     }
239   return groups;
240 }
241
242 void
243 Translator_group::terminate_translator (Translator*r_l)
244 {
245   DOUT << "Removing " << r_l->name() << " at " << now_moment () << '\n';
246   r_l->removal_processing();
247   Translator * trans_p =remove_translator_p (r_l);
248
249   delete trans_p;
250 }
251
252 Translator *
253 Translator_group::remove_translator_p (Translator*trans_l)
254 {
255   assert (trans_l);
256   
257   PCursor<Translator*> trans_cur (trans_p_list_.find (trans_l));
258   Translator * t =  trans_cur.remove_p();
259   /*
260     For elegant design, we would do this too.  Alas, it does not work yet..
261
262     t-> removal_processing ();
263   */
264   t-> daddy_trans_l_ = 0;
265   return t;
266 }
267
268
269 Translator*
270 Translator_group::get_simple_translator (char const *type) const
271 {
272   Link_array<Translator> nongroups (nongroup_l_arr ());
273   for (int i=0; i < nongroups.size(); i++)
274     {
275       if (nongroups[i]->name() == type)
276         return nongroups[i];
277     }
278   if (daddy_trans_l_)
279     return daddy_trans_l_->get_simple_translator (type);
280   return 0;
281 }
282
283
284 bool
285 Translator_group::is_bottom_translator_b () const
286 {
287   return !accepts_str_arr_.size ();
288 }
289
290
291
292 Translator_group*
293 Translator_group::get_default_interpreter()
294 {
295   if (accepts_str_arr_.size())
296     {
297       Translator*t = output_def_l ()->find_translator_l (accepts_str_arr_[0]);
298       if (!t)
299         {
300           warning (_f ("can't find or create `%s\'", accepts_str_arr_[0]));
301           t = this;
302         }
303       Translator_group * g= t->clone ()->access_Translator_group ();
304       add_translator (g);
305
306       if (!g->is_bottom_translator_b ())
307         return g->get_default_interpreter ();
308       else
309         return g;
310     }
311   return this;
312 }
313
314 void
315 Translator_group::each (Method_pointer method)
316 {
317   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
318     (i.ptr()->*method) ();
319 }
320
321 void
322 Translator_group::each (Const_method_pointer method) const
323 {
324   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
325     (i.ptr()->*method) ();
326 }
327
328 void
329 Translator_group::do_print() const
330 {
331 #ifndef NPRINT
332   if (!check_debug)
333     return ;
334   if (status == ORPHAN)
335     {
336       DOUT << "consists of: ";
337       for (int i=0; i < consists_str_arr_.size (); i++)
338         DOUT << consists_str_arr_[i] << ", ";
339       DOUT << "\naccepts: ";
340       for (int i=0; i < accepts_str_arr_.size (); i++)
341         DOUT << accepts_str_arr_[i] << ", ";
342     }
343   else
344     {
345       if (id_str_.length_i ())
346         DOUT << "ID: " << id_str_ ;
347       DOUT << " iterators: " << iterator_count_<< '\n';
348     }
349   each (&Translator::print);
350 #endif
351 }
352
353 void
354 Translator_group::do_pre_move_processing ()
355 {
356   each (&Translator::pre_move_processing);
357 }
358
359 void
360 Translator_group::do_post_move_processing ()
361 {
362   each (&Translator::post_move_processing);
363 }
364
365 void
366 Translator_group::do_process_requests ()
367 {
368   each (&Translator::process_requests);
369 }
370
371 void
372 Translator_group::do_creation_processing ()
373 {
374   each (&Translator::creation_processing);
375 }
376
377 void
378 Translator_group::do_removal_processing ()
379 {
380   each (&Translator::removal_processing);
381 }
382
383 void
384 Translator_group::do_add_processing ()
385 {
386    for (int i=0; i < consists_str_arr_.size(); i++)
387     {
388       Translator * t = output_def_l ()->find_translator_l (consists_str_arr_[i]);
389       if (!t)
390         warning (_f ("can't find `%s\'", consists_str_arr_[i]));
391       else
392         add_translator (t->clone ());
393     }
394 }