{$A+,B-,D+,E-,F-,G-,I-,L+,N-,O-,R-,S-,V-,X-}
{$IFDEF VER70}
{$P-,Q-,T-}
{$ENDIF}
unit
  Table;

interface
  uses
    tpString;

const
  sfOk        = $0000;
  sfNoMemory  = $0001;
  sfOverflow  = $0002;
  sfNotFound  = $0004;

const
  NumOp   =  211;
  MaxSym  =  500;
  Predef  =   29;  { number of predefined symbols }

var
  NumSym   : Integer; { current number of symbols }

type
  AsmEntryPtr = ^AsmEntry;
  AsmEntry = record
    OpCode  : Word;
    DstType : Word;
    SrcType : Word;
    Flags   : Word;
    Name    : pointer;
  end;
  AsmArrayPtr = ^AsmArray;
  AsmArray = array[1..NumOp] of AsmEntryPtr;

  AsmTablePtr = ^AsmTable;
  AsmTable = object
    Declared : Word;
    Elements : Word;
    Status   : Word;
    APtr     : AsmArrayPtr;
    constructor Init(NElements:Word);
    destructor Done; virtual;
    function Put(_Code: Word; _Name:String; _DType,_SType,_Flags:Word) :Word;
    function Get(No:Word; var _Code: Word; var _Name:String; var _DType,_SType,_Flags:Word) :Word;
    function OpCode(No : Word) : Word;
  end;

type
  SymEntryPtr = ^SymEntry;
  SymEntry = record
    Val1    : Word;
    Val2    : Word;
    SymType : Word;
    Name    : pointer;
  end;
  SymArrayPtr = ^SymArray;
  SymArray = array[1..MaxSym] of SymEntryPtr;

  SymTablePtr = ^SymTable;
  SymTable = object
    Declared : Word;
    Elements : Word;
    Status   : Word;
    SPtr     : SymArrayPtr;
    constructor Init(NElements: Word);
    destructor Done; virtual;
    function Put(_Val1,_Val2,_SymType : Word; _Name : String): Word;
    function Get(No: Word; var _Val1,_Val2,_SymType : Word; var _Name : String): Word;
  end;

implementation

function GetMemCheck(var P; Size : Word) : Boolean;
var
  Pt : pointer absolute P;
begin
  GetMemCheck := FALSE;
  if LongInt(Size) > MaxAvail then
    exit;
  GetMem(Pt,Size);
  GetMemCheck := TRUE;
end; { GetMemCheck }

{ =============== ASMTABLE ====================}
constructor AsmTable.Init;
begin
  Elements := 0;
  Status := sfNoMemory;
  if NElements > NumOp then
    Fail;
  if NOT GetMemCheck(APtr,NElements*sizeof(pointer)) then
    Fail;
  Status := sfOk;
  Declared := NElements;
  FillChar(Aptr^,NElements*sizeof(pointer),0);
end; { AsmTable.Init }

destructor AsmTable.Done;
var
  I : Word;
begin
  for I := 1 to Elements do
    FreeMem(Aptr^[I],sizeof(AsmEntry));
  FreeMem(APtr,Declared*sizeof(pointer));
end; { AsmTable.Done }

function AsmTable.Put;
begin
  Inc(Elements);
  if Elements > Declared then begin
    Put:= 0;
    Status := sfOverflow;
    exit;
  end;
  if NOT GetMemCheck(APtr^[Elements],sizeof(AsmEntry)) then begin
    Put := 0;
    Status := sfNoMemory;
    exit;
  end;
  with APtr^[Elements]^ do begin
    OpCode  := _Code;
    DstType := _DType;
    SrcType := _SType;
    Flags   := _Flags;
    Name    := StringToHeap(_Name);
  end;
  Put := Elements;
end; { AsmTable.Put }

function AsmTable.Get;
begin
  if No > Elements then begin
    Get := 0;
    Status := sfNotFound;
    exit;
  end;
  with APtr^[No]^ do begin
    _Code  := OpCode;
    _DType := DstType;
    _SType := SrcType;
    _Flags := Flags;
    _Name  := StringFromHeap(Name);
  end;
  Get := Elements;
end; { AsmTable.Get }

function AsmTable.Opcode;
begin
  OpCode := Aptr^[No]^.OpCode;
end;

{ =============== SYMTABLE ====================}
constructor SymTable.Init;
begin
  Elements := 0;
  Status := sfNoMemory;
  if NElements > MaxSym then
    Fail;
  if NOT GetMemCheck(SPtr,NElements*sizeof(pointer)) then
    Fail;
  Status := sfOk;
  Declared := NElements;
  FillChar(Sptr^,NElements*sizeof(pointer),0);
end; { SymTable.Init }

destructor SymTable.Done;
var
  I : Word;
begin
  for I := 1 to Elements do
    FreeMem(SPtr^[I],sizeof(AsmEntry));
  FreeMem(SPtr,Declared*sizeof(pointer));
end; { SymTable.Done }

function SymTable.Put;
begin
  Inc(Elements);
  if Elements > Declared then begin
    Put:= 0;
    Status := sfOverflow;
    exit;
  end;
  if NOT GetMemCheck(SPtr^[Elements],sizeof(SymEntry)) then begin
    Put := 0;
    Status := sfNoMemory;
    exit;
  end;
  with SPtr^[Elements]^ do begin
    Val1    := _Val1;
    Val2    := _Val2;
    SymType := _SymType;
    Name    := StringToHeap(_Name);
  end;
  NumSym := Integer(Elements);
  Put := Elements;
end; { SymTable.Put }

function SymTable.Get;
begin
  if No > Elements then begin
    Get := 0;
    Status := sfNotFound;
    exit;
  end;
  with SPtr^[No]^ do begin
    _Val1  := Val1;
    _Val2  := Val2;
    _SymType := SymType;
    _Name  := StringFromHeap(Name);
  end;
  Get := Elements;
end; { SymTable.Get }

end.