/* asmitree.c */
/*****************************************************************************/
/* 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)
BEGIN
   PInstTreeNode p1,p2;
   Boolean Result=False;

   ChkStack();

   if (*Node==Nil)
    BEGIN
     *Node=(PInstTreeNode) malloc(sizeof(TInstTreeNode));
     (*Node)->Left=Nil; (*Node)->Right=Nil; 
     (*Node)->Proc=NProc; (*Node)->Index=NIndex;
     (*Node)->Balance=0;
     (*Node)->Name=strdup(NName);
     Result=True;
    END
   else if (strcmp(NName,(*Node)->Name)<0)
    BEGIN
     if (AddSingle(&((*Node)->Left),NName,NProc,NIndex))
      switch ((*Node)->Balance)
       BEGIN
        case 1:
         (*Node)->Balance=0;
         break;
        case 0:
         (*Node)->Balance=(-1);
         Result=True;
         break;
        case -1:
         p1=(*Node)->Left;
         if (p1->Balance==-1)
          BEGIN
           (*Node)->Left=p1->Right; p1->Right=(*Node);
           (*Node)->Balance=0; *Node=p1;
          END
         else
          BEGIN
           p2=p1->Right;
           p1->Right=p2->Left; p2->Left=p1;
           (*Node)->Left=p2->Right; p2->Right=(*Node);
           if (p2->Balance==-1) (*Node)->Balance=   1; else (*Node)->Balance=0;
           if (p2->Balance== 1) p1     ->Balance=(-1); else p1     ->Balance=0;
           *Node=p2;
          END
         (*Node)->Balance=0;
         break;
       END
    END
   else
    BEGIN
     if (AddSingle(&((*Node)->Right),NName,NProc,NIndex))
      switch ((*Node)->Balance)
       BEGIN
        case -1:
         (*Node)->Balance=0;
         break;
        case 0:
         (*Node)->Balance=1;
         Result=True;
         break;
        case 1:
         p1=(*Node)->Right;
         if (p1->Balance==1)
          BEGIN
           (*Node)->Right=p1->Left; p1->Left=(*Node);
           (*Node)->Balance=0; *Node=p1;
          END
         else
          BEGIN
           p2=p1->Left;
           p1->Left=p2->Right; p2->Right=p1;
           (*Node)->Right=p2->Left; p2->Left=(*Node);
           if (p2->Balance== 1) (*Node)->Balance=(-1); else (*Node)->Balance=0;
           if (p2->Balance==-1) p1     ->Balance=   1; else p1     ->Balance=0;
           *Node=p2;
          END
         (*Node)->Balance=0;
         break;
       END
    END
   return Result;
END

        void AddInstTree(PInstTreeNode *Root, char *NName, InstProc NProc, Word NIndex)
BEGIN
   AddSingle(Root,NName,NProc,NIndex);
END

        static void ClearSingle(PInstTreeNode *Node)
BEGIN
   ChkStack();

   if (*Node!=Nil)
    BEGIN
     free((*Node)->Name);
     ClearSingle(&((*Node)->Left));
     ClearSingle(&((*Node)->Right));
     free(*Node); *Node=Nil;
    END
END

        void ClearInstTree(PInstTreeNode *Root)
BEGIN
   ClearSingle(Root);
END

        Boolean SearchInstTree(PInstTreeNode Root, char *OpPart)
BEGIN
   int z;

   z=0;
   while ((Root!=Nil) AND (strcmp(Root->Name,OpPart)!=0))
    BEGIN
     Root=(strcmp(OpPart,Root->Name)<0)? Root->Left : Root->Right;
     z++;
    END

   if (Root==Nil) return False;
   else
    BEGIN
     Root->Proc(Root->Index);
     return True;
    END
END

	static void PNode(PInstTreeNode Node, Word Lev)
BEGIN
   ChkStack();
   if (Node!=Nil)
    BEGIN
     PNode(Node->Left,Lev+1);
     printf("%*s %s %p %p %d\n",5*Lev,"",Node->Name,Node->Left,Node->Right,Node->Balance);
     PNode(Node->Right,Lev+1);
    END
END

	void PrintInstTree(PInstTreeNode Root)
BEGIN
   PNode(Root,0);
END

/*----------------------------------------------------------------------------*/

    static int GetKey(char *Name, LongWord TableSize)
BEGIN
   register unsigned char *p;
   LongWord tmp=0;

   for (p=(unsigned char *)Name; *p!='\0'; p++) tmp=(tmp<<2)+((LongWord)*p);
   return tmp%TableSize;
END

	PInstTable CreateInstTable(int TableSize)
BEGIN
   int z;
   PInstTableEntry tmp;
   PInstTable tab;
   
   tmp=(PInstTableEntry) malloc(sizeof(TInstTableEntry)*TableSize);
   for (z=0; z<TableSize; z++) tmp[z].Name=Nil;
   tab=(PInstTable) malloc(sizeof(TInstTable));
   tab->Fill=0; tab->Size=TableSize; tab->Entries=tmp; tab->Dynamic=FALSE;
   return tab;
END

	void SetDynamicInstTable(PInstTable Table)
BEGIN
   Table->Dynamic=TRUE;
END

	void DestroyInstTable(PInstTable tab)
BEGIN
   int z;

   if (tab->Dynamic)
    for (z=0; z<tab->Size; z++)
     free(tab->Entries[z].Name);

   free(tab->Entries);
   free(tab);
END

	void AddInstTable(PInstTable tab, char *Name, Word Index, InstProc Proc)
BEGIN
   LongWord h0=GetKey(Name,tab->Size),z=0;

   /* mindestens ein freies Element lassen, damit der Sucher garantiert terminiert */
 
   if (tab->Size-1<=tab->Fill) exit(255);
   while (1)
    BEGIN
     if (tab->Entries[h0].Name==Nil)
      BEGIN
       tab->Entries[h0].Name=(tab->Dynamic) ? strdup(Name) : Name;
       tab->Entries[h0].Proc=Proc;
       tab->Entries[h0].Index=Index;
       tab->Entries[h0].Coll=z;
       tab->Fill++;
       return;
      END
     z++;
     if ((++h0)==tab->Size) h0=0;
    END
END

	void RemoveInstTable(PInstTable tab, char *Name)
BEGIN
   LongWord h0=GetKey(Name,tab->Size);

   while (1)
    BEGIN
     if (tab->Entries[h0].Name==Nil) return;
     else if (strcmp(tab->Entries[h0].Name,Name)==0)
      BEGIN
       tab->Entries[h0].Name=Nil;
       tab->Entries[h0].Proc=Nil;
       tab->Fill--;
       return;
      END
     if ((++h0)==tab->Size) h0=0;
    END
END

	Boolean LookupInstTable(PInstTable tab, char *Name)
BEGIN
   LongWord h0=GetKey(Name,tab->Size);

   while (1)
    BEGIN
     if (tab->Entries[h0].Name==Nil) return False;
     else if (strcmp(tab->Entries[h0].Name,Name)==0)
      BEGIN
       tab->Entries[h0].Proc(tab->Entries[h0].Index);
       return True;
      END
     if ((++h0)==tab->Size) h0=0;
    END
END

	void PrintInstTable(FILE *stream, PInstTable tab)
BEGIN
   int z;

   for (z=0; z<tab->Size; z++)
    if (tab->Entries[z].Name!=Nil)
     fprintf(stream,"[%3d]: %-10s Index %4d Coll %2d\n",z,tab->Entries[z].Name,tab->Entries[z].Index,tab->Entries[z].Coll);
END

/*----------------------------------------------------------------------------*/ 

	void asmitree_init(void)
BEGIN
END
