version 0.5.2
[fw/sdcc] / sim / ucsim / pobj.cc
1 /*
2  * Simulator of microcontrollers (pobj.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32
33 #include "pstr.h"
34 /*#include "pobjt.h"*/
35 #include "pobjcl.h"
36
37
38 /*                                                                          *
39   ==========================================================================*
40                                                                     cl_base *
41   ==========================================================================*
42                                                                             *
43 */
44
45 /* 
46  * Initializing the object
47  */
48
49 cl_base::cl_base(void)
50 {
51   name= 0;
52   parent= 0;
53   children= 0;
54 }
55
56
57 /* 
58  * Destructing the object: calling hte virtual Done method
59  */
60
61 cl_base::~cl_base(void)
62 {
63   if (name)
64     free(name);
65   if (children)
66     {
67       int i;
68       for (i= 0; i < children->count; i++)
69         {
70         }
71       children->disconn_all();
72       delete children;
73     }
74   parent= 0;
75 }
76
77 int cl_base::init(void) {return(0);}
78
79 char *
80 cl_base::get_name(char *def)
81 {
82   if (!name)
83     return(def);
84   return(name);
85 }
86
87 char *
88 cl_base::set_name(char *new_name)
89 {
90   if (name)
91     free(name);
92   if (!new_name)
93     name= 0;
94   else if (*new_name)
95     name= strdup(new_name);
96   else
97     name= strdup("");
98   return(name);
99 }
100
101 char *
102 cl_base::set_name(char *new_name, char *def_name)
103 {
104   char *def;
105
106   if (!def_name ||
107       *def_name == '\0')
108     def= strdup("");
109   else
110     def= strdup(def_name);
111   if (name)
112     free(name);
113   if (!new_name)
114     name= def;
115   else if (*new_name)
116     name= strdup(new_name);
117   else
118     name= def;
119   return(name);
120 }
121
122 bool
123 cl_base::is_named(char *the_name)
124 {
125   if (!name ||
126       !*name ||
127       !the_name ||
128       !*the_name)
129     return(DD_FALSE);
130   return(strcmp(name, the_name) == 0);
131 }
132
133 bool
134 cl_base::is_inamed(char *the_name)
135 {
136   if (!name ||
137       !*name ||
138       !the_name ||
139       !*the_name)
140     return(DD_FALSE);
141   return(strcasecmp(name, the_name) == 0);
142 }
143
144
145 int
146 cl_base::nuof_children(void)
147 {
148   if (!children)
149     return(0);
150   return(children->count);
151 }
152
153 void
154 cl_base::add_child(class cl_base *child)
155 {
156   if (!children)
157     {
158       char *s;
159       s= (char*)malloc(strlen(get_name("?"))+100);
160       sprintf(s, "childs of %s", get_name("?"));
161       children= new cl_list(1, 1, s);
162       free(s);
163     }
164   if (child)
165     {
166       children->add(child);
167       child->parent= this;
168     }
169 }
170
171 void
172 cl_base::remove_child(class cl_base *child)
173 {
174   if (child &&
175       children)
176     {
177       child->unlink();
178       children->disconn(child);
179     }
180 }
181
182 void
183 cl_base::remove_from_chain(void)
184 {
185   if (parent)
186     parent->remove_child(this);
187 }
188
189 void
190 cl_base::unlink(void)
191 {
192   parent= 0;
193 }
194
195 class cl_base *
196 cl_base::first_child(void)
197 {
198   if (!children ||
199       children->count == 0)
200     return(0);
201   return(dynamic_cast<class cl_base *>(children->object_at(0)));
202 }
203
204 class cl_base *
205 cl_base::next_child(class cl_base *child)
206 {
207   if (!children ||
208       !child)
209     return(0);
210   return((class cl_base *)(children->next(child)));
211 }
212
213
214 bool
215 cl_base::handle_event(class cl_event &event)
216 {
217   return(pass_event_down(event));
218 }
219
220 bool
221 cl_base::pass_event_down(class cl_event &event)
222 {
223   int i;
224   if (!children)
225     return(DD_FALSE);
226   for (i= 0; i < children->count; i++)
227     {
228       class cl_base *child=
229         dynamic_cast<class cl_base *>(children->object_at(i));
230       if (child)
231         {
232           child->handle_event(event);
233           if (event.is_handled())
234             return(DD_TRUE);
235         }
236     }
237   return(DD_FALSE);
238 }
239
240
241 /*
242  * Event
243  */
244
245 cl_event::cl_event(enum event what_event):
246   cl_base()
247 {
248   handled= DD_FALSE;
249   what= what_event;
250 }
251
252 cl_event::~cl_event(void)
253 {
254 }
255
256
257 /*                                                                          *
258   ==========================================================================*
259                                                                     cl_list *
260   ==========================================================================*
261                                                                             *
262 */
263
264 /* 
265  * Initializing a collection
266  */
267
268 cl_list::cl_list(t_index alimit, t_index adelta, char *aname):
269   cl_base()
270 {
271   count= 0;
272   Items= 0;
273   Limit= 0;
274   Delta= adelta;
275   set_limit(alimit);
276   set_name(aname, "unnamed list");
277 }
278
279
280 /* 
281  * Disposing object's variables
282  */
283
284 cl_list::~cl_list(void)
285 {
286   //delete Items;
287   free(Items);
288 }
289
290
291 /*
292  * Get indexed item from the collection
293  */
294
295 void *
296 cl_list::at(t_index index)
297 {
298   if (index < 0 ||
299       index >= count)
300     error(1, index);
301   return(Items[index]);
302 }
303
304 class cl_base *
305 cl_list::object_at(t_index index)
306 {
307   if (index < 0 ||
308       index >= count)
309     error(1, index);
310   return((class cl_base *)(Items[index]));
311 }
312
313 /*void *
314 cl_list::operator[](t_index index)
315 {
316   if (index < 0 ||
317       index >= count)
318     error(1, 0);
319   return(Items[index]);  
320 }*/
321
322
323 /*
324  * Deleting the indexed item from the collection
325  */
326 #include "globals.h"
327 void
328 cl_list::disconn_at(t_index index)
329 {
330   if (index < 0 ||
331       index >= count)
332     error(1, 0);
333   count--;
334   /*{ char s[1000];
335   s[0]='\0';
336   sprintf(s, "disconn_at(%d) PC=0x%x", index,
337           application?
338           ((application->sim)?
339            ((application->sim->uc)?(application->sim->uc->PC):
340             -3):
341            -1):
342           -2);
343           strcat(s,"\n");}*/
344   memmove(&Items[index], &Items[index+1], (count-index)*sizeof(void *));
345 }
346
347
348 /*
349  * Deleting an item from the collection but not disposing it
350  */
351
352 void
353 cl_list::disconn(void *item)
354 {
355   t_index i;
356
357   if (index_of(item, &i))
358     disconn_at(i);
359 }
360
361
362 /* 
363  * Deleting all the items from the collection but not disposing them
364  */
365
366 void
367 cl_list::disconn_all(void)
368 {
369   count= 0;
370 }
371
372
373 /*
374  * Deleting the indexed item from the collection and disposing it
375  */
376
377 void
378 cl_list::free_at(t_index index)
379 {
380   void *Item= at(index);
381
382   disconn_at(index);
383   free_item(Item);
384 }
385
386 void
387 cl_list::free_all(void)
388 {
389   t_index i;
390
391   if (count)
392     {
393       for (i= count-1; i; i--)
394         free_at(i);
395       free_at(0);
396     }
397 }
398
399
400 /*
401  * Inserting a new item to the exact position
402  */
403
404 void
405 cl_list::add_at(t_index index, void *item)
406 {
407   if (index < 0 )
408     error(1, 0);
409   if (count == Limit)
410     set_limit(count + Delta);
411
412   { char s[1000];
413   s[0]='\0';
414   sprintf(s, "%s add_at(%d,%p) PC=0x%x (count=%d)", get_name("?"), index, item,
415           application?
416           ((application->sim)?
417            ((application->sim->uc)?(application->sim->uc->PC):
418             -3):
419            -1):
420           -2, count);
421   strcat(s,"\n");}
422   memmove(&Items[index+1], &Items[index], (count-index)*sizeof(void *));
423   count++;
424
425   Items[index]= item;
426 }
427
428
429 /* 
430  * Put a new item to the collection. This function replaces an existing
431  * item with a new one but it does not delete or dispose the old item!
432  */
433
434 void
435 cl_list::put_at(t_index index, void *item)
436 {
437   if (index >= count)
438     error(1, 0);
439   Items[index]= item;
440 }
441
442
443 /* 
444  * Action taken when an error occure
445  */
446
447 void
448 cl_list::error(t_index code, t_index info)
449 {
450   fprintf(stderr, 
451           "Collection index error. Code= %d, Info= %d.\n",
452           code, info);
453   exit(code);
454 }
455
456
457 /* 
458  * Iterator method. This function calls 'Test' using every items as Test's
459  * argument until Test returns TRUE.
460  */
461
462 void *
463 cl_list::first_that(match_func test, void *arg)
464 {
465   for (t_index i= 0; i < count; i++)
466     {
467       if (test(Items[i], arg)) return(Items[i]);
468     }
469   return(0);
470 }
471
472
473 /* 
474  * Iterator method. This function calls 'Action' using every items as
475  * Action's argument.
476  */
477
478 void
479 cl_list::for_each(iterator_func action, void *arg)
480 {
481   for(t_index i= 0; i < count; i++)
482     action(Items[i], arg);
483 }
484
485
486 /* 
487  * Disposing an item.
488  */
489
490 void
491 cl_list::free_item(void *item)
492 {
493   delete (class cl_base*)item;
494 }
495
496
497 /* 
498  * Get the number of collected items.
499  */
500
501 int
502 cl_list::get_count(void)
503 {
504   return(count);
505 }
506
507 void *
508 cl_list::pop(void)
509 {
510   void *i;
511
512   if (!count)
513     return(0);
514   i= Items[0];
515   disconn_at(0);
516   return(i);
517 }
518
519 void *
520 cl_list::top(void)
521 {
522   if (!count)
523     return(0);
524   return(Items[0]);
525 }
526
527
528 /* 
529  * Returning the index of an item.
530  */
531
532 t_index
533 cl_list::index_of(void *item)
534 {
535   for (t_index i= 0; i < count; i++)
536     if (item == Items[i])
537       return(i);
538   error(1, 0);
539   return(0);    /* Needed by Sun! */
540 }
541
542 bool
543 cl_list::index_of(void *item, t_index *idx)
544 {
545   for (t_index i= 0; i < count; i++)
546     if (item == Items[i])
547       {
548         if (idx)
549           *idx= i;
550         return(DD_TRUE);
551       }
552   return(DD_FALSE);
553 }
554
555 void *
556 cl_list::next(void *item)
557 {
558   for (t_index i= 0; i < count; i++)
559     if (item == Items[i])
560       {
561         if (count >= 2 &&
562             i < count-1)
563           return(Items[i+1]);
564       }
565   return(0);
566 }
567
568
569 /* 
570  * Inserting a new item to the collection.
571  */
572
573 t_index
574 cl_list::add(void *item)
575 {
576   t_index loc= count;
577
578   add_at(count, item);
579   return(loc);
580 }
581
582 t_index
583 cl_list::add(class cl_base *item, class cl_base *parent)
584 {
585   if (parent && item)
586     parent->add_child(item);
587   return(add(item));
588 }
589
590 void
591 cl_list::push(void *item)
592 {
593   if (count)
594     add_at(0, item);
595   else
596     add(item);
597 }
598
599
600 /* 
601  * Iterator method. This function calls 'Test' using every items
602  * (in reversed order) as Test's argument until Test returns TRUE.
603  */
604
605 void *
606 cl_list::last_that(match_func test, void *arg)
607 {
608   for(t_index i= count; i > 0; i--)
609     if (test(Items[i-1], arg))
610       return(Items[i-1]);
611   return(0);
612 }
613
614
615 /*
616  * ???
617  */
618
619 /*void
620 cl_list::pack(void)
621 {
622   void **CurDst= Items;
623   void **CurSrc= Items;
624   void **Last  = Items + count;
625
626   while (CurSrc < Last)
627     {
628       if (*CurSrc != 0)
629         *CurDst++= *CurSrc;
630       *CurSrc++;
631     }
632 }*/
633
634
635 /*
636  * Setting up the maximum number of items. This function may expand
637  * the size of the collection.
638  */
639
640 void
641 cl_list::set_limit(t_index alimit)
642 {
643   void **AItems;
644
645   if (alimit < count)
646     alimit= count;
647   if (alimit > (int)max_list_size)
648     alimit= max_list_size;
649   if (alimit != Limit)
650     {
651       if (alimit == 0)
652         AItems= 0;
653       else
654         {
655           //AItems = new void *[alimit];
656           int i= alimit*(sizeof(void *));
657           AItems= (void **)malloc(i);
658           if (count)
659             memcpy(AItems, Items, count*sizeof(void *));
660         }
661       //delete Items;
662       free(Items);
663       Items= AItems;
664       Limit= alimit;
665     }
666 }
667
668
669 /*                                                                          *
670   ==========================================================================*
671                                                              cl_sorted_list *
672   ==========================================================================*
673                                                                             *
674 */
675
676 /* 
677  * Initilizing the sorted collection
678  */
679
680 cl_sorted_list::cl_sorted_list(t_index alimit, t_index adelta, char *aname):
681   cl_list(alimit, adelta, aname)
682 {
683   Duplicates= DD_FALSE;
684 }
685
686
687 cl_sorted_list::~cl_sorted_list(void) {}
688
689
690 /* 
691  * Get the address of the key field in an item.
692  */
693
694 void *
695 cl_sorted_list::key_of(void *item)
696 {
697   return(item);
698 }
699
700
701 /* 
702  * Get index of an item.
703  */
704
705 t_index
706 cl_sorted_list::index_of(void *item)
707 {
708   t_index       i;
709
710   if (search(key_of(item), i) == 0)
711     return(ccNotFound);
712   else
713     {
714       if (Duplicates)
715         while (i < count &&
716                item != Items[i])
717           i++;
718       if (i < count)
719         return(i);
720       else
721         return(ccNotFound);
722     }
723 }
724
725
726 /*
727  * Inserting a new item to the collection
728  */
729
730 t_index
731 cl_sorted_list::add(void *item)
732 {
733   t_index i;
734
735   if (search(key_of(item), i) == 0 ||
736       Duplicates)                               // order dependency!
737     add_at(i, item);                            // must do Search
738                                                 // before calling
739                                                 // AtInsert
740   return(i);
741 }
742
743
744 /*
745  * Searching an item using binary search.
746  */
747
748 bool
749 cl_sorted_list::search(void *key, t_index &index)
750 {
751   t_index l  = 0;
752   t_index h  = count - 1;
753   bool    res= DD_FALSE;
754   
755   while (l <= h)
756     {
757       t_index i= (l + h) >> 1;
758       t_index c= compare(key_of(Items[i]), key);
759       if (c < 0) l= i + 1;
760       else
761         {
762           h= i - 1;
763           if (c == 0)
764             {
765               res= DD_TRUE;
766               if (!Duplicates)
767                 l= i;
768             }
769         }
770     }
771   index= l;
772   return(res);
773 }
774
775
776 /*                                                                          *
777   ==========================================================================*
778                                                                  cl_strings *
779   ==========================================================================*
780                                                                             *
781 */
782
783 /* 
784  * Initilizing the string collection
785  */
786
787 cl_strings::cl_strings(t_index alimit, t_index adelta, char *aname):
788   cl_sorted_list(alimit, adelta, aname)
789 {
790   Duplicates= DD_TRUE;
791 }
792
793
794 cl_strings::~cl_strings(void) {}
795
796
797 /* 
798  * Comapare two string from the collection
799  */
800
801 int
802 cl_strings::compare(void *key1, void *key2)
803 {
804   return(strcmp((char *)key1, (char *)key2));
805 }
806
807
808 /* 
809  * Deallocate string item of the collection
810  */
811
812 void
813 cl_strings::free_item(void* item)
814 {
815   delete (class cl_base*)item;
816 }
817
818
819 /*                                                                          *
820   ==========================================================================*
821                                                                 cl_ustrings *
822   ==========================================================================*
823                                                                             *
824 */
825
826 /*
827  * Initilizing the unsorted string collection
828  */
829
830 cl_ustrings::cl_ustrings(t_index alimit, t_index adelta, char *aname):
831   cl_strings(alimit, adelta, aname)
832 {}
833
834
835 cl_ustrings::~cl_ustrings(void) {}
836
837
838 /*
839  * Comapare two string from the collection
840  */
841
842 int
843 cl_ustrings::compare(void *key1, void *key2)
844 {
845   return(-1);
846 }
847
848
849 /* 
850  * Searching an item using linear search.
851  */
852
853 bool
854 cl_ustrings::search(void *key, t_index& index)
855 {
856   t_index i    = 0;
857   bool    found= DD_FALSE;
858   void    *Actual;
859
860   if ((count) && key)
861     {
862       while (!found && (i < count))
863         {
864           Actual= key_of(at(i));
865           found = (Actual != 0) &&
866                   (compare(key, Actual) == 0);
867           i++;
868         }
869     }
870   if (found)
871     index= i-1;
872   else
873     index= count;
874
875   return(found);
876 }
877
878 /* End of pobj.cc */