903 lines
14 KiB
C++
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 */
|