sdcc-gas/sim/ucsim/pobj.cc

903 lines
14 KiB
C++

/*
* Simulator of microcontrollers (pobj.cc)
*
* Copyright (C) 1997,16 Drotos Daniel, Talker Bt.
*
* To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
*
*/
/* This file is part of microcontroller simulator: ucsim.
UCSIM is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
UCSIM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with UCSIM; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/*@1@*/
#include "ddconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include "pstr.h"
/*#include "pobjt.h"*/
#include "pobjcl.h"
/* *
==========================================================================*
cl_base *
==========================================================================*
*
*/
/*
* Initializing the object
*/
cl_base::cl_base(void)
{
name= 0;
parent= 0;
children= 0;
}
/*
* Destructing the object: calling hte virtual Done method
*/
cl_base::~cl_base(void)
{
//if (name) free((void*)name);
if (children)
{
int i;
for (i= 0; i < children->count; i++)
{
}
children->disconn_all();
delete children;
}
parent= 0;
}
int cl_base::init(void) {return(0);}
const char *
cl_base::get_name(const char *def)
{
if (!name)
return(def);
return(name);
}
const char *
cl_base::set_name(const char *new_name)
{
/*
if (name)
free((void*)name);
if (!new_name)
name= 0;
else if (*new_name)
name= strdup(new_name);
else
name= strdup("");
*/
name= new_name;
return(name);
}
const char *
cl_base::set_name(const char *new_name, const char *def_name)
{
char *def;
if (!def_name ||
*def_name == '\0')
def= /*strdup*/cchars("");
else
def= /*strdup*/cchars(def_name);
// if (name) free((void*)name);
if (!new_name)
name= def;
else if (*new_name)
name= /*strdup*/(new_name);
else
name= def;
return(name);
}
bool
cl_base::is_named(const char *the_name)
{
/*
if (!name ||
!*name ||
!the_name ||
!*the_name)
return(false);*/
return(/*strcmp(name, the_name) == 0*/name==the_name);
}
bool
cl_base::is_inamed(const char *the_name)
{
if (/*!name ||
!*name ||
!the_name ||
!*the_name*/name.empty())
return(false);
return(strcasecmp(name, the_name) == 0);
}
int
cl_base::nuof_children(void)
{
if (!children)
return(0);
return(children->count);
}
void
cl_base::add_child(class cl_base *child)
{
if (!children)
{
/*
char *s;
s= (char*)malloc(name.len()+100);
sprintf(s, "children of %s", get_name("?"));
*/
chars cs("", "children of %s", get_name("?"));
children= new cl_list(1, 1, cs);
//free(s);
}
if (child)
{
children->add(child);
child->parent= this;
}
}
void
cl_base::remove_child(class cl_base *child)
{
if (child &&
children)
{
child->unlink();
children->disconn(child);
}
}
void
cl_base::remove_from_chain(void)
{
if (parent)
parent->remove_child(this);
}
void
cl_base::unlink(void)
{
parent= 0;
}
class cl_base *
cl_base::first_child(void)
{
if (!children ||
children->count == 0)
return(0);
return(dynamic_cast<class cl_base *>(children->object_at(0)));
}
class cl_base *
cl_base::next_child(class cl_base *child)
{
if (!children ||
!child)
return(0);
return((class cl_base *)(children->next(child)));
}
bool
cl_base::handle_event(class cl_event &event)
{
return(pass_event_down(event));
}
bool
cl_base::pass_event_down(class cl_event &event)
{
int i;
if (!children)
return(false);
for (i= 0; i < children->count; i++)
{
class cl_base *child=
dynamic_cast<class cl_base *>(children->object_at(i));
if (child)
{
child->handle_event(event);
if (event.is_handled())
return(true);
}
}
return(false);
}
/*
* Event
*/
cl_event::cl_event(enum event what_event):
cl_base()
{
handled= false;
what= what_event;
}
cl_event::~cl_event(void)
{
}
/* *
==========================================================================*
cl_list *
==========================================================================*
*
*/
/*
* Initializing a collection
*/
cl_list::cl_list(t_index alimit, t_index adelta, char *aname):
cl_base()
{
count= 0;
Items= 0;
Limit= 0;
Delta= adelta;
set_limit(alimit);
set_name(aname, "unnamed list");
}
cl_list::cl_list(t_index alimit, t_index adelta, const char *aname):
cl_base()
{
count= 0;
Items= 0;
Limit= 0;
Delta= adelta;
set_limit(alimit);
set_name(aname, "unnamed list");
}
/*
* Disposing object's variables
*/
cl_list::~cl_list(void)
{
//delete Items;
free(Items);
}
/*
* Get indexed item from the collection
*/
/*void *
cl_list::at(t_index index)
{
if (index < 0 ||
index >= count)
error(1, index);
return(Items[index]);
}*/
class cl_base *
cl_list::object_at(t_index index)
{
if (index < 0 ||
index >= count)
error(1, index);
return((class cl_base *)(Items[index]));
}
/*void *
cl_list::operator[](t_index index)
{
if (index < 0 ||
index >= count)
error(1, 0);
return(Items[index]);
}*/
/*
* Deleting the indexed item from the collection
*/
void
cl_list::disconn_at(t_index index)
{
if (index < 0 ||
index >= count)
error(1, 0);
count--;
memmove(&Items[index], &Items[index+1], (count-index)*sizeof(void *));
}
/*
* Deleting an item from the collection but not disposing it
*/
void
cl_list::disconn(void *item)
{
t_index i;
if (index_of(item, &i))
disconn_at(i);
}
/*
* Deleting all the items from the collection but not disposing them
*/
void
cl_list::disconn_all(void)
{
count= 0;
}
/*
* Deleting the indexed item from the collection and disposing it
*/
void
cl_list::free_at(t_index index)
{
void *Item= at(index);
disconn_at(index);
free_item(Item);
}
void
cl_list::free_all(void)
{
t_index i;
if (count)
{
for (i= count-1; i; i--)
free_at(i);
free_at(0);
}
}
/*
* Inserting a new item to the exact position
*/
void
cl_list::add_at(t_index index, void *item)
{
if (index < 0 )
error(1, 0);
if (count == Limit)
set_limit(count + Delta);
/*{
char s[1000];
s[0]='\0';
sprintf(s, "%s add_at(%d,%p) PC=0x%x (count=%d)", get_name("?"), index, item,
application?
((application->sim)?
((application->sim->uc)?(application->sim->uc->PC):
-3):
-1):
-2, count);
strcat(s,"\n");
}*/
memmove(&Items[index+1], &Items[index], (count-index)*sizeof(void *));
count++;
Items[index]= item;
}
/*
* Put a new item to the collection. This function replaces an existing
* item with a new one but it does not delete or dispose the old item!
*/
void
cl_list::put_at(t_index index, void *item)
{
if (index >= count)
error(1, 0);
Items[index]= item;
}
/*
* Action taken when an error occure
*/
void
cl_list::error(t_index code, t_index info)
{
fprintf(stderr,
"Collection index error. Code= %d, Info= %d.\n",
code, info);
exit(code);
}
/*
* Iterator method. This function calls 'Test' using every items as Test's
* argument until Test returns TRUE.
*/
void *
cl_list::first_that(match_func test, void *arg)
{
for (t_index i= 0; i < count; i++)
{
if (test(Items[i], arg)) return(Items[i]);
}
return(0);
}
/*
* Iterator method. This function calls 'Action' using every items as
* Action's argument.
*/
void
cl_list::for_each(iterator_func action, void *arg)
{
for(t_index i= 0; i < count; i++)
action(Items[i], arg);
}
/*
* Disposing an item.
*/
void
cl_list::free_item(void *item)
{
delete (class cl_base*)item;
}
/*
* Get the number of collected items.
*/
int
cl_list::get_count(void)
{
return(count);
}
void *
cl_list::pop(void)
{
void *i;
if (!count)
return(0);
i= Items[0];
disconn_at(0);
return(i);
}
void *
cl_list::top(void)
{
if (!count)
return(0);
return(Items[0]);
}
/*
* Returning the index of an item.
*/
t_index
cl_list::index_of(void *item)
{
for (t_index i= 0; i < count; i++)
if (item == Items[i])
return(i);
error(1, 0);
return(0); /* Needed by Sun! */
}
bool
cl_list::index_of(void *item, t_index *idx)
{
for (t_index i= 0; i < count; i++)
if (item == Items[i])
{
if (idx)
*idx= i;
return(true);
}
return(false);
}
void *
cl_list::next(void *item)
{
for (t_index i= 0; i < count; i++)
if (item == Items[i])
{
if (count >= 2 &&
i < count-1)
return(Items[i+1]);
}
return(0);
}
/*
* Inserting a new item to the collection.
*/
t_index
cl_list::add(void *item)
{
t_index loc= count;
add_at(count, item);
return(loc);
}
t_index
cl_list::add(class cl_base *item, class cl_base *parent)
{
if (parent && item)
parent->add_child(item);
return(add(item));
}
void
cl_list::push(void *item)
{
if (count)
add_at(0, item);
else
add(item);
}
/*
* Iterator method. This function calls 'Test' using every items
* (in reversed order) as Test's argument until Test returns TRUE.
*/
void *
cl_list::last_that(match_func test, void *arg)
{
for(t_index i= count; i > 0; i--)
if (test(Items[i-1], arg))
return(Items[i-1]);
return(0);
}
/*
* ???
*/
/*void
cl_list::pack(void)
{
void **CurDst= Items;
void **CurSrc= Items;
void **Last = Items + count;
while (CurSrc < Last)
{
if (*CurSrc != 0)
*CurDst++= *CurSrc;
*CurSrc++;
}
}*/
/*
* Setting up the maximum number of items. This function may expand
* the size of the collection.
*/
void
cl_list::set_limit(t_index alimit)
{
void **AItems;
if (alimit < count)
alimit= count;
if (alimit > (int)max_list_size)
alimit= max_list_size;
if (alimit != Limit)
{
if (alimit == 0)
AItems= 0;
else
{
//AItems = new void *[alimit];
int i= alimit*(sizeof(void *));
AItems= (void **)malloc(i);
if (count)
memcpy(AItems, Items, count*sizeof(void *));
}
//delete Items;
if (Items)
free(Items);
Items= AItems;
Limit= alimit;
}
}
/* *
==========================================================================*
cl_sorted_list *
==========================================================================*
*
*/
/*
* Initilizing the sorted collection
*/
cl_sorted_list::cl_sorted_list(t_index alimit, t_index adelta, char *aname):
cl_list(alimit, adelta, aname)
{
Duplicates= false;
}
cl_sorted_list::cl_sorted_list(t_index alimit, t_index adelta, const char *aname):
cl_list(alimit, adelta, aname)
{
Duplicates= false;
}
cl_sorted_list::~cl_sorted_list(void) {}
/*
* Get the address of the key field in an item.
*/
void *
cl_sorted_list::key_of(void *item)
{
return(item);
}
/*
* Get index of an item.
*/
t_index
cl_sorted_list::index_of(void *item)
{
t_index i;
if (search(key_of(item), i) == 0)
return(ccNotFound);
else
{
if (Duplicates)
while (i < count &&
item != Items[i])
i++;
if (i < count)
return(i);
else
return(ccNotFound);
}
}
/*
* Inserting a new item to the collection
*/
t_index
cl_sorted_list::add(void *item)
{
t_index i;
if (search(key_of(item), i) == 0 ||
Duplicates) // order dependency!
add_at(i, item); // must do Search
// before calling
// AtInsert
return(i);
}
/*
* Searching an item using binary search.
*/
bool
cl_sorted_list::search(void *key, t_index &index)
{
t_index l = 0;
t_index h = count - 1;
bool res= false;
while (l <= h)
{
t_index i= (l + h) >> 1;
t_index c= compare(key_of(Items[i]), key);
if (c < 0) l= i + 1;
else
{
h= i - 1;
if (c == 0)
{
res= true;
if (!Duplicates)
l= i;
}
}
}
index= l;
return(res);
}
/* *
==========================================================================*
cl_strings *
==========================================================================*
*
*/
/*
* Initilizing the string collection
*/
cl_strings::cl_strings(t_index alimit, t_index adelta, char *aname):
cl_sorted_list(alimit, adelta, aname)
{
Duplicates= true;
}
cl_strings::cl_strings(t_index alimit, t_index adelta, const char *aname):
cl_sorted_list(alimit, adelta, aname)
{
Duplicates= true;
}
cl_strings::~cl_strings(void) {}
/*
* Comapare two string from the collection
*/
int
cl_strings::compare(void *key1, void *key2)
{
return(strcmp((char *)key1, (char *)key2));
}
/*
* Deallocate string item of the collection
*/
void
cl_strings::free_item(void* item)
{
delete (char*)item;
}
/* *
==========================================================================*
cl_ustrings *
==========================================================================*
*
*/
/*
* Initilizing the unsorted string collection
*/
cl_ustrings::cl_ustrings(t_index alimit, t_index adelta, char *aname):
cl_strings(alimit, adelta, aname)
{}
cl_ustrings::cl_ustrings(t_index alimit, t_index adelta, const char *aname):
cl_strings(alimit, adelta, aname)
{}
cl_ustrings::~cl_ustrings(void) {}
/*
* Comapare two string from the collection
*/
int
cl_ustrings::compare(void *key1, void *key2)
{
return(-1);
}
/*
* Searching an item using linear search.
*/
bool
cl_ustrings::search(void *key, t_index& index)
{
t_index i = 0;
bool found= false;
void *Actual;
if ((count) && key)
{
while (!found && (i < count))
{
Actual= key_of(at(i));
found = (Actual != 0) &&
(compare(key, Actual) == 0);
i++;
}
}
if (found)
index= i-1;
else
index= count;
return(found);
}
/* End of pobj.cc */