f747e96bbd9473988f2970dbc821bc21afc1eced
[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 }
53
54
55 /* 
56  * Destructing the object: calling hte virtual Done method
57  */
58
59 cl_base::~cl_base(void)
60 {
61   if (name)
62     free(name);
63 }
64
65 int cl_base::init(void) {return(0);}
66
67 char *
68 cl_base::get_name(char *def)
69 {
70   if (!name)
71     return(def);
72   return(name);
73 }
74
75 char *
76 cl_base::set_name(char *new_name)
77 {
78   if (name)
79     free(name);
80   if (!new_name)
81     name= 0;
82   else if (*new_name)
83     name= strdup(new_name);
84   else
85     name= strdup("");
86   return(name);
87 }
88
89
90 /*                                                                          *
91   ==========================================================================*
92                                                                     cl_list *
93   ==========================================================================*
94                                                                             *
95 */
96
97 /* 
98  * Initializing a collection
99  */
100
101 cl_list::cl_list(t_index alimit, t_index adelta):
102   cl_base()
103 {
104   count= 0;
105   Items= 0;
106   Limit= 0;
107   Delta= adelta;
108   set_limit(alimit);
109 }
110
111
112 /* 
113  * Disposing object's variables
114  */
115
116 cl_list::~cl_list(void)
117 {
118   //delete Items;
119   free(Items);
120 }
121
122
123 /*
124  * Get indexed item from the collection
125  */
126
127 void *
128 cl_list::at(t_index index)
129 {
130   if (index < 0 ||
131       index >= count)
132     error(1, index);
133   return(Items[index]);
134 }
135
136 /*void *
137 cl_list::operator[](t_index index)
138 {
139   if (index < 0 ||
140       index >= count)
141     error(1, 0);
142   return(Items[index]);  
143 }*/
144
145
146 /*
147  * Deleting the indexed item from the collection
148  */
149
150 void
151 cl_list::disconn_at(t_index index)
152 {
153   if (index < 0 ||
154       index >= count)
155     error(1, 0);
156   count--;
157   memmove(&Items[index], &Items[index+1], (count-index)*sizeof(void *));
158 }
159
160
161 /*
162  * Deleting an item from the collection but not disposing it
163  */
164
165 void
166 cl_list::disconn(void *item)
167 {
168   t_index i;
169
170   if (index_of(item, &i))
171     disconn_at(i);
172 }
173
174
175 /* 
176  * Deleting all the items from the collection but not disposing them
177  */
178
179 void
180 cl_list::disconn_all(void)
181 {
182   count= 0;
183 }
184
185
186 /*
187  * Deleting the indexed item from the collection and disposing it
188  */
189
190 void
191 cl_list::free_at(t_index index)
192 {
193   void *Item= at(index);
194
195   disconn_at(index);
196   free_item(Item);
197 }
198
199 void
200 cl_list::free_all(void)
201 {
202   t_index i;
203
204   if (count)
205     {
206       for (i= count-1; i; i--)
207         free_at(i);
208       free_at(0);
209     }
210 }
211
212
213 /*
214  * Inserting a new item to the exact position
215  */
216
217 void
218 cl_list::add_at(t_index index, void *item)
219 {
220   if (index < 0 )
221     error(1, 0);
222   if (count == Limit)
223     set_limit(count + Delta);
224
225   memmove(&Items[index+1], &Items[index], (count-index)*sizeof(void *));
226   count++;
227
228   Items[index]= item;
229 }
230
231
232 /* 
233  * Put a new item to the collection. This function replaces an existing
234  * item with a new one but it does not delete or dispose the old item!
235  */
236
237 void
238 cl_list::put_at(t_index index, void *item)
239 {
240   if (index >= count)
241     error(1, 0);
242   Items[index]= item;
243 }
244
245
246 /* 
247  * Action taken when an error occure
248  */
249
250 void
251 cl_list::error(t_index code, t_index info)
252 {
253   fprintf(stderr, 
254           "Collection index error. Code= %d, Info= %d.\n",
255           code, info);
256   exit(code);
257 }
258
259
260 /* 
261  * Iterator method. This function calls 'Test' using every items as Test's
262  * argument until Test returns TRUE.
263  */
264
265 void *
266 cl_list::first_that(match_func test, void *arg)
267 {
268   for (t_index i= 0; i < count; i++)
269     {
270       if (test(Items[i], arg)) return(Items[i]);
271     }
272   return(0);
273 }
274
275
276 /* 
277  * Iterator method. This function calls 'Action' using every items as
278  * Action's argument.
279  */
280
281 void
282 cl_list::for_each(iterator_func action, void *arg)
283 {
284   for(t_index i= 0; i < count; i++)
285     action(Items[i], arg);
286 }
287
288
289 /* 
290  * Disposing an item.
291  */
292
293 void
294 cl_list::free_item(void *item)
295 {
296   delete (class cl_base*)item;
297 }
298
299
300 /* 
301  * Get the number of collected items.
302  */
303
304 int
305 cl_list::get_count(void)
306 {
307   return(count);
308 }
309
310 void *
311 cl_list::pop(void)
312 {
313   void *i;
314
315   if (!count)
316     return(0);
317   i= Items[0];
318   disconn_at(0);
319   return(i);
320 }
321
322 void *
323 cl_list::top(void)
324 {
325   if (!count)
326     return(0);
327   return(Items[0]);
328 }
329
330
331 /* 
332  * Returning the index of an item.
333  */
334
335 t_index
336 cl_list::index_of(void *item)
337 {
338   for (t_index i= 0; i < count; i++)
339     if (item == Items[i])
340       return(i);
341   error(1, 0);
342   return(0);    /* Needed by Sun! */
343 }
344
345 bool
346 cl_list::index_of(void *item, t_index *idx)
347 {
348   for (t_index i= 0; i < count; i++)
349     if (item == Items[i])
350       {
351         if (idx)
352           *idx= i;
353         return(DD_TRUE);
354       }
355   return(DD_FALSE);
356 }
357
358
359 /* 
360  * Inserting a new item to the collection.
361  */
362
363 t_index
364 cl_list::add(void *item)
365 {
366   t_index loc= count;
367
368   add_at(count, item);
369   return(loc);
370 }
371
372
373 void
374 cl_list::push(void *item)
375 {
376   if (count)
377     add_at(0, item);
378   else
379     add(item);
380 }
381
382
383 /* 
384  * Iterator method. This function calls 'Test' using every items
385  * (in reversed order) as Test's argument until Test returns TRUE.
386  */
387
388 void *
389 cl_list::last_that(match_func test, void *arg)
390 {
391   for(t_index i= count; i > 0; i--)
392     if (test(Items[i-1], arg))
393       return(Items[i-1]);
394   return(0);
395 }
396
397
398 /*
399  * ???
400  */
401
402 /*void
403 cl_list::pack(void)
404 {
405   void **CurDst= Items;
406   void **CurSrc= Items;
407   void **Last  = Items + count;
408
409   while (CurSrc < Last)
410     {
411       if (*CurSrc != 0)
412         *CurDst++= *CurSrc;
413       *CurSrc++;
414     }
415 }*/
416
417
418 /*
419  * Setting up the maximum number of items. This function may expand
420  * the size of the collection.
421  */
422
423 void
424 cl_list::set_limit(t_index alimit)
425 {
426   void **AItems;
427
428   if (alimit < count)
429     alimit= count;
430   if (alimit > (int)max_list_size)
431     alimit= max_list_size;
432   if (alimit != Limit)
433     {
434       if (alimit == 0)
435         AItems= 0;
436       else
437         {
438           //AItems = new void *[alimit];
439           int i= alimit*(sizeof(void *));
440           AItems= (void **)malloc(i);
441           if (count)
442             memcpy(AItems, Items, count*sizeof(void *));
443         }
444       //delete Items;
445       free(Items);
446       Items= AItems;
447       Limit= alimit;
448     }
449 }
450
451
452 /*                                                                          *
453   ==========================================================================*
454                                                              cl_sorted_list *
455   ==========================================================================*
456                                                                             *
457 */
458
459 /* 
460  * Initilizing the sorted collection
461  */
462
463 cl_sorted_list::cl_sorted_list(t_index alimit, t_index adelta):
464   cl_list(alimit, adelta)
465 {
466   Duplicates= DD_FALSE;
467 }
468
469
470 cl_sorted_list::~cl_sorted_list(void) {}
471
472
473 /* 
474  * Get the address of the key field in an item.
475  */
476
477 void *
478 cl_sorted_list::key_of(void *item)
479 {
480   return(item);
481 }
482
483
484 /* 
485  * Get index of an item.
486  */
487
488 t_index
489 cl_sorted_list::index_of(void *item)
490 {
491   t_index       i;
492
493   if (search(key_of(item), i) == 0)
494     return(ccNotFound);
495   else
496     {
497       if (Duplicates)
498         while (i < count &&
499                item != Items[i])
500           i++;
501       if (i < count)
502         return(i);
503       else
504         return(ccNotFound);
505     }
506 }
507
508
509 /*
510  * Inserting a new item to the collection
511  */
512
513 t_index
514 cl_sorted_list::add(void *item)
515 {
516   t_index i;
517
518   if (search(key_of(item), i) == 0 ||
519       Duplicates)                               // order dependency!
520     add_at(i, item);                            // must do Search
521                                                 // before calling
522                                                 // AtInsert
523   return(i);
524 }
525
526
527 /*
528  * Searching an item using binary search.
529  */
530
531 bool
532 cl_sorted_list::search(void *key, t_index &index)
533 {
534   t_index l  = 0;
535   t_index h  = count - 1;
536   bool    res= DD_FALSE;
537   
538   while (l <= h)
539     {
540       t_index i= (l + h) >> 1;
541       t_index c= compare(key_of(Items[i]), key);
542       if (c < 0) l= i + 1;
543       else
544         {
545           h= i - 1;
546           if (c == 0)
547             {
548               res= DD_TRUE;
549               if (!Duplicates)
550                 l= i;
551             }
552         }
553     }
554   index= l;
555   return(res);
556 }
557
558
559 /*                                                                          *
560   ==========================================================================*
561                                                                  cl_strings *
562   ==========================================================================*
563                                                                             *
564 */
565
566 /* 
567  * Initilizing the string collection
568  */
569
570 cl_strings::cl_strings(t_index alimit, t_index adelta):
571   cl_sorted_list(alimit, adelta)
572 {
573   Duplicates= DD_TRUE;
574 }
575
576
577 cl_strings::~cl_strings(void) {}
578
579
580 /* 
581  * Comapare two string from the collection
582  */
583
584 int
585 cl_strings::compare(void *key1, void *key2)
586 {
587   return(strcmp((char *)key1, (char *)key2));
588 }
589
590
591 /* 
592  * Deallocate string item of the collection
593  */
594
595 void
596 cl_strings::free_item(void* item)
597 {
598   delete (class cl_base*)item;
599 }
600
601
602 /*                                                                          *
603   ==========================================================================*
604                                                                 cl_ustrings *
605   ==========================================================================*
606                                                                             *
607 */
608
609 /*
610  * Initilizing the unsorted string collection
611  */
612
613 cl_ustrings::cl_ustrings(t_index alimit, t_index adelta):
614   cl_strings(alimit, adelta)
615 {}
616
617
618 cl_ustrings::~cl_ustrings(void) {}
619
620
621 /*
622  * Comapare two string from the collection
623  */
624
625 int
626 cl_ustrings::compare(void *key1, void *key2)
627 {
628   return(-1);
629 }
630
631
632 /* 
633  * Searching an item using linear search.
634  */
635
636 bool
637 cl_ustrings::search(void *key, t_index& index)
638 {
639   t_index i    = 0;
640   bool    found= DD_FALSE;
641   void    *Actual;
642
643   if ((count) && key)
644     {
645       while (!found && (i < count))
646         {
647           Actual= key_of(at(i));
648           found = (Actual != 0) &&
649                   (compare(key, Actual) == 0);
650           i++;
651         }
652     }
653   if (found)
654     index= i-1;
655   else
656     index= count;
657
658   return(found);
659 }
660
661 /* End of pobj.cc */