]> git.donarmstrong.com Git - lilypond.git/blob - lily/translator-group.cc
3d5a6ff2d0a4cd5dfcf0d895c2a27fe64cec5ab2
[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   for (int i =0; i < group_l_arr ().size();)
39     {
40       group_l_arr ()[i]->check_removal();
41       if (group_l_arr ()[i]->removable_b())
42         terminate_translator (group_l_arr ()[i]);
43       else
44         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   return !(iterator_count_ || group_l_arr ().size());
90 }
91
92 Translator_group *
93 Translator_group::find_existing_translator_l (String n, String id)
94 {
95   if (is_alias_b (n) && (id_str_ == id || id.empty_b ()))
96     return this;
97   Translator_group* r = 0;
98   for (int i =0; !r && i < group_l_arr ().size(); i++)
99     {
100       r = group_l_arr ()[i]->find_existing_translator_l (n,id);
101     }
102
103   return r;
104 }
105
106 Link_array<Translator_group>
107 Translator_group::path_to_acceptable_translator (String type) const
108 {
109  Link_array<Translator_group> accepted_arr;
110   for (int i=0; i < accepts_str_arr_.size (); i++)
111     {
112       Translator *t = output_def_l ()->find_translator_l (accepts_str_arr_[i]);
113       if (!t || !t->access_Translator_group ())
114         continue;
115       accepted_arr.push (t->access_Translator_group ());
116     }
117
118
119  for (int i=0; i < accepted_arr.size (); i++)
120     if (accepted_arr[i]->type_str_ == type)
121       {
122         Link_array<Translator_group> retval;
123         retval.push (accepted_arr[i]);
124         return retval;
125       }
126
127   Link_array<Translator_group> best_result;
128   int best_depth= INT_MAX;
129   for (int i=0; i < accepted_arr.size (); i++)
130     {
131       Translator_group * g = accepted_arr[i];
132
133       Link_array<Translator_group> result
134         = g->path_to_acceptable_translator (type);
135       if (result.size () && result.size () < best_depth)
136         {
137           result.insert (g,0);
138           best_result = result;
139         }
140     }
141
142   return best_result;
143 }
144
145 Translator_group*
146 Translator_group::find_create_translator_l (String n, String id)
147 {
148   Translator_group * existing = find_existing_translator_l (n,id);
149   if (existing)
150     return existing;
151
152   Link_array<Translator_group> path = path_to_acceptable_translator (n);
153
154   if (path.size ())
155     {
156       Translator_group * current = this;
157
158       // start at 1.  The first one (index 0) will be us.
159       for (int i=0; i < path.size (); i++)
160         {
161           Translator_group * new_group = path[i]->clone ()->access_Translator_group ();
162           current->add_translator (new_group);
163           current = new_group;
164         }
165       current->id_str_ = id;
166       return current;
167     }
168
169   Translator_group *ret = 0;
170   if (daddy_trans_l_)
171     ret = daddy_trans_l_->find_create_translator_l (n,id);
172   else
173     {
174       warning (_f ("can't find or create `%s\' called `%s\'", n, id));
175       ret =0;
176     }
177   return ret;
178 }
179
180
181 bool
182 Translator_group::do_try_request (Request* req_l)
183 {
184   bool hebbes_b =false;
185   for (int i =0; !hebbes_b && i < nongroup_l_arr ().size() ; i++)
186     hebbes_b =nongroup_l_arr ()[i]->try_request (req_l);
187   if (!hebbes_b && daddy_trans_l_)
188     hebbes_b = daddy_trans_l_->try_request (req_l);
189   return hebbes_b ;
190 }
191
192 int
193 Translator_group::depth_i() const
194 {
195   return (daddy_trans_l_) ? daddy_trans_l_->depth_i()  + 1 : 0;
196 }
197
198 Translator_group*
199 Translator_group::ancestor_l (int level)
200 {
201   if (!level || !daddy_trans_l_)
202     return this;
203
204   return daddy_trans_l_->ancestor_l (level-1);
205 }
206
207 Link_array<Translator_group>
208 Translator_group::group_l_arr () const
209 {
210   Link_array<Translator_group> groups;
211   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
212     {
213       if (i->access_Translator_group ())
214         groups.push (i->access_Translator_group ());
215     }
216   return groups;
217 }
218
219 Link_array<Translator>
220 Translator_group::nongroup_l_arr () const
221 {
222   Link_array<Translator> groups;
223   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
224     {
225       if (!i->access_Translator_group ())
226         groups.push (i.ptr ());
227     }
228   return groups;
229 }
230
231 void
232 Translator_group::terminate_translator (Translator*r_l)
233 {
234   DOUT << "Removing " << r_l->name() << " at " << now_moment () << '\n';
235   r_l->removal_processing();
236   Translator * trans_p =remove_translator_p (r_l);
237
238   delete trans_p;
239 }
240
241 Translator *
242 Translator_group::remove_translator_p (Translator*trans_l)
243 {
244   assert (trans_l);
245   
246   PCursor<Translator*> trans_cur (trans_p_list_.find (trans_l));
247   Translator * t =  trans_cur.remove_p();
248   /*
249     For elegant design, we would do this too.  Alas, it does not work yet..
250
251     t-> removal_processing ();
252   */
253   t-> daddy_trans_l_ = 0;
254   return t;
255 }
256
257
258 Translator*
259 Translator_group::get_simple_translator (char const *type) const
260 {
261   for (int i=0; i < nongroup_l_arr ().size(); i++)
262     {
263       if (nongroup_l_arr ()[i]->name() == type)
264         return nongroup_l_arr ()[i];
265     }
266   if (daddy_trans_l_)
267     return daddy_trans_l_->get_simple_translator (type);
268   return 0;
269 }
270
271
272 bool
273 Translator_group::is_bottom_translator_b () const
274 {
275   return !accepts_str_arr_.size ();
276 }
277
278
279
280 Translator_group*
281 Translator_group::get_default_interpreter()
282 {
283   if (accepts_str_arr_.size())
284     {
285       Translator*t = output_def_l ()->find_translator_l (accepts_str_arr_[0]);
286       if (!t)
287         {
288           warning (_f ("can't find or create `%s\'", accepts_str_arr_[0]));
289           t = this;
290         }
291       Translator_group * g= t->clone ()->access_Translator_group ();
292       add_translator (g);
293
294       if (!g->is_bottom_translator_b ())
295         return g->get_default_interpreter ();
296       else
297         return g;
298     }
299   return this;
300 }
301
302 void
303 Translator_group::each (Method_pointer method)
304 {
305   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
306     (i.ptr()->*method) ();
307 }
308
309 void
310 Translator_group::each (Const_method_pointer method) const
311 {
312   for (PCursor<Translator*> i (trans_p_list_.top ()); i.ok (); i++)
313     (i.ptr()->*method) ();
314 }
315
316 void
317 Translator_group::do_print() const
318 {
319 #ifndef NPRINT
320   if (!check_debug)
321     return ;
322   if (status == ORPHAN)
323     {
324       DOUT << "consists of: ";
325       for (int i=0; i < consists_str_arr_.size (); i++)
326         DOUT << consists_str_arr_[i] << ", ";
327       DOUT << "\naccepts: ";
328       for (int i=0; i < accepts_str_arr_.size (); i++)
329         DOUT << accepts_str_arr_[i] << ", ";
330     }
331   else
332     {
333       if (id_str_.length_i ())
334         DOUT << "ID: " << id_str_ ;
335       DOUT << " iterators: " << iterator_count_<< '\n';
336     }
337   each (&Translator::print);
338 #endif
339 }
340
341 void
342 Translator_group::do_pre_move_processing ()
343 {
344   each (&Translator::pre_move_processing);
345 }
346
347 void
348 Translator_group::do_post_move_processing ()
349 {
350   each (&Translator::post_move_processing);
351 }
352
353 void
354 Translator_group::do_process_requests ()
355 {
356   each (&Translator::process_requests);
357 }
358
359 void
360 Translator_group::do_creation_processing ()
361 {
362   each (&Translator::creation_processing);
363 }
364
365 void
366 Translator_group::do_removal_processing ()
367 {
368   each (&Translator::removal_processing);
369 }
370
371 void
372 Translator_group::do_add_processing ()
373 {
374    for (int i=0; i < consists_str_arr_.size(); i++)
375     {
376       Translator * t = output_def_l ()->find_translator_l (consists_str_arr_[i]);
377       if (!t)
378         warning (_f ("can't find `%s\'", consists_str_arr_[i]));
379       else
380         add_translator (t->clone ());
381     }
382 }