Blame |
Last modification |
View Log
| Download
| RSS feed
| ?url?
/* asmitree.c */
/*****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Opcode-Abfrage als Binaerbaum */
/* */
/* Historie: 30.10.1996 Grundsteinlegung */
/* 8.10.1997 Hash-Tabelle */
/* 6.12.1998 dynamisches Kopieren der Namen */
/* */
/*****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "chunks.h"
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmitree.h"
/*---------------------------------------------------------------------------*/
static Boolean AddSingle
(PInstTreeNode
*Node
, char *NName
, InstProc NProc
, Word NIndex
)
{
PInstTreeNode p1
, p2
;
Boolean Result
= False
;
ChkStack
();
if (!*Node
)
{
*Node
= (PInstTreeNode
) malloc(sizeof(TInstTreeNode
));
(*Node
)->Left
= NULL
;
(*Node
)->Right
= NULL
;
(*Node
)->Proc
= NProc
;
(*Node
)->Index
= NIndex
;
(*Node
)->Balance
= 0;
(*Node
)->Name
= as_strdup
(NName
);
Result
= True
;
}
else if (strcmp(NName
, (*Node
)->Name
) < 0)
{
if (AddSingle
(&((*Node
)->Left
), NName
, NProc
, NIndex
))
switch ((*Node
)->Balance
)
{
case 1:
(*Node
)->Balance
= 0;
break;
case 0:
(*Node
)->Balance
= -1;
Result
= True
;
break;
case -1:
p1
= (*Node
)->Left
;
if (p1
->Balance
== -1)
{
(*Node
)->Left
= p1
->Right
;
p1
->Right
= (*Node
);
(*Node
)->Balance
= 0;
*Node
= p1
;
}
else
{
p2
= p1
->Right
;
p1
->Right
= p2
->Left
;
p2
->Left
= p1
;
(*Node
)->Left
= p2
->Right
;
p2
->Right
= (*Node
);
(*Node
)->Balance
= (p2
->Balance
== -1) ? 1 : 0;
p1
->Balance
= (p2
->Balance
== 1) ? -1 : 0;
*Node
= p2
;
}
(*Node
)->Balance
= 0;
break;
}
}
else
{
if (AddSingle
(&((*Node
)->Right
), NName
, NProc
, NIndex
))
switch ((*Node
)->Balance
)
{
case -1:
(*Node
)->Balance
= 0;
break;
case 0:
(*Node
)->Balance
= 1;
Result
= True
;
break;
case 1:
p1
= (*Node
)->Right
;
if (p1
->Balance
== 1)
{
(*Node
)->Right
= p1
->Left
;
p1
->Left
= (*Node
);
(*Node
)->Balance
= 0;
*Node
= p1
;
}
else
{
p2
= p1
->Left
;
p1
->Left
= p2
->Right
;
p2
->Right
= p1
;
(*Node
)->Right
= p2
->Left
;
p2
->Left
= (*Node
);
(*Node
)->Balance
= (p2
->Balance
== 1) ? -1 : 0;
p1
->Balance
= (p2
->Balance
== -1) ? 1 : 0;
*Node
= p2
;
}
(*Node
)->Balance
= 0;
break;
}
}
return Result
;
}
void AddInstTree
(PInstTreeNode
*Root
, char *NName
, InstProc NProc
, Word NIndex
)
{
AddSingle
(Root
, NName
, NProc
, NIndex
);
}
static void ClearSingle
(PInstTreeNode
*Node
)
{
ChkStack
();
if (*Node
)
{
free((*Node
)->Name
);
ClearSingle
(&((*Node
)->Left
));
ClearSingle
(&((*Node
)->Right
));
free(*Node
);
*Node
= NULL
;
}
}
void ClearInstTree
(PInstTreeNode
*Root
)
{
ClearSingle
(Root
);
}
Boolean SearchInstTree
(PInstTreeNode Root
, char *OpPart
)
{
while (Root
)
{
int cmp_res
= strcmp(OpPart
, Root
->Name
);
if (!cmp_res
)
break;
Root
= (cmp_res
< 0) ? Root
->Left
: Root
->Right
;
}
if (!Root
)
return False
;
else
{
Root
->Proc
(Root
->Index
);
return True
;
}
}
static void PNode
(PInstTreeNode Node
, Word Lev
)
{
ChkStack
();
if (Node
)
{
PNode
(Node
->Left
, Lev
+ 1);
printf("%*s %s %p %p %d\n", 5 * Lev
, "", Node
->Name
, (void*)Node
->Left
, (void*)Node
->Right
, Node
->Balance
);
PNode
(Node
->Right
, Lev
+ 1);
}
}
void PrintInstTree
(PInstTreeNode Root
)
{
PNode
(Root
, 0);
}
/*----------------------------------------------------------------------------*/
static int GetKey
(const char *Name
, LongWord TableSize
)
{
register unsigned char *p
;
LongWord tmp
= 0;
for (p
= (unsigned char *)Name
; *p
!= '\0'; p
++)
tmp
= (tmp
<< 2) + ((LongWord
)*p
);
return tmp
% TableSize
;
}
PInstTable CreateInstTable
(int TableSize
)
{
int z
;
PInstTableEntry tmp
;
PInstTable tab
;
tmp
= (PInstTableEntry
) malloc(sizeof(TInstTableEntry
) * TableSize
);
for (z
= 0; z
< TableSize
; z
++)
tmp
[z
].
Name = NULL
;
tab
= (PInstTable
) malloc(sizeof(TInstTable
));
tab
->Fill
= 0;
tab
->Size
= TableSize
;
tab
->Entries
= tmp
;
tab
->Dynamic
= FALSE
;
return tab
;
}
/*!------------------------------------------------------------------------
* \fn inst_fnc_table_create(int table_size)
* \brief create new instance of function table
* \param table_size max. # of entries in table
* \return * to table
* ------------------------------------------------------------------------ */
inst_fnc_table_t
*inst_fnc_table_create
(int table_size
)
{
int z
;
inst_fnc_table_entry_t
*p_entries
= NULL
;
inst_fnc_table_t
*p_ret
= NULL
;
p_entries
= (inst_fnc_table_entry_t
*)calloc(table_size
, sizeof(*p_entries
));
if (!p_entries
)
goto func_exit
;
for (z
= 0; z
< table_size
; z
++)
p_entries
[z
].
p_name = NULL
;
p_ret
= (inst_fnc_table_t
*) calloc(1, sizeof(*p_ret
));
if (!p_ret
)
goto func_exit
;
p_ret
->fill
= 0;
p_ret
->size
= table_size
;
p_ret
->p_entries
= p_entries
; p_entries
= NULL
;
p_ret
->dynamic
= False
;
func_exit
:
if (p_entries
)
free(p_entries
);
return p_ret
;
}
void SetDynamicInstTable
(PInstTable Table
)
{
Table
->Dynamic
= TRUE
;
}
void DestroyInstTable
(PInstTable tab
)
{
int z
;
if (tab
->Dynamic
)
for (z
= 0; z
< tab
->Size
; z
++)
free(tab
->Entries
[z
].
Name);
free(tab
->Entries
);
free(tab
);
}
void AddInstTable
(PInstTable tab
, const char *Name
, Word Index
, InstProc Proc
)
{
LongWord h0
= GetKey
(Name
, tab
->Size
), z
= 0;
/* mindestens ein freies Element lassen, damit der Sucher garantiert terminiert */
if (tab
->Size
- 1 <= tab
->Fill
)
{
fprintf(stderr
, "\nhash table overflow\n");
exit(255);
}
while (1)
{
if (!tab
->Entries
[h0
].
Name)
{
tab
->Entries
[h0
].
Name = (tab
->Dynamic
) ? as_strdup
(Name
) : (char*)Name
;
tab
->Entries
[h0
].
Proc = Proc
;
tab
->Entries
[h0
].
Index = Index
;
tab
->Entries
[h0
].
Coll = z
;
tab
->Fill
++;
return;
}
if (!strcmp(tab
->Entries
[h0
].
Name, Name
))
{
printf("%s double in table\n", Name
);
exit(255);
}
z
++;
if ((LongInt
)(++h0
) == tab
->Size
)
h0
= 0;
}
}
/*!------------------------------------------------------------------------
* \fn inst_fnc_table_add(inst_fnc_table_t *p_table, const char *p_name, Word index, inst_fnc_t fnc)
* \brief augment table by one entry
* \param p_table table to add to
* \param p_name name of instruction
* \param index callback argument
* \param fnc callback itself
* ------------------------------------------------------------------------ */
void inst_fnc_table_add
(inst_fnc_table_t
*p_table
, const char *p_name
, Word index
, inst_fnc_t fnc
)
{
LongWord tab_index
= GetKey
(p_name
, p_table
->size
), num_coll
= 0;
/* mindestens ein freies Element lassen, damit der Sucher garantiert terminiert */
if (p_table
->size
- 1 <= p_table
->fill
)
{
fprintf(stderr
, "\nhash table overflow\n");
exit(255);
}
while (1)
{
if (!p_table
->p_entries
[tab_index
].
p_name)
{
p_table
->p_entries
[tab_index
].
p_name = (p_table
->dynamic
) ? as_strdup
(p_name
) : (char*)p_name
;
p_table
->p_entries
[tab_index
].
fnc = fnc
;
p_table
->p_entries
[tab_index
].
index = index
;
p_table
->p_entries
[tab_index
].
coll = num_coll
;
p_table
->fill
++;
return;
}
if (!strcmp(p_table
->p_entries
[tab_index
].
p_name, p_name
))
{
printf("%s double in table\n", p_name
);
exit(255);
}
num_coll
++;
if ((LongInt
)(++tab_index
) == p_table
->size
)
tab_index
= 0;
}
}
void RemoveInstTable
(PInstTable tab
, const char *Name
)
{
LongWord h0
= GetKey
(Name
, tab
->Size
);
while (1)
{
if (!tab
->Entries
[h0
].
Name)
return;
else if (!strcmp(tab
->Entries
[h0
].
Name, Name
))
{
tab
->Entries
[h0
].
Name = NULL
;
tab
->Entries
[h0
].
Proc = NULL
;
tab
->Fill
--;
return;
}
if ((LongInt
)(++h0
) == tab
->Size
)
h0
= 0;
}
}
Boolean LookupInstTable
(PInstTable tab
, const char *Name
)
{
LongWord h0
= GetKey
(Name
, tab
->Size
);
while (1)
{
if (!tab
->Entries
[h0
].
Name)
return False
;
else if (!strcmp(tab
->Entries
[h0
].
Name, Name
))
{
tab
->Entries
[h0
].
Proc(tab
->Entries
[h0
].
Index);
return True
;
}
if ((LongInt
)(++h0
) == tab
->Size
)
h0
= 0;
}
}
/*!------------------------------------------------------------------------
* \fn inst_fnc_table_lookup(const inst_fnc_table_t *p_table, const char *p_name)
* \brief look up & execute instruction callback
* \param p_table table with functions
* \param p_name instruction name
* \return True if callback was found and executed
* ------------------------------------------------------------------------ */
Boolean inst_fnc_table_lookup
(const inst_fnc_table_t
*p_table
, const char *p_name
)
{
LongWord index
= GetKey
(p_name
, p_table
->size
);
while (1)
{
if (!p_table
->p_entries
[index
].
p_name)
return False
;
else if (!strcmp(p_table
->p_entries
[index
].
p_name, p_name
))
return p_table
->p_entries
[index
].
fnc(p_table
->p_entries
[index
].
index);
if ((LongInt
)(++index
) == p_table
->size
)
index
= 0;
}
}
void PrintInstTable
(FILE
*stream
, PInstTable tab
)
{
int z
;
for (z
= 0; z
< tab
->Size
; z
++)
if (tab
->Entries
[z
].
Name)
fprintf(stream
, "[%3d]: %-10s Index %4d Coll %2d\n", z
,
tab
->Entries
[z
].
Name, tab
->Entries
[z
].
Index, tab
->Entries
[z
].
Coll);
}
/*----------------------------------------------------------------------------*/
void asmitree_init
(void)
{
}