home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 16 / CD_ASCQ_16_0994.iso / maj / swag / pointers.swg < prev    next >
Text File  |  1994-08-29  |  138KB  |  2 lines

  1. SWAGOLX.EXE (c) 1993 GDSOFT  ALL RIGHTS RESERVED 00028         POINTERS, LINKING, LISTS, TREES                                   1      05-28-9313:54ALL                      SWAG SUPPORT TEAM        DLLIST1.PAS              IMPORT              9      ╙═√d { > Does anybody have any good source/Units For Turboπ > Pascal 6.0/7.0 For doing Double Linked List Fileπ > structures?π}ππTypeππ   DLinkPtr = ^DLinkRecord;ππ   DLinkRecord = Recordπ      Data     : Integer;π      Next     : DLinkPtr;π      Last     : DLinkPtr;π     end;ππVarπ  Current,π  First,π  Final,π  Prev    : DLinkPtr;π  X       : Byte;ππProcedure AddNode;πbeginπ  if First = Nil thenπ   beginπ     New(Current);π     Current^.Next:=Nil;π     Current^.Last:=Nil;π     Current^.Data:=32;π     First:=Current;π     Final:=Current;π   endπ  elseπ   beginπ    Prev:=Current;π    New(Current);π    Current^.Next:=Nil;π    Current^.Last:=Prev;π    Current^.Data:=54;π    Prev^.Next:=Current;π    Final:=Current;π   end;πend;ππbeginπ  First:=Nil;π  For X:=1 to 10 Do AddNode;π  Writeln('First: ',first^.data);π  Writeln('Final: ',final^.data);π  Writeln('Others:');π  Writeln(first^.next^.data);ππend.π                                                                                                                       2      05-28-9313:54ALL                      SWAG SUPPORT TEAM        LINKLIST.PAS             IMPORT              63     ╙═╖─ {πThe following is the LinkList Unit written by Peter Davis in his wonderfulπbut, unFortunately, short-lived newsletter # PNL002.ZIP.  I have used thisπUnit to Write tests of three or four of the Procedures but have stumped my toeπon his DELETE_HERE Procedure, the last one in the Unit.  I will post my testsπin the next message For any who may wish to see it:  Pete's Unit is unmodified.π I almost think there is some kind of error in DELETE_HERE but he was tooπthorough For that.  Can you, or someone seeing this show me how to use thisπProcedure?  It will help me both With Pointers and With Units.ππHere is the Unit:π}ππUnit LinkList;ππ{ This is the linked list Unit acCompanying The Pascal NewsLetter, Issue #2.π  This Unit is copyrighted by Peter Davis.π  It may be freely distributed in un-modified Form, or modified For use inπ  your own Programs. Programs using any modified or unmodified Form of thisπ(107 min left), (H)elp, More?   Unit must include a run-time and source visible recognition of the author,π  Peter Davis.π}ππ{ The DataType used is Integer, but may be changed to whatever data Typeπ  that you want.π}ππInterfaceπππTypeπ  DataType = Integer;    { Change this data-Type to whatever you want  }ππ  Data_Ptr = ^Data_Rec;  { Pointer to our data Records                 }ππ  Data_Rec = Record      { Our Data Record Format                      }π    OurData  : DataType;π    Next_Rec : Data_Ptr;π  end;πππProcedure Init_List(Var Head : Data_Ptr);πProcedure Insert_begin(Var Head : Data_Ptr; Data_Value : DataType);πProcedure Insert_end(Var Head : Data_Ptr; Data_Value : DataType);πProcedure Insert_In_order(Var Head : Data_Ptr; Data_Value : DataType);πFunction Pop_First(Var Head : Data_Ptr) : DataType;πFunction Pop_Last(Var Head : Data_Ptr) : DataType;πProcedure Delete_Here(Var Head : Data_Ptr; Our_Rec : Data_Ptr);ππππImplementationππProcedure Init_List(Var Head : Data_Ptr);ππbeginπ  Head := nil;πend;ππProcedure Insert_begin(Var Head : Data_Ptr; Data_Value : DataType);ππ{ This Procedure will insert a link and value into theπ  beginning of a linked list.                             }ππVarπ  Temp : Data_Ptr;                { Temporary  Pointer.            }ππbeginπ  new(Temp);                      { Allocate our space in memory.  }π  Temp^.Next_Rec := Head;         { Point to existing list.        }π  Head:= Temp;                    { Move head to new data item.    }π  Head^.OurData := Data_Value;    { Insert Data_Value.             }πend;ππProcedure Insert_end(Var Head : Data_Ptr; Data_Value : DataType);ππ{ This Procedure will insert a link and value into theπ  end of the linked list.                                 }ππVarπ  Temp1,             { This is where we're going to put new data }π  Temp2 : Data_Ptr;  { This is to move through the list.         }ππbeginπ  new(Temp1);π  Temp2 := Head;π  if Head=nil thenπ    beginπ      Head := Temp1;                  { if list is empty, insert first   }π      Head^.OurData := Data_Value;    { and only Record. Add value and   }π      Head^.Next_Rec := nil;          { then put nil in Next_Rec Pointer }π    endπ  elseπ    beginπ      { Go to the end of the list. Since Head is a Variable parameter,π        we can't move it through the list without losing Pointer to theπ        beginning of the list. to fix this, we use a third Variable:π        Temp2.π      }π      While Temp2^.Next_Rec <> nil do    { Find the end of the list. }π        Temp2 := Temp2^.Next_Rec;ππ      Temp2^.Next_Rec := Temp1;          { Insert as last Record.    }π      Temp1^.Next_Rec := nil;            { Put in nil to signify end }π      Temp1^.OurData := Data_Value;      { and, insert the data      }π    end;πend;ππProcedure Insert_In_order(Var Head : Data_Ptr; Data_Value : DataType);ππ{ This Procedure will search through an ordered linked list, findπ  out where the data belongs, and insert it into the list.        }ππVarπ  Current,              { Where we are in the list               }π  Next     : Data_Ptr;  { This is what we insert our data into.  }ππbeginπ  New(Next);π  Current := Head;      { Start at the top of the list.          }ππ  if Head = Nil thenπ    beginπ      Head:= Next;π      Head^.OurData := Data_Value;π      Head^.Next_Rec := Nil;π    endπ  elseπ  { Check to see if it comes beFore the first item in the list   }π  if Data_Value < Current^.OurData thenπ    beginπ      Next^.Next_Rec := Head;      { Make the current first come after Next }π      Head := Next;                { This is our new head of the list       }π      Head^.OurData := Data_Value; { and insert our data value.             }π    endπ  elseπ    beginπ      { Here we need to go through the list, but always looking one stepπ        ahead of where we are, so we can maintain the links. The methodπ        we'll use here is: looking at Current^.Next_Rec^.OurDataπ        A way to explain that in english is "what is the data pointed toπ        by Pointer Next_Rec, in the Record pointed to by Pointerπ        current." You may need to run that through your head a few timesπ        beFore it clicks, but hearing it in English might make it a bitπ        easier For some people to understand.                            }ππ      While (Data_Value >= Current^.Next_Rec^.OurData) andπ            (Current^.Next_Rec <> nil) doπ        Current := Current^.Next_Rec;π      Next^.OurData := Data_Value;π      Next^.Next_Rec := Current^.Next_Rec;π      Current^.Next_Rec := Next;π    end;πend;ππFunction Pop_First(Var Head : Data_Ptr) : DataType;ππ{ Pops the first item off the list and returns the value to the caller. }ππVarπ  Old_Head : Data_Ptr;ππbeginπ  if Head <> nil then   { Is list empty? }π    beginπ      Old_Head := Head;π      Pop_First := Head^.OurData;  { Nope, so Return the value }π      Head := Head^.Next_Rec;      { and increment head.       }π      Dispose(Old_Head);           { Get rid of the old head.  }π    endπ  elseπ    beginπ      Writeln('Error: Tried to pop an empty stack!');π      halt(1);π    end;πend;πππFunction Pop_Last(Var Head : Data_Ptr) : DataType;ππ{ This Function pops the last item off the list and returns theπ  value of DataType to the caller.                              }ππVarπ  Temp : Data_Ptr;ππbeginπ  Temp := Head;       { Start at the beginning of the list. }π  if head = nil then  { Is the list empty? }π    beginπ      Writeln('Error: Tried to pop an empty stack!');π      halt(1);π    endπ  elseπ  if head^.Next_Rec = Nil then { if there is only one item in list, }π    beginπ      Pop_Last := Head^.OurData;  { Return the value               }π      Dispose(Head);              { Return the memory to the heap. }π      Head := Nil;                { and make list empty.           }π    endπ  elseπ    beginπ      While Temp^.Next_Rec^.Next_Rec <> nil do  { otherwise, find the end }π        Temp := Temp^.Next_rec;π      Pop_Last := Temp^.Next_Rec^.OurData;  { Return the value          }π      Dispose(Temp^.Next_Rec);              { Return the memory to heap }π      Temp^.Next_Rec := nil;                { and make new end of list. }π    end;πend;πππProcedure Delete_Here(Var Head : Data_Ptr; Our_Rec : Data_Ptr);πππ{ Deletes the node Our_Rec from the list starting at Head. The Procedureπ  does check For an empty list, but it assumes that Our_Rec IS in the list.π}ππVarπ  Current : Data_Ptr;  { Used to move through the list. }ππbeginπ  Current := Head;π  if Current = nil then   { Is the list empty? }π    beginπ      Writeln('Error: Cant delete from an empty stack.');π      halt(1);π    endπ  elseπ    begin   { Go through list Until we find the one to delete. }π      While Current^.Next_Rec <> Our_Rec doπ        Current := Current^.Next_Rec;π      Current ^.Next_Rec := Our_Rec^.Next_Rec; { Point around old link. }π      Dispose(Our_Rec);                        { Get rid of the link..  }π    end;πend;πππend.π                                                                                                3      05-28-9313:54ALL                      SWAG SUPPORT TEAM        LL-INSRT.PAS             IMPORT              13     ╙═#t {     The following Program yields output that indicates that I have it set upπcorrectly but With my scanty understanding of exactly how to handle a linkedπlist I would be surprised if it is.  This is one difficult area in which Swanπis not quite as expansive as he might be.ππ        I will appreciate critique and commentary on this if you are anybodyπwould be so kind as to give it:π}ππProgram InsertLink;πUses Crt;ππTypeπ  Str15 = String[15];π  Aptr = ^Link;π  Link = Recordπ       Data : Str15;π       Node : Aptr;π  end;ππVarπ  FirstItem, NewItem, OldItem : Aptr;ππProcedure CreateList;πbeginπ  Writeln('Linked list BEForE insertion of node.');π  Writeln;π  New(FirstItem);π  FirstItem^.Data := 'inSERT ';π  Write(FirstItem^.Data);π  Write('             ');π  New(FirstItem^.Node);π  FirstItem^.Node^.Data := 'HERE';π  Writeln(FirstItem^.Node^.Data);π  FirstItem^.Node^.Node := NIL;πend;ππProcedure InsertALink;πbeginπ  Writeln; Writeln;π  Writeln('Linked list AFTER insertion of node.');π  Writeln;π  Write(FirstItem^.Data);π  New(NewItem);π  NewItem^.Node := OldItem^.Node;π  OldItem^.Node := NewItem;π  FirstItem^.Node^.Data := 'inSERTEDLinK';π  Write(FirstItem^.Node^.Data);π  New(FirstItem^.Node^.Node);π  FirstItem^.Node^.Node^.Data := ' HERE';π  Writeln(FirstItem^.Node^.Node^.Data);π  FirstItem^.Node^.Node^.Node := NIL;πend;ππProcedure DisposeList;πbeginπ  Dispose(FirstItem^.Node^.Node);π  FirstItem^.Node := NIL;πend;ππbeginπ  ClrScr;π  CreateList;π  Writeln;π  InsertALink;π  DisposeList;πend.π                        4      05-28-9313:54ALL                      SWAG SUPPORT TEAM        LL_TEST.PAS              IMPORT              20     ╙═±O {πThis is the test Program that I drew up to test the Procedures in PeteπDavis' LinkList.Pas posted in the previous message.  It could be a little moreπdressed up but it does work and offers some insight, I think, into the use ofπPointers and linked lists:  note that I ran a little manual test to locate aπdesignated Pointer in a given list.  Here it is:π}ππUsesπ  Crt, LinkList;ππVarπ  AList1, AList2, AList3, AList4 : Data_Ptr;π  ANum : DataType;π  Count : Integer;ππbeginπ  ClrScr;π  Init_List(AList1);π  Writeln('Results of inserting links at the beginning of a list: ');π  For Count := 1 to 20 doπ  beginπ    ANum := Count;π    Write(' ',ANum);π    Insert_begin(AList1, ANum); {pay out first link (1) to last (20) like}π                                {a fishing line With #-cards.  You end up}π  end;                          {with 20 in your hand going up to 1}π  Writeln;π  Writeln('Watch - Last link inserted is the highest number.');π  Writeln('You are paying out the list like reeling out a fishing line,');π  Writeln('Foot 1, Foot 2, Foot 3, etc. - last one is Foot 20.');π  Writeln('Now, mentally reel in the line to the fourth number.');π  Writeln(' ',alist1^.Next_Rec^.Next_Rec^.Next_Rec^.OurData);π  Writeln;π  Writeln('Now insert one additional number at beginning of list');π  beginπ    ANum := 21;π    Insert_begin(AList1,ANum);π  end;π  Writeln(' ',AList1^.OurData);π   Writeln;πππ  Init_List(Alist2);π  Writeln('Results of Inserting links in turn at the end of a list: ');π  For Count := 1 to 20 doπ  beginπ    ANum := Count;π    Write(' ',ANum);π    Insert_end(Alist2,ANum);π  end;π  Writeln;π  Writeln('note, just the reverse situation of the process above.');π  Writeln('Reel in the line to the fourth number.');π  Writeln(' ',Alist2^.Next_Rec^.Next_Rec^.Next_Rec^.OurData);π          {We inserted at the end so we are now going out toward the 20}ππππ Init_List(Alist3);π Writeln('Results of Inserting links in turn in orDER');π For Count := 1 to 20 doπ beginπ   Anum := Count;π   Write(' ',ANum);π   Insert_In_order(Alist3,ANum);π end;π Writeln;π Writeln(' ',Alist3^.Next_Rec^.Next_Rec^.Next_Rec^.OurData);ππend.π{π        In Case anybody missed Pete Davis' Linklist Unit in the previousπmessage but may have it in her/his library (PNL002.ZIP) what I was asking isπsome help With writing code to test the Procedure DELETE_HERE which is the lastπProcedure in the Unit.π}                                     5      05-28-9313:54ALL                      SWAG SUPPORT TEAM        OOP-LLST.PAS             IMPORT              90     ╙═û┴ Program Linked;ππTypeπ  FileDescriptor =π    Objectπ      Fpt       : File;π      Name      : String[80];π      HeaderSize: Word;π      RecordSize: Word;π      RecordPtr : Pointer;π      SoftPut   : Boolean;π      IsOpen    : Boolean;π      CurRec    : LongInt;ππ      Constructor Init(Nam : String; Hdr : Word; Size : Word; Buff : Pointer;πPut : Boolean);π      Destructor  Done; Virtual;π      Procedure   OpenFile; Virtual;π      Procedure   CloseFile; Virtual;π      Procedure   GetRecord(Rec : LongInt);π      Procedure   PutRecord(Rec : LongInt);π    end;ππ  FileLable =π    Recordπ      Eof : LongInt;π      MRD : LongInt;π      Act : LongInt;π      Val : LongInt;π      Sync: LongInt;π    end;ππ  LabeledFile =π    Object(FileDescriptor)π      Header : FileLable;ππ      Constructor Init(Nam : String; Size : Word; Buff : Pointer; Put :πBoolean);π      Destructor  Done; Virtual;π      Procedure   OpenFile; Virtual;π      Procedure   CloseFile; Virtual;π      Procedure   WriteHeader;π      Procedure   ReadHeader;π      Procedure   AddRecord;π      Procedure   DelRecord(Rec : LongInt);π    end;ππ  DetailHeaderPtr = ^DetailHeader;π  DetailHeader =π    Recordπ      Master : LongInt;π      Prev   : LongInt;π      Next   : LongInt;π    end;ππ  MasterHeaderPtr = ^MasterHeader;π  MasterHeader =π    Recordπ      First  : LongInt;π      Last   : LongInt;π    end;ππ  DetailFileDetailPtr = ^DetailFileDetail;π  DetailFileDetail =π    Object(LabeledFile)π      Constructor Init(Nam : String; Size : Word; Buff : Pointer; Put :πBoolean);π      Procedure   LinkChain(MR, Last, Curr : LongInt);π      Procedure   DelinkChain(Rec : LongInt);π    end;ππ  DetailFileMaster =π    Object(LabeledFile)π      Constructor Init(Nam : String; Size : Word; Buff : Pointer; Put :πBoolean);π      Procedure   LinkDetail(DF : DetailFileDetailPtr);π      Procedure   DelinkDetail(DF : DetailFileDetailPtr; DR : LongInt);π      Procedure   GetFirst(DF : DetailFileDetailPtr);π      Procedure   GetLast(DF : DetailFileDetailPtr);π      Procedure   GetNext(DF : DetailFileDetailPtr);π      Procedure   GetPrev(DF : DetailFileDetailPtr);π    end;ππ{---------------------------------------------------------------------------}ππConstructor FileDescriptor.Init(Nam : String; Hdr : Word; Size : Word; Buff :π                                Pointer; Put : Boolean);π  beginπ    IsOpen := False;π    Name := Nam;π    HeaderSize := Hdr;π    RecordSize := Size;π    RecordPtr := Buff;π    SoftPut := Put;π    CurRec := -1;π  end;ππDestructor  FileDescriptor.Done;π  beginπ    if SoftPut and (CurRec <> -1) thenπ        PutRecord(CurRec);π    if IsOpen thenπ        CloseFile;π  end;ππProcedure   FileDescriptor.OpenFile;π  beginπ    if IsOpen thenπ        Exit;π    Assign(Fpt,Name);π    {$I-}π    Reset(Fpt,1);π    if IoResult <> 0 thenπ        ReWrite(Fpt,1);π    if IoResult = 0 thenπ        IsOpen := True;π    {$I+}π    CurRec := -1;π  end;ππProcedure   FileDescriptor.CloseFile;π  beginπ    if not IsOpen thenπ        Exit;π    {$I-}π    Close(Fpt);π    if IoResult = 0 thenπ        IsOpen := False;π    {$I+}π    CurRec := -1;π  end;ππProcedure   FileDescriptor.GetRecord(Rec : LongInt);π  Varπ    Result : Word;π  beginπ    if not IsOpen thenπ        Exit;π    if CurRec = Rec thenπ        Exit;π    if SoftPut and (CurRec <> -1) thenπ        PutRecord(CurRec);π    {$I-}π    if Rec = 0 thenπ      beginπ        Seek(Fpt,0);π        if IoResult = 0 thenπ          beginπ            BlockRead(Fpt,RecordPtr^,HeaderSize,Result);π            if (Result <> HeaderSize) or (IoResult <> 0) thenπ                {Error Routine};π          end;π      endπ    elseπ      beginπ        Seek(Fpt,HeaderSize + (Rec - 1) * RecordSize);π        if IoResult = 0 thenπ          beginπ            BlockRead(Fpt,RecordPtr^,RecordSize,Result);π            if (Result <> RecordSize) or (IoResult <> 0) thenπ                {Error Routine};π          end;π      end;π    {$I+}π    CurRec := Rec;π  end;ππProcedure   FileDescriptor.PutRecord(Rec : LongInt);π  Varπ    Result : Word;π  beginπ    if not IsOpen thenπ        Exit;π    {$I-}π    if Rec = 0 thenπ      beginπ        Seek(Fpt,0);π        if IoResult = 0 thenπ          beginπ            BlockWrite(Fpt,RecordPtr^,HeaderSize,Result);π            if (Result <> HeaderSize) or (IoResult <> 0) thenπ                {Error Routine};π          end;π      endπ    elseπ      beginπ        Seek(Fpt,HeaderSize + (Rec - 1) * RecordSize);π        if IoResult = 0 thenπ          beginπ            BlockWrite(Fpt,RecordPtr^,RecordSize,Result);π            if (Result <> RecordSize) or (IoResult <> 0) thenπ                {Error Routine};π          end;π      end;π    CurRec := Rec;π    {$I+}π  end;ππ{---------------------------------------------------------------------------}ππConstructor LabeledFile.Init(Nam : String; Size : Word; Buff : Pointer; Put :πBoolean);π  beginπ    if Size < 4 thenπ      beginπ        WriteLN('Record size must be 4 or larger');π        Fail;π      end;π    FileDescriptor.Init(Nam,Sizeof(Header),Size,Buff,Put);π    Header.Eof := 0;π    Header.MRD := 0;π    Header.Act := 0;π    Header.Val := 0;π    Header.Sync:= 0;π  end;ππDestructor LabeledFile.Done;π  beginπ    CloseFile;π    FileDescriptor.Done;π  end;ππProcedure LabeledFile.OpenFile;π  beginπ    FileDescriptor.OpenFile;π    if IsOpen thenπ        ReadHeader;π  end;ππProcedure LabeledFile.CloseFile;π  beginπ    {$I-}π    if IsOpen thenπ      beginπ        if SoftPut and (CurRec <> -1) thenπ            PutRecord(CurRec);π        Header.Val := 0;π        WriteHeader;π        CurRec := -1;π      end;π    FileDescriptor.CloseFile;π    {$I+}π  end;ππProcedure LabeledFile.ReadHeader;π  Varπ    Result : Word;π  beginπ    {$I-}π    Seek(Fpt,0);π    if IoResult = 0 thenπ      beginπ        BlockRead(Fpt,Header,HeaderSize,Result);π        if (Result <> HeaderSize) or (IoResult <> 0) thenπ            {Error Routine};π      end;π    {$I+}π  end;ππProcedure LabeledFile.WriteHeader;π  Varπ    Result : Word;π  beginπ    {$I-}π    Seek(Fpt,0);π    if IoResult = 0 thenπ      beginπ        BlockWrite(Fpt,Header,HeaderSize,Result);π        if (Result <> HeaderSize) or (IoResult <> 0) thenπ            {Error Routine};π      end;π    {$I+}π  end;ππProcedure LabeledFile.AddRecord;π  Varπ    TmpRec : Pointer;π    Result : Word;π    Next   : LongInt;π  beginπ    {$I-}π    if Header.MRD <> 0 thenπ      beginπ        GetMem(TmpRec,RecordSize);π        Seek(Fpt,HeaderSize + (Header.MRD - 1) * RecordSize);π        if IoResult = 0 thenπ          beginπ            BlockRead(Fpt,TmpRec^,RecordSize,Result);π            if (Result <> RecordSize) or (IoResult <> 0) thenπ                {Error Routine};π            Next := LongInt(TmpRec^);π            PutRecord(Header.MRD);π            Header.MRD := Next;π            Header.Act := Header.Act + 1;π          end;π        FreeMem(TmpRec,RecordSize);π      endπ    elseπ      beginπ        PutRecord(Header.Eof);π        Header.Eof := Header.Eof + 1;π        Header.Act := Header.Act + 1;π      end;π    WriteHeader;π    {$I+}π  end;ππProcedure LabeledFile.DelRecord(Rec : LongInt);π  Varπ    TmpRec : Pointer;π    Result : Word;π  beginπ    {$I-}π    GetMem(TmpRec,RecordSize);π    Seek(Fpt,HeaderSize + (Rec - 1) * RecordSize);π    if IoResult = 0 thenπ      beginπ        BlockRead(Fpt,TmpRec^,RecordSize,Result);π        LongInt(TmpRec^) := Header.MRD;π        BlockWrite(Fpt,TmpRec^,RecordSize,Result);π        if (Result <> RecordSize) or (IoResult <> 0) thenπ           {Error Routine};π        Header.MRD := Rec;π        Header.Act := Header.Act - 1;π        WriteHeader;π      end;π    {$I+}π  end;ππ{---------------------------------------------------------------------------}ππConstructor DetailFileDetail.Init(Nam : String; Size : Word; Buff : Pointer;πPut : Boolean);π  beginπ    if Size < 12 thenπ      beginπ        WriteLn('Detail File Records must be 12 Bytes or more');π        Fail;π      end;π    LabeledFile.Init(Nam,Size,Buff,Put);π  end;ππProcedure   DetailFileDetail.LinkChain(MR, Last, Curr : LongInt);π  Varπ    Hdr : DetailHeaderPtr;π  beginπ    Hdr := RecordPtr;π    if Last <> 0 thenπ      beginπ        GetRecord(Last);π        Hdr^.Next := Curr;π        PutRecord(Last);π      end;π    GetRecord(Curr);π    Hdr^.Prev := Last;π    Hdr^.Master := MR;π    Hdr^.Next := 0;π    PutRecord(Curr);π  end;ππProcedure   DetailFileDetail.DelinkChain(Rec : LongInt);  Varπ    Hdr : DetailHeaderPtr;π    Tmp : LongInt;π  beginπ    Hdr := RecordPtr;π    GetRecord(Rec);π    if Hdr^.Next <> 0 thenπ      beginπ        Tmp := Hdr^.Prev;π        GetRecord(Hdr^.Next);π        Hdr^.Prev := Tmp;π        PutRecord(CurRec);π        GetRecord(Rec);π      end;π    if Hdr^.Prev <> 0 thenπ      beginπ        Tmp := Hdr^.Next;π        GetRecord(Hdr^.Prev);π        Hdr^.Next := Tmp;π        PutRecord(CurRec);π        GetRecord(Rec);π      end;π    Hdr^.Master := 0;π    Hdr^.Next := 0;π    Hdr^.Prev := 0;π    PutRecord(Rec);π  end;ππ{---------------------------------------------------------------------------}ππConstructor DetailFileMaster.Init(Nam : String; Size : Word; Buff : Pointer;πPut : Boolean);π  beginπ    if Size < 8 thenπ      beginπ        WriteLn('Master File Records must be 8 Bytes or more');π        Fail;π      end;π    LabeledFile.Init(Nam,Size,Buff,Put);π  end;ππProcedure   DetailFileMaster.LinkDetail(DF : DetailFileDetailPtr);π  Varπ    Hdr : MasterHeaderPtr;π  beginπ    Hdr := RecordPtr;π    DF^.AddRecord;π    DF^.LinkChain(CurRec,Hdr^.Last,DF^.CurRec);π    Hdr^.Last := DF^.CurRec;π    if Hdr^.First = 0 then Hdr^.First := DF^.CurRec;π    PutRecord(CurRec);π  end;ππProcedure   DetailFileMaster.DelinkDetail(DF : DetailFileDetailPtr; DR :πLongInt);π  Varπ    Hdr : MasterHeaderPtr;π  beginπ    Hdr := RecordPtr;π    DF^.GetRecord(DR);π    if Hdr^.Last = DR thenπ        Hdr^.Last := DetailHeader(DF^.RecordPtr^).Prev;π    if Hdr^.First = DR thenπ        Hdr^.First := DetailHeader(DF^.RecordPtr^).Next;π    DF^.DelinkChain(DR);π    PutRecord(CurRec);π  end;ππProcedure   DetailFileMaster.GetFirst(DF : DetailFileDetailPtr);π  Varπ    Hdr : MasterHeaderPtr;π  beginπ    Hdr := RecordPtr;π    if Hdr^.First = 0 thenπ      beginπ        FillChar(DF^.RecordPtr^,DF^.RecordSize,#0);π        DF^.CurRec := -1;π        Exit;π      end;π    DF^.GetRecord(Hdr^.First);π  end;ππProcedure   DetailFileMaster.GetLast(DF : DetailFileDetailPtr);π  Varπ    Hdr : MasterHeaderPtr;π  beginπ    Hdr := RecordPtr;π    if Hdr^.Last = 0 thenπ      beginπ        FillChar(DF^.RecordPtr^,DF^.RecordSize,#0);π        DF^.CurRec := -1;π        Exit;π      end;π    DF^.GetRecord(Hdr^.Last);π  end;ππProcedure   DetailFileMaster.GetNext(DF : DetailFileDetailPtr);π  Varπ    Hdr : DetailHeaderPtr;π  beginπ    Hdr := DF^.RecordPtr;π    if Hdr^.Next = 0 thenπ      beginπ        FillChar(DF^.RecordPtr^,DF^.RecordSize,#0);π        DF^.CurRec := -1;π        Exit;π      end;π    DF^.GetRecord(Hdr^.Next);π  end;ππProcedure   DetailFileMaster.GetPrev(DF : DetailFileDetailPtr);π  Varπ    Hdr : DetailHeaderPtr;π  beginπ    Hdr := DF^.RecordPtr;π    if Hdr^.Prev = 0 thenπ      beginπ        FillChar(DF^.RecordPtr^,DF^.RecordSize,#0);π        DF^.CurRec := -1;π        Exit;π      end;π    DF^.GetRecord(Hdr^.Prev);π  end;ππ{---------------------------------------------------------------------------}ππbeginπend.ππ                      6      05-28-9313:54ALL                      SWAG SUPPORT TEAM        PTR-MEM.PAS              IMPORT              5      ╙═ñ5 Program Test_Pointers;ππTypeπ  Array_Pointer = ^MyArray;π  MyArray = Array[1..10] of String;ππVarπ  MyVar : Array_Pointer;ππbeginπ  Writeln('Memory beFore initializing Variable : ',MemAvail);ππ  New(MyVar);ππ  Writeln('Memory after initializiation : ',MemAvail);ππ  MyVar^[1] := 'Hello';π  MyVar^[2] := 'World!';ππ  Writeln(MyVar^[1], ' ', MyVar^[2]);ππ  Dispose(MyVar);ππ  Writeln('Memory after Variable memory released : ',MemAvail);πend.π                                                                       7      05-28-9313:54ALL                      SWAG SUPPORT TEAM        PTRARRAY.PAS             IMPORT              13     ╙═x DS> Hi, I've recently encountered a problem With not having enough memoryπDS> to open a large sized Array [ie: 0..900].  Is there any way toπDS> allocate more memory to the Array as to make larger ArraysππArray of what?  if the total size of the Array (i.e. 901 *πsizeof(whatever_it_is_you're_talking_about)) is less than 64K, it's a snap.πRead your dox on Pointers and the heap.  You'll end up doing something likeπthis:ππTypeπ  tWhatever : whatever_it_is_you're_talking_about;π  tMyArray : Array[0..900] of tWhatever;π  tPMyArray : ^MyArray;ππVarπ  PMyArray : tPMyArray;ππbeginπ  getmem(PMyArray,sizeof(tMyArray));ππ  { now access your Array like this:π    PMyArray^[IndexNo] }ππif your Array is >64K, you can do something like this:ππTypeπ  tWhatever : whatever_it_is_you're_talking_about;π  tPWhatever : ^tWhatever;ππVarπ  MyArray : Array[0..900] of tPWhatever;π  i : Word;ππbeginπ  For i := 0 to 900 doπ    getmem(MyArray[i],sizeof(tWhatever));ππ  { now access your Array like this:π    MyArray[IndexNo]^ }ππif you don't have enough room left in your data segment to use this latterπapproach (and I'll bet you do), you'll just need one more level of indirection.πDeclare one Pointer in the data segment that points to the Array of Pointers onπthe heap, which in turn point to your data.ππif you're a beginner, this may seem impossibly Complex (it did to me), but keepπat it and it will soon be second nature.π                                                                                                                          8      05-28-9313:54ALL                      SWAG SUPPORT TEAM        TREEHITE.PAS             IMPORT              7      ╙═£ {πAuthors: Chet Kress and Jerome Tonnesonππ>Help !!! I need a Function or Procedure in standard pascal that willπ>calculate the height of a binary tree. It must be able to calculate theπ>height of the tree if the tree is either balanced, unbalanced or full.π>The Procedure must be recursive.ππHere are the only two Functions you will need.π}ππFunction Max(A, B : Integer) : Integer;πbegin {Max}π  If A > B thenπ    Max := A;π  elseπ    Max := B;πend; {Max}ππFunction Height (Tree : TreeType) : Integer;πbegin {Height}π  If Tree = Nil thenπ    Height := 0π  elseπ    Height := Max(Height(Tree^.Right), Height(Tree^.Left)) + 1;πend; {Height}π                                                                                                                                9      06-22-9309:20ALL                      SWAG SUPPORT TEAM        Generic Linked List      IMPORT              34     ╙═]D UNIT LinkList;ππ{-------------------------------------------------π          Generic linked list object            -π-------------------------------------------------}ππ{***************************************************************}π                          INTERFACEπ{***************************************************************}ππTYPEππ    { Generic Linked List Handler Definition }ππ  NodeValuePtr = ^NodeValue;ππ  NodeValue = OBJECTπ    CONSTRUCTOR Init;π    DESTRUCTOR  Done; VIRTUAL;π  END;ππ  NodePtr = ^Node;π  Node = RECORDπ    Retrieve : NodeValuePtr;π    Next     : NodePtr;π  END;πππ    { Specific Linked List Handler Definition }ππ  NodeListPtr = ^NodeList;ππ  NodeList = OBJECTπ    Items : NodePtr;π    CONSTRUCTOR Init;π    DESTRUCTOR Done; VIRTUAL;π    PROCEDURE Add (A_Value : NodeValuePtr);ππ    (* Iterator Functions *)ππ    PROCEDURE StartIterator (VAR Ptr : NodePtr);π    PROCEDURE NextValue (VAR Ptr : NodePtr);π    FUNCTION AtEndOfList (Ptr : NodePtr) : Boolean;π  END;ππ{***************************************************************}π                         IMPLEMENTATIONπ{***************************************************************}πππCONSTRUCTOR NodeValue.Init;πBEGINπEND;ππDESTRUCTOR NodeValue.Done;πBEGINπEND;ππCONSTRUCTOR NodeList.Init;πBEGINπ  Items := NIL;πEND;ππDESTRUCTOR NodeList.Done;π    VARπ         Temp : NodePtr;πBEGINπ    WHILE Items <> NIL DOπ    BEGINπ         Temp := Items;π         IF Temp^.Retrieve <> NIL THENπ              Dispose (Temp^.Retrieve, Done);π         Items := Items^.Next;π         Dispose (Temp);π    END;πEND;ππPROCEDURE NodeList.Add (A_Value : NodeValuePtr);π    VARπ         Cell : NodePtr;π         Temp : NodePtr;πBEGINπ    (* Go TO the END OF the linked list. *)π    Cell := Items;π    IF Cell <> NIL THENπ         WHILE Cell^.Next <> NIL DOπ              Cell := Cell^.Next;ππ    New (Temp);π    Temp^.Retrieve := A_Value;π    Temp^.Next := NIL;π    IF Items = NILπ    THENπ         Items := Tempπ    ELSEπ         Cell^.Next := Temp;πEND;ππPROCEDURE NodeList.StartIterator (VAR Ptr : NodePtr);πBEGINπ    Ptr := Items;πEND;ππPROCEDURE NodeList.NextValue (VAR Ptr : NodePtr);πBEGINπ    IF Ptr <> NIL THENπ    Ptr := Ptr^.Next;πEND;ππFUNCTION NodeList.AtEndOfList (Ptr : NodePtr) : Boolean;πBEGINπ  AtEndOfList := (Ptr = NIL);πEND;ππEND.ππ{ DEMO PROGRAM }ππPROGRAM LL_Demo;ππUSES LinkList;ππ{ Turbo Pascal Linked List Object Example }ππTYPEππ  DataValuePtr = ^DataValue;ππ  DataValue = OBJECT (NodeValue)π    Value : Real;π    CONSTRUCTOR Init (A_Value : Real);π    FUNCTION TheValue : Real;π  END;ππ  DataList = OBJECT (NodeList)π    FUNCTION CurrentValue (Ptr : NodePtr) : Real;π    PROCEDURE SetCurrentValue (Ptr : NodePtr; Value : Real);π  END;ππVARπ    Itr : NodePtr;π    TestLink : DataList;ππ{------ Unique methods to create for your linked list type -----}ππCONSTRUCTOR DataValue.Init (A_Value : Real);πBEGINπ    Value := A_Value;πEND;ππFUNCTION DataValue.TheValue : Real;πBEGINπ  TheValue := Value;πEND;ππFUNCTION DataList.CurrentValue (Ptr : NodePtr) : Real;πBEGINπ  CurrentValue := DataValuePtr (Ptr^.Retrieve)^.TheValue;πEND;ππPROCEDURE DataList.SetCurrentValue (Ptr : NodePtr; Value : Real);πBEGINπ  DataValuePtr (Ptr^.Retrieve)^.Value := Value;πEND;πππBEGINπ  TestLink.Init;        {Create the list then add 5 values to it}ππ  TestLink.Add (New (DataValuePtr, Init (1.0)));π  TestLink.Add (New (DataValuePtr, Init (2.0)));π  TestLink.Add (New (DataValuePtr, Init (3.0)));π  TestLink.Add (New (DataValuePtr, Init (4.0)));π  TestLink.Add (New (DataValuePtr, Init (5.0)));ππ  TestLink.StartIterator (Itr);      {Display the list on screen}π  WHILE NOT TestLink.AtEndOfList (Itr) DO BEGINπ    Write (TestLink.CurrentValue (Itr) : 5 : 1);π    TestLink.NextValue (Itr);π    END;π  WriteLn;ππ  TestLink.StartIterator (Itr);  {Change some values in the list}π  TestLink.SetCurrentValue (Itr, 0.0);π  TestLink.NextValue (Itr);π  TestLink.SetCurrentValue (Itr, -1.0);ππ  TestLink.StartIterator (Itr);       {Redisplay the list values}π  WHILE NOT TestLink.AtEndOfList (Itr) DO BEGINπ    Write (TestLink.CurrentValue (Itr) : 5 : 1);π    TestLink.NextValue (Itr);π  END;π  WriteLn;π  ReadLn;πEND.π                                           10     08-17-9308:39ALL                      SWAG SUPPORT TEAM        Binary Tree - Linked ListIMPORT              73     ╙═╙¡ Unit BinTree;ππInterfaceππConst TOTAL_NODES = 100;ππType BTreeStr = String[40];π  ShiftSet = (TiltL_Tilt, neutral, TiltR_Tilt);π  BinData  = Recordπ    Key : BTreeStr;π  End;π  BinPtr = ^Bin_Tree_Rec;π  Bin_Tree_Rec = Recordπ    BTreeData    : BinData;π    Shift        : ShiftSet;π    TiltL, TiltR : BinPtr;π  End;π  BTreeRec = Array[1..TOTAL_NODES] of BinData;ππProcedure Ins_BinTreeπ  (Var Rt   : BinPtr;π       Node : BinData);ππFunction Srch_BinTreeπ  (Rt     : BinPtr;π   Node   : BinData;π   Index1 : Word) : Word;ππProcedure BSortArrayπ  (Var Rt       : BinPtr;π   Var SortNode : BTreeRec;π   Var Index    : Word);ππProcedure Del_BinTreeπ  (Var Rt      : BinPtr;π       Node    : BinData;π       Var DelFlag : Boolean);ππImplementationππProcedure Move_TiltR(Var Rt : BinPtr);ππ  Varπ    Ptr1, Ptr2 : BinPtr;ππ  Beginπ    Ptr1 := Rt^.TiltR;π    If Ptr1^.Shift = TiltR_Tilt Then Beginπ      Rt^.TiltR := Ptr1^.TiltL;π      Ptr1^.TiltL := Rt;π      Rt^.Shift := neutral;π      Rt := Ptr1π    Endπ    Else Beginπ      Ptr2 := Ptr1^.TiltL;π      Ptr1^.TiltL := Ptr2^.TiltR;π      Ptr2^.TiltR := Ptr1;π      Rt^.TiltR := Ptr2^.TiltL;π      Ptr2^.TiltL := Rt;π      If Ptr2^.Shift = TiltL_Tiltπ        Then Ptr1^.Shift := TiltR_Tiltπ        Else Ptr1^.Shift := neutral;π      If Ptr2^.Shift = TiltR_Tiltπ        Then Rt^.Shift := TiltL_Tiltπ        Else Rt^.Shift := neutral;π      Rt := Ptr2π    End;π    Rt^.Shift := neutralπ  End;ππProcedure Move_TiltL(Var Rt : BinPtr);ππ  Varπ    Ptr1, Ptr2 : BinPtr;ππ  Beginπ    Ptr1 := Rt^.TiltL;π    If Ptr1^.Shift = TiltL_Tilt Then Beginπ      Rt^.TiltL := Ptr1^.TiltR;π      Ptr1^.TiltR := Rt;π      Rt^.Shift := neutral;π      Rt := Ptr1π    Endπ    Else Beginπ      Ptr2 := Ptr1^.TiltR;π      Ptr1^.TiltR := Ptr2^.TiltL;π      Ptr2^.TiltL := Ptr1;π      Rt^.TiltL := Ptr2^.TiltR;π      Ptr2^.TiltR := Rt;π      If Ptr2^.Shift = TiltR_Tiltπ        Then Ptr1^.Shift := TiltL_Tiltπ        Else Ptr1^.Shift := neutral;π      If Ptr2^.Shift = TiltL_Tiltπ        Then Rt^.Shift := TiltR_Tiltπ        Else Rt^.Shift := neutral;π      Rt := Ptr2;π    End;π    Rt^.Shift := neutralπ  End;ππProcedure Ins_Bin(Var Rt    : BinPtr;π                      Node  : BinData;π                  Var InsOK : Boolean);ππ  Beginπ    If Rt = NIL Then Beginπ      New(Rt);π      With Rt^ Do Beginπ        BTreeData := Node;π        TiltL := NIL;π        TiltR := NIL;π        Shift := neutralπ      End;π      InsOK := TRUEπ    Endπ    Else If Node.Key <= Rt^.BTreeData.Key Then Beginπ      Ins_Bin(Rt^.TiltL, Node, InsOK);π      If InsOK Thenπ        Case Rt^.Shift Ofπ          TiltL_Tilt : Beginπ                        Move_TiltL(Rt);π                        InsOK := FALSEπ                       End;π          neutral    : Rt^.Shift := TiltL_Tilt;π          TiltR_Tilt : Beginπ                        Rt^.Shift := neutral;π                        InsOK := FALSEπ                       End;π        End;π      Endπ      Else Beginπ        Ins_Bin(Rt^.TiltR, Node, InsOK);π        If InsOK Thenπ          Case Rt^.Shift Ofπ            TiltL_Tilt : Beginπ                          Rt^.Shift := neutral;π                          InsOK := FALSEπ                         End;π            neutral    : Rt^.Shift := TiltR_Tilt;π            TiltR_Tilt : Beginπ                          Move_TiltR(Rt);π                          InsOK := FALSEπ                         End;π          End;π        End;π  End;ππProcedure Ins_BinTree(Var Rt   : BinPtr;π                        Node : BinData);ππ  Var Ins_ok : Boolean;ππ  Beginπ    Ins_ok := FALSE;π    Ins_Bin(Rt, Node, Ins_ok)π  End;ππFunction Srch_BinTree(Rt     : BinPtr;π                      Node   : BinData;π                      Index1 : Word)π                      : Word;ππ  Varπ    Index : Word;ππ  Beginπ    Index := 0;π    While (Rt <> NIL) AND (Index < Index1) Doπ      If Node.Key > Rt^.BTreeData.Key Then Rt := Rt^.TiltRπ      Else if Node.Key < Rt^.BTreeData.Key Then Rt := Rt^.TiltLπ      Else Beginπ        Inc(Index);π        Rt := Rt^.TiltLπ      End;π    Srch_BinTree := Indexπ  End;ππProcedure Tvrs_Treeπ  (Var Rt       : BinPtr;π   Var SortNode : BTreeRec;π   Var Index    : Word);ππ  Beginπ    If Rt <> NIL Then Beginπ      Tvrs_Tree(Rt^.TiltL, SortNode, Index);π      Inc(Index);π      If Index <= TOTAL_NODES Thenπ        SortNode[Index].Key := Rt^.BTreeData.Key;π      Tvrs_Tree(Rt^.TiltR, SortNode, Index);π    End;π  End;ππProcedure BSortArrayπ  (Var Rt       : BinPtr;π   Var SortNode : BTreeRec;π   Var Index    : Word);ππ  Beginπ    Index := 0;π    Tvrs_Tree(Rt, SortNode, Index);π  End;ππProcedure Shift_TiltRπ  (Var Rt      : BinPtr;π   Var DelFlag : Boolean);ππ  Varπ    Ptr1, Ptr2 : BinPtr;π    balnc2, balnc3 : ShiftSet;ππ  Beginπ    Case Rt^.Shift Ofπ      TiltL_Tilt : Rt^.Shift := neutral;π      neutral    : Beginπ                     Rt^.Shift := TiltR_Tilt;π                     DelFlag := FALSEπ                   End;π      TiltR_Tilt : Beginπ           Ptr1 := Rt^.TiltR;π           balnc2 := Ptr1^.Shift;π           If NOT (balnc2 = TiltL_Tilt) Then Beginπ             Rt^.TiltR := Ptr1^.TiltL;π             Ptr1^.TiltL := Rt;π             If balnc2 = neutral Then Beginπ               Rt^.Shift := TiltR_Tilt;π               Ptr1^.Shift := TiltL_Tilt;π               DelFlag := FALSEπ             Endπ             Else Beginπ               Rt^.Shift := neutral;π               Ptr1^.Shift := neutral;π             End;π             Rt := Ptr1π           Endπ           Else Beginπ             Ptr2 := Ptr1^.TiltL;π             balnc3 := Ptr2^.Shift;π             Ptr1^.TiltL := Ptr2^.TiltR;π             Ptr2^.TiltR := Ptr1;π             Rt^.TiltR := Ptr2^.TiltL;π             Ptr2^.TiltL := Rt;π             If balnc3 = TiltL_Tilt Thenπ               Ptr1^.Shift := TiltR_Tiltπ             Elseπ               Ptr1^.Shift := neutral;π             If balnc3 = TiltR_Tilt Thenπ               Rt^.Shift := TiltL_Tiltπ             Elseπ               Rt^.Shift := neutral;π             Rt := Ptr2;π             Ptr2^.Shift := neutral;π           End;π         End;π      End;π    End;ππProcedure Shift_TiltLπ  (Var Rt      : BinPtr;π   Var DelFlag : Boolean);ππ  Varπ    Ptr1, Ptr2 : BinPtr;π    balnc2, balnc3 : ShiftSet;ππ  Beginπ    Case Rt^.Shift Ofπ      TiltR_Tilt : Rt^.Shift := neutral;π      neutral    : Beginπ                     Rt^.Shift := TiltL_Tilt;π                     DelFlag := Falseπ                   End;π      TiltL_Tilt : Beginπ           Ptr1 := Rt^.TiltL;π           balnc2 := Ptr1^.Shift;π           If NOT (balnc2 = TiltR_Tilt) Then Beginπ             Rt^.TiltL := Ptr1^.TiltR;π             Ptr1^.TiltR := Rt;π             If balnc2 = neutral Then Beginπ               Rt^.Shift := TiltL_Tilt;π               Ptr1^.Shift := TiltR_Tilt;π               DelFlag := FALSEπ             Endπ             Else Beginπ               Rt^.Shift := neutral;π               Ptr1^.Shift := neutral;π             End;π             Rt := Ptr1π           Endπ           Else Beginπ             Ptr2 := Ptr1^.TiltR;π             balnc3 := Ptr2^.Shift;π             Ptr1^.TiltR := Ptr2^.TiltL;π             Ptr2^.TiltL := Ptr1;π             Rt^.TiltL := Ptr2^.TiltR;π             Ptr2^.TiltR := Rt;π             If balnc3 = TiltR_Tilt Thenπ               Ptr1^.Shift := TiltL_Tiltπ             Elseπ               Ptr1^.Shift := neutral;π             If balnc3 = TiltL_Tilt Thenπ               Rt^.Shift := TiltR_Tiltπ             Elseπ               Rt^.Shift := neutral;π             Rt := Ptr2;π             Ptr2^.Shift := neutral;π           End;π         End;π    End;π  End;ππProcedure Kill_Lo_Nodesπ  (Var Rt,π       Ptr     : BinPtr;π   Var DelFlag : Boolean);ππ  Beginπ    If Ptr^.TiltR = NIL Then Beginπ      Rt^.BTreeData := Ptr^.BTreeData;π      Ptr := Ptr^.TiltL;π      DelFlag := TRUEπ    Endπ    Else Beginπ      Kill_Lo_Nodes(Rt, Ptr^.TiltR, DelFlag);π      If DelFlag Then Shift_TiltL(Ptr,DelFlag);π    End;π  End;ππProcedure Del_Bin(Var Rt      : BinPtr;π                      Node    : BinData;π                  Var DelFlag : Boolean);ππ  Varπ    Ptr : BinPtr;ππ  Beginπ    If Rt = NIL Thenπ       DelFlag := Falseπ    Elseπ      If Node.Key < Rt^.BTreeData.Key Then Beginπ        Del_Bin(Rt^.TiltL, Node, DelFlag);π        If DelFlag Then Shift_TiltR(Rt, DelFlag);π      Endπ      Else Beginπ        If Node.Key > Rt^.BTreeData.Key Then Beginπ          Del_Bin(Rt^.TiltR, Node, DelFlag);π          If DelFlag Then Shift_TiltL(Rt, DelFlag);π        Endπ        Else Beginπ          Ptr := Rt;π          If Rt^.TiltR = NIL Then Beginπ            Rt := Rt^.TiltL;π            DelFlag := TRUE;π            Dispose(Ptr);π          Endπ          Else If Rt^.TiltL = NIL Then Beginπ            Rt := Rt^.TiltR;π            DelFlag := TRUE;π            Dispose(Ptr);π          Endπ          Else Beginπ            Kill_Lo_Nodes(Rt, Rt^.TiltL, DelFlag);π            If DelFlag Then Shift_TiltR(Rt, DelFlag);π            Dispose(Rt^.TiltL);π          End;π        End;π      End;π  End;ππProcedure Del_BinTreeπ  (Var Rt      : BinPtr;π       Node    : BinData;π   Var DelFlag : Boolean);ππ  Beginπ    DelFlag := FALSE;π    Del_Bin(Rt, Node, DelFlag)π  End;πEnd.                   11     08-27-9320:11ALL                      SWAG SUPPORT TEAM        AVL Binary Trees         IMPORT              52     ╙═. {π> Does anyone have code(preferably TP) the implements AVL trees?π> I'm having trouble With the insertion part of it.  I'm writing a smallπ> parts inventory Program For work(although I'm not employed as aπ> Programmer) and the AVL tree would be very fast For it.π}πππProgram avl;ππTypeπ  nodeptr = ^node;π  node    = Recordπ    key   : Char;π    bal   : -1..+1; { bal = h(right) - h(left) }π    left,π    right : nodeptrπ  end;ππ  tree = nodeptr;ππVarπ  t : tree;π  h : Boolean; { insert & delete parameter }πππProcedure maketree(Var t : tree);πbeginπ  t := nil;πend;ππFunction member(k : Char; t : tree) : Boolean;πbegin { member }π  if t = nil thenπ    member := Falseπ  elseπ  if k = t^.key thenπ    member := Trueπ  elseπ  if k < t^.key thenπ    member := member(k, t^.left)π  elseπ    member := member(k, t^.right);πend;ππProcedure ll(Var t : tree);πVarπ  p : tree;πbeginπ  p := t^.left;π  t^.left  := p^.right;π  p^.right := t;π  t := p;πend;ππProcedure rr(Var t : tree);πVarπ   p : tree;πbeginπ  p := t^.right;π  t^.right := p^.left;π  p^.left  := t;π  t := p;πendππProcedure lr(Var t : tree);πbeginπ  rr(t^.left);π  ll(t);πend;ππProcedure rl(Var t : tree);πbeginπ  ll(t^.right);π  rr(t);πend;ππProcedure insert(k : Char; Var t : tree; Var h : Boolean);ππ  Procedure balanceleft(Var t : tree; Var h : Boolean);π  beginπ    Writeln('balance left');π    Case t^.bal ofπ      +1 :π        beginπ          t^.bal := 0;π          h := False;π        end;π       0 : t^.bal := -1;π      -1 :π        begin { rebalance }π          if t^.left^.bal = -1 thenπ          begin { single ll rotation }π            Writeln('single ll rotation');π            ll(t);π            t^.right^.bal := 0;π          endπ          else { t^.left^.bal  = +1 }π          begin  { double lr rotation }π            Writeln('double lr rotation');π            lr(t);π            if t^.bal = -1 thenπ              t^.right^.bal := +1π            elseπ              t^.right^.bal := 0;π            if t^.bal = +1 thenπ              t^.left^.bal := -1π            elseπ              t^.left^.bal := 0;π          end;π          t^.bal := 0;π          h := False;π        end;π    end;π  end;ππ  Procedure balanceright(Var t : tree; Var h : Boolean);π  beginπ    Writeln('balance right');π    Case t^.bal ofπ      -1 :π        beginπ          t^.bal := 0;π          h := False;π        end;π       0 : t^.bal := +1;π      +1 :π        begin { rebalance }π          if t^.right^.bal = +1 thenπ          begin { single rr rotation }π            Writeln('single rr rotation');π            rr(t);π            t^.left^.bal := 0π          endπ          else { t^.right^.bal  = -1 }π          begin  { double rl rotation }π            Writeln('double rl rotation');π            rl(t);π            if t^.bal = -1 thenπ              t^.right^.bal := +1π            elseπ              t^.right^.bal := 0;π            if t^.bal = +1 thenπ              t^.left^.bal := -1π            elseπ              t^.left^.bal := 0;π          end;π          t^.bal := 0;π          h := False;π        end;π    end;π  end;ππbegin { insert }π  if t = nil thenπ  beginπ    new(t);π    t^.key   := k;π    t^.bal   := 0;π    t^.left  := nil;π    t^.right := nil;π      h := True;π  endπ  elseπ  if k < t^.key thenπ  beginπ    insert(k, t^.left, h);π      if h thenπ      balanceleft(t, h);π  endπ  elseπ  if k > t^.key thenπ  beginπ    insert(k, t^.right, h);π    if h thenπ      balanceright(t, h);π  end;πend;ππProcedure delete(k : Char; Var t : tree; Var h : Boolean);ππ  Procedure balanceleft(Var t : tree; Var h : Boolean);π  beginπ    Writeln('balance left');π    Case t^.bal ofπ      -1 :π        beginπ          t^.bal := 0;π          h := True;π        end;π       0 :π         beginπ             t^.bal := +1;π             h := False;π           end;π      +1 :π        begin { rebalance }π          if t^.right^.bal >= 0 thenπ          beginπ            Writeln('single rr rotation'); { single rr rotation }π                if t^.right^.bal = 0 thenπ            beginπ              rr(t);π                  t^.bal := -1;π                  h := False;π                endπ                elseπ            beginπ              rr(t);π                  t^.left^.bal := 0;π                  t^.bal := 0;π                  h := True;π                end;π          endπ          else { t^.right^.bal  = -1 }π          beginπ                Writeln('double rl rotation');π               rl(t);π                t^.left^.bal := 0;π            t^.right^.bal := 0;π                h := True;π              end;π        end;π    end;π  end;ππ  Procedure balanceright(Var t : tree; Var h : Boolean);π  beginπ    Writeln('balance right');π    Case t^.bal ofπ      +1 :π        beginπ          t^.bal := 0;π          h := True;π        end;π       0 :π         beginπ             t^.bal := -1;π             h := False;π           end;π      -1 :π        begin { rebalance }π          if t^.left^.bal <= 0 thenπ          begin { single ll rotation }π            Writeln('single ll rotation');π                if t^.left^.bal = 0 thenπ            beginπ              ll(t);π                  t^.bal := +1;π                  h := False;π                endπ                elseπ            beginπ              ll(t);π                  t^.left^.bal := 0;π                  t^.bal := 0;π                  h := True;π                end;π          endπ          else { t^.left^.bal  = +1 }π          begin  { double lr rotation }π            Writeln('double lr rotation');π            lr(t);π                t^.left^.bal := 0;π                t^.right^.bal := 0;π                h := True;π          end;π        end;π    end;π  end;ππ  Function deletemin(Var t : tree; Var h : Boolean) : Char;π  begin { deletemin }π    if t^.left = nil thenπ    beginπ      deletemin := t^.key;π      t := t^.right;π        h := True;π    endπ    elseπ    beginπ      deletemin := deletemin(t^.left, h);π        if h thenπ        balanceleft(t, h);π    end;π  end;ππbegin { delete }π  if t <> nil thenπ  beginπ    if k < t^.key thenπ    beginπ      delete(k, t^.left, h);π        if h thenπ        balanceleft(t, h);π    endπ    elseπ    if k > t^.key thenπ    beginπ      delete(k, t^.right, h);π        if h thenπ        balanceright(t, h);π    endπ    elseπ    if (t^.left = nil) and (t^.right = nil) thenπ    beginπ      t := nil;π        h := True;π    endπ    elseπ    if t^.left = nil thenπ    beginπ      t := t^.right;π        h := True;π    endπ    elseπ    if t^.right = nil thenπ    beginπ      t := t^.left;π        h := True;π    endπ    elseπ    beginπ      t^.key := deletemin(t^.right, h);π        if h thenπ          balanceright(t, h);π    end;π  end;πend;ππbeginπend.π                        12     09-26-9308:50ALL                      GARRY J. VASS            Linked Lists in EMS      IMPORT              111    ╙═Çù {π       PROTOTYPE PROCEDURES FOR CREATING AND ACCESSING SORTEDπ                 LINKED LISTS IN EXPANDED MEMORYππ                  GARRY J. VASS [72307,3311]ππThe procedures and functions given below present a prototypeπmethod for creating and accesing linked lists in expanded memory.πAlthough pointer variables are used in a way that appears toπconform to the TPascal pointer syntax, there are several majorπdifferences:ππ            -  there are none of the standard NEW, GETMEM,π               MARK, RELEASE, DISPOSE, FREEMEM, and MAXAVAILπ               calls made.  These are bound to the program'sπ               physical location in memory, and have noπ               effect in expanded memory.  Attempting toπ               use these here, or to implement standardπ               linked procedures by altering the HeapPtrπ               standard variable is dangerous and highlyπ               discouraged.π            -  pointer variables are set and queried byπ               a simulation of TPascal's internal proceduresπ               that is specially customized to the EMSπ               page frame segment.π            -  the MEMAVAIL function is useless here.  Theseπ               procedures will support a list of up to 64K.ππThe general pseudo-code for creating a linked list in expandedπmemory is:ππ      1.  Get a handle and allocate memory from the EMM.π      2.  Get the page frame segment for the handle toπ          mark the physical beginning of the list inπ          expanded memory.π      3.  Initialize the root pointer to the page frameπ          segment.π      4.  For each new record (or list member):ππ          a.  Calculate a new physical location for theπ              record using a simulated normalizationπ              procedure.π          b.  Set the appropriate values to theπ              pointers using a simulated pointerπ              assignment procedure.π          c.  Assure that the last logical recordπ              contains a pointer value of NIL.ππAccessing the list is basically the same as the standard algorithms.ππThe procedures here assume that each list record (or member) is composedπof three elements:ππ        -  a pointer to the next logical record.  If the member is theπ           last logical record, this pointer is NIL.π        -  an index, or logical sort key.  This value determines theπ           logical position of the record in the list.  These routinesπ           and the demo use an integer type for index.  The index,π           however, can be of any type where ordinal comparisonsπ           can be made, including pointers.π        -  an area for the actual data in each record.  These routinesπ           and the demo use a string of length 255, but this area canπ           be of any type, including pointers to other lists.ππPlease note that these routines are exploratory and prototype.  In no wayπare they intended to be definitive, accurate, efficient, or exemplary.ππAreas for further analysis are:ππ      1.  A reliable analog to the MEMAVAIL function.π      2.  Creating linked lists that cross handle boundaries.π      3.  Creating linked lists that begin in heapspace andπ          extend to expanded memory.π      4.  A reliable method for assigning the standardπ          variable, HeapPtr, to the base page.ππPlease let me know of your progress in these areas, or improvementsπto the routines below via the BORLAND SIG [72307,3311] or my PASCAL/πPROLOG SIG at the POLICE STATION BBS (201-963-3115).ππ}πPROGRAM LINKED_LISTS;πUses dos,crt;πCONSTπ     ALLOCATE_MEMORY =   $43;π     EMS_SERVICES    =   $67;π     FOREVER:BOOLEAN = FALSE;π     GET_PAGE_FRAME  =   $41;π     LOGICAL_PAGES   =     5;π     MAP_MEMORY      =   $44;π     RELEASE_HANDLE  =   $45;πTYPEπ    ANYSTRING = STRING[255];π    LISTPTR   = ^LISTREC;π    LISTREC   = RECORDπ                      NEXT_POINTER : LISTPTR;π                      INDEX_PART   : INTEGER;π                      DATA_PART    : ANYSTRING;π                END;πVARπ   ANYINTEGER : INTEGER;π   ANYSTR     : ANYSTRING;π   HANDLE     : INTEGER;    { HANDLE ASSIGNED BY EMM }π   LIST       : LISTREC;π   NEWOFFSET  : INTEGER;    { PHYSICAL OFFSET OF RECORD }π   NEWSEGMENT : INTEGER;    { PHYSICAL SEGMENT OF RECORD }π   REGS1      : Registers;π   ROOT       : LISTPTR;    { POINTER TO LIST ROOT }π   SEGMENT    : INTEGER;    { PAGE FRAME SEGMENT }ππ{--------------------- GENERAL SUPPORT ROUTINES  ----------------------}πFUNCTION HEXBYTE(N:INTEGER):ANYSTRING;πCONST H:ANYSTRING='0123456789ABCDEF';πBEGINπ     HEXBYTE:=H[((LO(N)DIV 16)MOD 16)+1]+H[(LO(N) MOD 16)+1];πEND;ππFUNCTION HEXWORD(N:INTEGER):ANYSTRING;πBEGINπ     HEXWORD:= HEXBYTE(HI(N))+HEXBYTE(LO(N));πEND;ππFUNCTION CARDINAL(I:INTEGER):REAL;πBEGINπ     CARDINAL:=256.0*HI(I)+LO(I);πEND;ππPROCEDURE  PAUSE;πVAR CH:CHAR;πBEGINπ     WRITELN;WRITELN('-- PAUSING FOR KEYBOARD INPUT...');π     READ(CH);π     WRITELN;πEND;ππPROCEDURE DIE(M:ANYSTRING);πBEGINπ     WRITELN('ERROR IN: ',M);π     WRITELN('HALTING HERE, SUGGEST REBOOT');π     HALT;πEND;πFUNCTION EXIST(FILENAME:ANYSTRING):BOOLEAN;VAR FILVAR:FILE;BEGIN ASSIGN(FILVAR,FILENAME);{$I-}πRESET(FILVAR);{$I+}EXIST := (IORESULT = 0);END;π{--------------------- END OF GENERAL SUPPORT ROUTINES  ----------------}ππ{----------------------  EMS SUPPORT ROUTINES  -------------------------}ππFUNCTION EMS_INSTALLED:BOOLEAN;         { RETURNS TRUE IF EMS IS INSTALLED }πBEGIN                                   { ASSURED DEVICE NAME OF EMMXXXX0  }π     EMS_INSTALLED := EXIST('EMMXXXX0');{ BY LOTUS/INTEL/MS STANDARDS      }πEND;ππFUNCTION NEWHANDLE(NUMBER_OF_LOGICAL_PAGES_NEEDED:INTEGER):INTEGER;πBEGINπ     REGS1.AH := ALLOCATE_MEMORY;π     REGS1.BX := NUMBER_OF_LOGICAL_PAGES_NEEDED;π     INTR(EMS_SERVICES, REGS1);π     IF REGS1.AH <> 0 THEN DIE('ALLOCATE MEMORY');π     NEWHANDLE := REGS1.DX;πEND;ππPROCEDURE KILL_HANDLE(HANDLE_TO_KILL:INTEGER);  { RELEASES EMS HANDLE.    }πBEGIN                                           { THIS MUST BE DONE IF    }π     REPEAT                                     { OTHER APPLICATIONS ARE  }π          WRITELN('RELEASING EMS HANDLE');      { TO USE THE EM ARES.  DUE}π          REGS1.AH := RELEASE_HANDLE;            { TO CONCURRENT PROCESSES,}π          REGS1.DX := HANDLE_TO_KILL;            { SEVERAL TRIES MAY BE    }π          INTR(EMS_SERVICES, REGS1);             { NECESSARY.              }π     UNTIL REGS1.AH = 0;π     WRITELN('HANDLE RELEASED');πEND;ππFUNCTION PAGE_FRAME_SEGMENT:INTEGER;         { RETURNS PFS }πBEGINπ     REGS1.AH := GET_PAGE_FRAME;π     INTR(EMS_SERVICES, REGS1);π     IF REGS1.AH <> 0 THEN DIE('GETTING PFS');π     PAGE_FRAME_SEGMENT := REGS1.BX;πEND;ππPROCEDURE MAP_MEM(HANDLE_TO_MAP:INTEGER);  {MAPS HANDLE TO PHYSICAL}πCONST PHYSICAL_PAGE = 0;                 {PAGES.}πBEGINπ     REGS1.AH := MAP_MEMORY;π     REGS1.AL := PHYSICAL_PAGE;π     REGS1.BX := PHYSICAL_PAGE;π     REGS1.DX := HANDLE_TO_MAP;π     INTR(EMS_SERVICES, REGS1);π     IF REGS1.AH <> 0 THEN DIE('MAPPING MEMORY');πEND;ππPROCEDURE GET_EMS_MEMORY(NUMBER_OF_16K_LOGICAL_PAGES:INTEGER);πVAR TH:INTEGER;                     { REQUESTS EM FROM EMM IN 16K INCREMENTS }πBEGINπ     HANDLE :=  NEWHANDLE(NUMBER_OF_16K_LOGICAL_PAGES);π     SEGMENT := PAGE_FRAME_SEGMENT;π     MAP_MEM(HANDLE);πEND;π{----------------- END OF EMS SUPPORT ROUTINES  -----------------------}ππ{----------------- CUSTOMIZED LINKED LIST SUPPORT ---------------------}πFUNCTION ABSOLUTE_ADDRESS(S, O:INTEGER):REAL;   { RETURNS THE REAL }πBEGIN                                           { ABSOLUTE ADDRESS }π     ABSOLUTE_ADDRESS :=  (CARDINAL(S) * $10)   { FOR SEGMENT "S"  }π                         + CARDINAL(O);         { AND OFFSET "O".  }πEND;ππPROCEDURE NORMALIZE(VAR S, O:INTEGER); { SIMULATION OF TURBO'S INTERNAL }πVAR                                    { NORMALIZATION ROUTINES FOR     }π   NEW_SEGMENT: INTEGER;               { POINTER VARIABLES.             }π   NEW_OFFSET : INTEGER;               { NORMALIZES SEGMENT "S" AND     }πBEGIN                                  { OFFSET "O" INTO LEGITAMATE     }π     NEW_SEGMENT := S;                 { POINTER VALUES.                }π     NEW_OFFSET  := O;π     REPEATπ           CASE NEW_OFFSET OFπ              $00..$0E   : NEW_OFFSET := SUCC(NEW_OFFSET);π              $0F..$FF   : BEGINπ                               NEW_OFFSET := 0;π                               NEW_SEGMENT := SUCC(NEW_SEGMENT);π                           END;π           END;π     UNTIL  (ABSOLUTE_ADDRESS(NEW_SEGMENT, NEW_OFFSET) >π             ABSOLUTE_ADDRESS(S, O) + SIZEOF(LIST));π     S := NEW_SEGMENT;π     O := NEW_OFFSET;πEND;ππFUNCTION VALUEOF(P:LISTPTR):ANYSTRING;  { RETURNS A STRING IN   }π                                        { SEGMENT:OFFSET FORMAT }π                                        { WHICH CONTAINS VALUE  }πBEGIN                                   { OF A POINTER VARIABLE }π     VALUEOF := HEXBYTE(MEM[SEG(P):OFS(P) + 3]) +π                HEXBYTE(MEM[SEG(P):OFS(P) + 2]) +':'+π                HEXBYTE(MEM[SEG(P):OFS(P) + 1]) +π                HEXBYTE(MEM[SEG(P):OFS(P) + 0]);πEND;ππPROCEDURE SNAP(P:LISTPTR);                   { FOR THE RECORD BEING         }πBEGIN                                        { POINTED TO BY "P", THIS      }π     WRITELN(VALUEOF(P):10,                  { PRINTS THE SEGMENT/OFFSET    }π             VALUEOF(P^.NEXT_POINTER):20,    { LOCATION, THE SEGMENT/       }π             P^.INDEX_PART:5,                { OFFSET OF THE RECORD PONTER, }π             '     ',P^.DATA_PART);          { RECORD INDEX, AND DATA.      }πEND;ππPROCEDURE PROCESS_LIST;               { GET AND PRINT MEMBERS OF A LIST }πVAR M1:LISTPTR;                       { SORTED IN INDEX ORDER.          }πBEGINπ     PAUSE;π     M1 := ROOT;π     WRITELN;π     WRITELN('---------------- LINKED LIST ---------------------------------');π     WRITELN('MEMBER LOCATION           MEMBER CONTENTS');π     WRITELN('IN MEMORY             POINTER    INDEX  DATA   ');π     WRITELN('---------------       -----------------------------------------');π     WRITELN;π     REPEATπ           SNAP(M1);π           M1 := M1^.NEXT_POINTER;π     UNTIL M1 = NIL;π     WRITELN('------------ END OF LIST----------');πEND;ππPROCEDURE LOAD_MEMBER_HIGH (IND:INTEGER; DAT:ANYSTRING);πVAR M1:LISTPTR;π     P:LISTPTR;                  { INSERTS A RECORD AT THE HIGH }πBEGIN                            { END OF THE LIST.             }π     M1 := ROOT;π     REPEATπ           IF M1^.NEXT_POINTER <> NIL THEN M1 := M1^.NEXT_POINTER;π     UNTIL M1^.NEXT_POINTER = NIL;π     NORMALIZE(NEWSEGMENT, NEWOFFSET);π     M1^.NEXT_POINTER := PTR(NEWSEGMENT, NEWOFFSET);π     P := M1^.NEXT_POINTER;π     P^.INDEX_PART := IND;π     P^.DATA_PART := DAT;π     P^.NEXT_POINTER := NIL;πEND;ππPROCEDURE LOAD_MEMBER_MIDDLE (IND:INTEGER; DAT:ANYSTRING);πVAR M1:LISTPTR;π    M2:LISTPTR;π    P :LISTPTR;π    T :LISTPTR;πBEGIN                         { INSERTS A MEMBER INTO THE MIDDLE }π     M1 := ROOT;              { OF A LIST.                       }π     REPEATπ           M2 := M1;π           IF M1^.NEXT_POINTER <> NIL THEN M1 := M1^.NEXT_POINTER;π     UNTIL (M1^.NEXT_POINTER = NIL) OR (M1^.INDEX_PART >= IND);π     IF (M1^.NEXT_POINTER = NIL) ANDπ        (M1^.INDEX_PART <   IND) THENπ        BEGINπ             LOAD_MEMBER_HIGH (IND, DAT);π             EXIT;π        END;π     T := M2^.NEXT_POINTER;π     NORMALIZE(NEWSEGMENT, NEWOFFSET);π     M2^.NEXT_POINTER := PTR(NEWSEGMENT, NEWOFFSET);π     P := M2^.NEXT_POINTER;π     P^.INDEX_PART := IND;π     P^.DATA_PART := DAT;π     P^.NEXT_POINTER := T;πEND;ππPROCEDURE LOAD_MEMBER (IND:INTEGER; DAT:ANYSTRING);πVAR  M1:LISTPTR;πBEGINπ     WRITELN('ADDING:  ',DAT,' WITH AGE OF ',IND);π     WRITELN('TURBO`S HEAP POINTER:  ',VALUEOF(HEAPPTR),π             ', MEMAVAIL = ',MEMAVAIL * 16.0:8:0);π     WRITELN;π     PAUSE;π     WRITELN('... SEARCHING FOR ADD POINT ...');π     IF ROOT^.INDEX_PART <= IND THEN             { ENTRY POINT ROUTINE FOR }π        BEGIN                                    { ADDING NEW LIST MEMBERS }π             LOAD_MEMBER_MIDDLE(IND, DAT);       { ACTS ONLY IF NEW MEMBER }π             EXIT;                               { SHOULD REPLACE CURRENT  }π        END;                                     { ROOT.                   }π     M1 := ROOT;π     NORMALIZE(NEWSEGMENT, NEWOFFSET);π     ROOT := PTR(NEWSEGMENT, NEWOFFSET);π     ROOT^.INDEX_PART   := IND;π     ROOT^.DATA_PART    := DAT;π     ROOT^.NEXT_POINTER := M1;πEND;ππPROCEDURE INITIALIZE_ROOT_ENTRY(IND:INTEGER; DAT:ANYSTRING);πBEGINπ     ROOT := PTR(NEWSEGMENT, NEWOFFSET);       { INITIALIZES A LIST AND }π     ROOT^.INDEX_PART   := IND;                { ADDS FIRST MEMBER AS   }π     ROOT^.DATA_PART    := DAT;                { "ROOT".                }π     ROOT^.NEXT_POINTER := NIL;πEND;ππBEGINπ     TEXTCOLOR(15);π     IF NOT EMS_INSTALLED THEN DIE('LOCATING EMS DRIVER');π     CLRSCR;π     WRITELN('DEMO OF LINKED LIST IN EXPANDED MEMORY...');π     WRITELN('SETTING UP EMS PARAMETERS...');π     GET_EMS_MEMORY(LOGICAL_PAGES);π     WRITELN;π     WRITELN('ASSIGNED HANDLE:  ',HANDLE);π     NEWSEGMENT := SEGMENT;π     NEWOFFSET  := 0;π     WRITELN('EMS PARAMETERS SET.  BASE PAGE IS:  ',HEXWORD(SEGMENT));π     WRITELN;π     WRITELN('TURBO`S HEAP POINTER IS ',VALUEOF(HEAPPTR));π     WRITELN('READY TO ADD RECORDS...');π     PAUSE;ππ{ Demo:  Create a linked list of names and ages with age as the index/sortπ  key.  Use random numbers for the ages so as to get a different sequenceπ  each time the demo is run.}ππ     INITIALIZE_ROOT_ENTRY(RANDOM(10) + 20, 'Anne Baxter (original root)');π     LOAD_MEMBER(RANDOM(10) + 20,  'Rosie Mallory  ');π     LOAD_MEMBER(RANDOM(10) + 20,  'Sue Perkins    ');π     LOAD_MEMBER(RANDOM(10) + 20,  'Betty Williams ');π     LOAD_MEMBER(RANDOM(10) + 20,  'Marge Holly    ');π     LOAD_MEMBER(RANDOM(10) + 20,  'Lisa Taylor    ');π     LOAD_MEMBER(RANDOM(10) + 20,  'Carmen Abigail ');π     LOAD_MEMBER(RANDOM(10) + 20,  'Rhonda Perlman ');π     PROCESS_LIST;π     KILL_HANDLE(HANDLE);πEND.π                                                        13     01-27-9412:12ALL                      WARREN PORTER            Linked List Queues       IMPORT              32     ╙═m' {π│ I'm trying to understand the rudiments of linked listsππ│ 4) What are common uses for linked lists?  Is any one particular formπ│    (oneway, circular etc ) preferred or used over any other form?ππOne use is to maintain queues.  New people, requests, or jobs come in atπthe end of the line (or break in with priority), but once the head ofπthe line has been serviced, there is no need to maintain its location inπthe queue.  I wrote the following last semester:π---------------------------------------------------------------πPurpose:π  Maintains a queue of jobs and priorities of those jobs in a linked list.π  The user will be prompted for job number and priority and can list theπ  queue, remove a job from the front of the queue (as if it ran), and stopπ  the program.  A count of jobs outstanding at the end will be displayed. }ππtypeπ  PriRange = 0 .. 9;π  JobPnt   = ^JobNode;π  Jobnode  = RECORDπ    Numb     : integer;π    Priority : PriRange;π    Link     : JobPntπ  END;ππprocedure addrec(var Start : JobPnt; comprec : Jobnode);πvarπ  curr,π  next,π  this  : JobPnt;π  found : boolean;πbeginπ  new(this);π  this^.Numb := comprec.Numb;π  this^.Priority := comprec.Priority;π  if Start = NIL thenπ  beginπ    Start := this;   {Points to node just built}π    Start^.Link := NIL; {Is end of list}π  endπ  else    {Chain exists, find a place to insert it}π  if comprec.Priority > Start^.Priority thenπ  beginπ    this^.Link := Start;     {Prep for a new beg of chain}π    Start := thisπ  end {Condition for insert at beg of chain}π  elseπ  begin {Begin loop to insert after beg of chain}π    found := false;  {To initialize}π    curr  := start;π    while not found doπ    beginπ      next := curr^.link;π      if (next = NIL) or (comprec.Priority > next^.Priority) thenπ        found := true;π        if not found thenπ          curr:= next  {another iteration needed}π    end;π    {Have found this^ goes after curr^ and before next^}π    this^.Link := next; {Chain to end (even if NIL)}π    curr^.Link := this;  {Insertion complete}π  end;πend;ππprocedure remove(Var Start : JobPnt);πvarπ  hold : JobPnt;πbeginπ  if Start = NIL thenπ    Writeln('Cannot remove from empty queue', chr(7))π  elseπ  beginπ    hold := Start^.Link; {Save 1st node of new chain}π    dispose(Start);     {Delete org from chain}π    Start := hold;       {Reset to new next job}π  end;πend;ππprocedure list(Start : JobPnt); {List all jobs in queue. "var" omitted}πbeginπ  if Start = NIL thenπ    Writeln('No jobs in queue')π  elseπ  beginπ    Writeln('Job No     Priority');π    Writeln;π    while Start <> NIL doπ    beginπ      Writeln('  ',Start^.Numb : 3, '          ', Start^.Priority);π      Start:=Start^.Linkπ    end;π    Writeln;π    Writeln('End of List');π  end;πend;ππ{Main Procedure starts here}πvarπ  cntr  : integer;π  build : JobNode;π  work,π  Start : JobPnt;π  Achar : char;ππbeginπ  Start := NIL; {Empty at first}π  cntr  := 0;π  REPEATπ    Write('Enter (S)top, (R)emove, (L)ist, or A jobnumb priority to');π    Writeln(' add to queue');π    Read(Achar);ππ    CASE Achar ofπ      'A', 'a' :π      beginπ        Read(build.Numb);π        REPEATπ          Readln(build.Priority);π          if (build.Priority < 0) or (build.priority > 9) thenπ            Write(chr(7), 'Priority between 0 and 9, try again ');π        UNTIL (build.Priority >= 0) and (build.Priority <= 9);π        addrec(Start, build);π      end;ππ      'R', 'r' :π      beginπ        Readln;π        remove(Start);π      end;ππ      'L', 'l' :π      beginπ        Readln;π        list(Start);π      end;ππ      'S', 's' : Readln; {Will wait until out of CASE loop}ππ      elseπ      beginπ        Readln;π        Writeln('Invalid option',chr(7))π      end;π    end;ππ  UNTIL (Achar = 's') or (Achar = 'S');π  work := start;π  while work <> NIL doπ  beginπ    cntr := cntr + 1;π    work := work^.linkπ  end;π  Writeln('Number of jobs remaining in queue: ', cntr);πend.π                              14     02-03-9416:08ALL                      KEN BURROWS              Linked List of Text      IMPORT              24     ╙═══ {πFrom: KEN BURROWSπSubj: Linked List Problemπ---------------------------------------------------------------------------πHere is a short Linked List example. It loads a file, and lets you traverse theπlist in two directions. It's as simple as it gets. You may also want to lookπinto the TCollection objects associated with the Objects unit of Borlandsπversion 6 and 7.π}ππ{$A+,B-,D+,E-,F+,G-,I-,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y+}π{$M 16384,0,655360}πProgram LinkedListOfText; {tested}πUses Dos,CRT;πTypeπ  TextListPtr = ^TextList;π  TextList    = Recordπ                 line : string;π                 next,π                 prev : TextListPtr;π                end;πConstπ  first : TextListPtr = nil;π  last  : TextListPtr = nil;ππProcedure FreeTheList(p:TextListPtr);π   var hold:TextListPtr;π   beginπ     while p <> Nil doπ       beginπ         hold := p;π         p := p^.next;π         dispose(hold);π       end;π   end;ππProcedure ViewForward(p:TextListPtr);π   beginπ     clrscr;π     while p <> nil doπ       beginπ         writeln(p^.line);π         p := p^.next;π       end;π   end;ππProcedure ViewReverse(p:TextListPtr);π   beginπ     clrscr;π     while p <> nil doπ       beginπ         writeln(p^.line);π         p := p^.prev;π       end;π   end;ππProcedure Doit(fname:string);π   var f    :Text;π       s    :string;π       curr,π       hold : TextListPtr;π       stop : boolean;π   beginπ     assign(f,fname);π     reset(f);π     if ioresult <> 0 then exit;π     curr := nil;π     hold := nil;ππ     while (not eof(f)) andπ           (maxavail > SizeOf(TextList)) doπ       begin          {load the list forward and link the prev fields}π         readln(f,s);π         new(curr);π         curr^.prev := hold;π         curr^.next := nil;π         curr^.line := s;π         hold := curr;π      end;π     close(f);ππ     while curr^.prev <> nil do   {traverse the list backwards}π       begin                      {and link the next fields}π         hold := curr;π         curr := curr^.prev;π         curr^.next := hold;π       end;ππ     first := curr;               {set the first and last records}π     while curr^.next <> Nil do curr := curr^.next;π     last := curr;ππ     Repeat   {test it}π       clrscr;π       writeln(' [F]orward view : ');π       writeln(' [R]everse view : ');π       writeln(' [S]top         : ');π       write('enter a command : ');π       readln(s);π       stop := (s = '') or (upcase(s[1]) = 'S');π       if   not stopπ       then case upcase(s[1]) ofπ             'F' : ViewForward(first);π             'R' : ViewReverse(last);π            end;π     Until Stop;ππ     FreeTheList(First);π   end;ππvar m:longint;πBeginπ  m := memavail;π  if   paramcount > 0π  then doit(paramstr(1))π  else writeln('you need to supply a filename');π  if   m <> memavailπ  then writeln('memory error of ',m-memavail,' bytes');πEnd.π                                                                                     15     05-25-9408:21ALL                      ALEXANDER STAUBO         Buffer Streams           SWAG9405            45     ╙═°≡ π{πJB> AS>Use buffered streams.  That way you can access fairly many records onπJB> AS>disk without noticable speed degradation.πJB>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^πJB> Do you mean from RAM?? Whoah! How do you go about using bufferedπJB> streams?ππActually, you should write a local "cache" for your records.  Ie.,πyour implement an array of records, say 1..50, or, 1..MaxCacheSize,πwhere MaxCacheSize is a defined constant.  Then you have a couple ofπgeneralized procedures for putting/getting records; now, the point is,πwhenever the program asks for a record -that is in the cache-, thatπrecord is read directly from RAM.  If the record is -not- in theπcache, the record is read, and, if there is space in the cache, theπrecord is inserted into the cache.ππLet's try a Pascal implementation.π}ππ        constπ          MaxCacheSize = 50; (* cache can hold 50 records *)ππ        typeπ          (* this is the cache item *)π          PCacheItem = ^TCacheItem;π          TCacheItem =π            recordπ              Offset : Longint; (* file offset of cache record *)π              Rec    : TRecord; (* use your own record type here *)π            end;ππ        varπ          Cache : array[1..MaxCacheSize] of PCacheItem;π          CacheSize : Word;ππ        procedure InitCache;π          {-Resets cache}π        beginπ          CacheSize:=0;π        end;ππ        function FindCache (Offset : Longint) : PCacheItem;π          {-Returns cache item for Offset if found, otherwise nil}π        varπ          W : Word;π        beginπ          for W:=1 to CacheSize doπ            if Cache[W]^.Offset = Offset thenπ              beginπ                FindCache:=Cache[W];π                Exit;π              end;π          FindCache:=nil;π        end;ππ        varπ          F : file of TRecord; (* file in question *)ππ        procedure PutRecord (Offset : Longint; var Rec : TRecord);π          {-Put record into cache and file}π        varπ          P : PCacheItem;π        beginπ          Write(F, Rec);ππ          (* if exists in RAM (cache), update it *)π          P:=FindCache(Offset);π          if P <> nil thenπ            P^.Rec:=Recπ          elseπ            beginπ              (* put into cache *)π              Inc(CacheSize);π              New(Cache[CacheSize]);π              Cache[CacheSize]^.Offset:=Offset;π              Cache[CacheSize]^.Rec:=Rec;π            end;π        end;ππ        procedure GetRecord (Offset : Longint; var Rec : TRecord);π          {-Get record from cached file}π        varπ          P : PCacheItem;π        beginπ          (* if exists in RAM (cache), get it *)π          P:=FindCache(Offset);π          if P <> nil thenπ            Rec:=P^.Recπ          else if CacheSize < MaxCacheSize thenπ            beginπ              (* read record from file *)π              Read(F, Rec);ππ              (* put into cache *)π              Inc(CacheSize);π              New(Cache[CacheSize]);π              Cache[CacheSize]^.Offset:=Offset;π              Cache[CacheSize]^.Rec:=Rec;π            end;π        end;ππTo use the routines:ππ          Assign(F, 'MYFILE.DAT');π          Reset(F);π          GetRecord(FilePos(F), MyRec);π          GetRecord(FilePos(F), MyRec);π          GetRecord(FilePos(F), MyRec);π          PutRecord(FilePos(F), MyRec);π          Close(F);ππOr something like that, anyway.ππNow, there is a simpler way; "simpler" in this case means "some guyπhas already spent hours writing it just for you".  The concept isπcalled streams.  Now, I don't know how "novice" a programmer you are,πbut knowledge of streams requires knowledge of OOP.  I suggest youπread about OOP right away.ππStreams work in a very simple way.  You have a basic, "abstract"πobject, which provides some simple I/O tools.  A stream is a type ofπ(abstract) file, an input/output mechanism, that you may manipulate;πmost often it's on a hierarchical level, ie., the high-levelπprocedures call low-level procedures, just like DOS.  Think of streamsπas the Pascal type "file", except now the stream is a shell forπanything.ππThe shell implements a -standard- interface for any kind ofπinformation area.  You have file streams, buffered streams (streamsπthat caches areas of the file in memory to optimize accessπefficiency), EMS streams (yes, you can have a "virtual file" that liesπin EMS memory and may be used just like a file), and so on.  Theπstandardization implies that you may write more flexible programs.ππA tiny example:ππ        varπ          S   : TBufStream;π          T   : TRecord;π          Str : string;π        beginπ          S.Init('MYFILE.DAT', stOpen, 2048);π              (* |             |          |π                 file name     file mode  buffer sizeπ              *)π          S.Read(T, SizeOf(T));π          S.Write(T, SizeOf(T));π          Str:=S.ReadStr^;ππ          S.Done;π        end;ππThe corresponding boring-old-Dos example'd be:ππ        varπ          F   : file;π          T   : TRecord;π          Str : string;π        beginπ          (* note: no buffering -> slower! *)π          Assign(F, 'MYFILE.DAT');π          Reset(F, 1);ππ          BlockRead(F, T, SizeOf(T));π          BlockWrite(F, T, SizeOf(T));π          Read(F, Str[0]);π          BlockRead(F, Str[1], Ord(Str[0]));ππ          Close(F);π        end;ππIn the end, streams -are- simpler, too.  And they are extremely fast;πa friend of mine is writing a mail reader and is using object streamsπfor the message/conference/etc. databases.  Now, personally I useπindexed, light-speed B-tree databases.  And his work -just fine-.π                                                                  16     05-26-9411:06ALL                      BILL ZECH                Linked List Routine      IMPORT              65     ╙═≤ π{ Links Unit - Turbo Pascal 5.5π  Patterned after the list processing facility in Simula class SIMSET.π  Simula fans will note the same naming conventions as Simula-67.ππ  Written by Bill Zech @CIS:[73547,1034]), May 16, 1989.ππ  The Links unit defines objects and methods useful for implementingπ  list (set) membership in your own objects.ππ  Any object which inherits object <Link> will acquire the attributesπ  needed to maintain that object in a doubly-linked list.  Because theπ  Linkage object only has one set of forward and backward pointers, aπ  given object may belong to only one list at any given moment.  Thisπ  is sufficient for many purposes.  For example, a task control blockπ  might belong in either a ready list, a suspended list, or a swappedπ  list, but all are mutually exclusive.ππ  A list is defined as a head node and zero or more objects linkedπ  to the head node.  A head node with no other members is an emptyπ  list.  Procedures and functions are provided to add members to theπ  end of the list, insert new members in position relative to anπ  existing member, determine the first member, last member, sizeπ  (cardinality) of the list, and to remove members from the list.ππ  Because your object inherits all these attributes, your programπ  need not concern itself with allocating or maintaining pointersπ  or other stuff.  All the actual linkage mechanisms will beπ  transparent to your object.ππ  *Note*π      The following discussion assumes you have defined your objectsπ      as static variables instead of pointers to objects.  For mostπ      programs, dynamic objects manipulated with pointers will beπ      more useful.  Some methods require pointers as arguments.π      Example program TLIST.PAS uses pointer type variables.ππ  Define your object as required, inheriting object Link:ππ        typeπ            myObjType = object(Link)π                xxx.....xxxxπ            end;ππ  To establish a new list, declare a variable for the head nodeπ  as a type Head:ππ        varπ            Queue1    :Head;π            Queue2    :Head;ππ    Define your object variables:ππ        varπ            X    : myObjType;π            Y    : myObjType;π            Z    : myObjType;π            P    :^myObjType;ππ    Make sure the objects have been Init'ed as required for dataπ    initialization, VMT setup, etc.ππ            Queue1.Init;π            Queue2.Init;π            X.Init;π            Y.Init;π            Z.Init;ππ    You can add your objects to a list with <Into>:π    (Note the use of the @ operator to make QueueX a pointer to theπ     object.)ππ        beginπ            X.Into(@Queue1);π            Y.Into(@Queue2);ππ    You can insert at a specific place with <Precede> or <Follow>:ππ            Z.Precede(@Y);π            Z.Follow(@Y);ππ    Remove an object with <Out>:ππ            Y.Out;ππ    Then add it to another list:ππ            Y.Into(@Queue1);ππ    Note that <Into>, <Precede> and <Follow> all have a built-inπ    call to Out, so to move an object from one list to another canπ    be had with a single operation:ππ            Z.Into(@Queue1);ππ    You can determine the first and last elements with <First> and <Last>:π    (Note the functions return pointers to objects.)ππ            P := Queue1.First;π            P := Queue1.Last;ππ    The succcessor or predecessor of a given member can be found withπ    fucntions <Suc> and <Pred>:ππ            P := X.Pred;π            P := Y.Suc;π            P := P^.Suc;ππ    The number of elements in a list is found with <Cardinal>:ππ            N := Queue1.Cardinal;ππ    <Empty> returns TRUE is the list has no members:ππ            if Queue1.Empty then ...ππ    You can remove all members from a list with <Clear>:ππ            Queue1.Clear;ππ    GENERAL NOTES:ππ        The TP 5.5 type compatibility rules allow a pointer to aπ        descendant be assigned to an ancestor pointer, but not vice-versa.π        So although it is perfectly legal to assign a pointer toπ        type myObjType to a pointer to type Linkage, it won't letπ        us do it the opposite.ππ        We would like to be able to assign returned values fromπ        Suc, Pred, First, and Last to pointers of type myObjType,π        and the least fussy way is to define these pointer typesπ        internal to this unit as untyped pointers.  This works fineπ        because all we are really doing is passing around pointersπ        to Self, anyway.  The only down-side to this I have noticedπ        is you can't do:  P^.Suc^.Pred because the returned pointerπ        type cannot be dereferenced without a type cast.π}ππunit Links;ππinterfaceππtypeππ  pLinkage = ^Linkage;π  pLink = ^Link;π  pHead = ^Head;ππ  Linkage = objectπ      prede :pLinkage;π      succ  :pLinkage;π      function Suc  :pointer;π      function Pred :pointer;π      constructor Init;π  end;ππ  Link = object(Linkage)π      procedure Out;π      procedure Into(s :pHead);π      procedure Follow (x :pLinkage);π      procedure Precede(x :pLinkage);π  end;ππ  Head = object(Linkage)π      function First :pointer;π      function Last  :pointer;π      function Empty :boolean;π      function Cardinal :integer;π      procedure Clear;π      constructor Init;π  end;ππππimplementationππconstructor Linkage.Init;πbeginπ  succ := NIL;π  prede := NIL;πend;ππfunction Linkage.Suc :pointer;πbeginπ  if TypeOf(succ^) = TypeOf(Head) thenπ     Suc := NILπ  else Suc := succ;πend;ππfunction Linkage.Pred :pointer;πbeginπ  if TypeOf(prede^) = TypeOf(Head) thenπ     Pred := NILπ  else Pred := prede;πend;ππprocedure Link.Out;πbeginπ    if succ <> NIL thenπ    beginπ      succ^.prede := prede;π      prede^.succ := succ;π      succ := NIL;π      prede := NIL;π    end;πend;ππprocedure Link.Follow(x :pLinkage);πbeginπ    Out;π    if x <> NIL thenπ    beginπ      if x^.succ <> NIL thenπ      beginπ          prede := x;π          succ := x^.succ;π          x^.succ := @Self;π          succ^.prede := @Self;π      end;π    end;πend;πππprocedure Link.Precede(x :pLinkage);πbeginπ    Out;π    if x <> NIL thenπ    beginπ        if x^.succ <> NIL thenπ        beginπ            succ := x;π            prede := x^.prede;π            x^.prede := @Self;π            prede^.succ := @Self;π        end;π    end;πend;ππprocedure Link.Into(s :pHead);πbeginπ    Out;π    if s <> NIL thenπ    beginπ        succ := s;π        prede := s^.prede;π        s^.prede := @Self;π        prede^.succ := @Self;π    end;πend;πππfunction Head.First :pointer;πbeginπ    First := suc;πend;ππfunction Head.Last :pointer;πbeginπ    Last := Pred;πend;ππfunction Head.Empty :boolean;πbeginπ  Empty := succ = prede;πend;ππfunction Head.Cardinal :integer;πvarπ    i   :integer;π    p   :pLinkage;πbeginπ    i := 0;π    p := succ;π    while p <> @Self doπ      beginπ          i := i + 1;π          p := p^.succ;π      end;π    Cardinal := i;πend;ππprocedure Head.Clear;πvarπ    x  : pLink;πbeginπ    x := First;π    while x <> NIL doπ      beginπ          x^.Out;π          x := First;π      end;πend;ππconstructor Head.Init;πbeginπ  succ := @Self;π  prede := @Self;πend;ππend.ππ{------------------------   DEMO PROGRAM --------------------- }ππprogram tlist;ππuses Links;ππtypeπ    NameType = string[10];π    person = object(link)π        name :NameType;π        constructor init(nameArg :NameType);π    end;π    Pperson = ^person;ππconstructor person.init(nameArg :NameType);πbeginπ    name := nameArg;π    link.init;πend;ππvarπ    queue : Phead;π    man   : Pperson;π    man2  : Pperson;π    n     : integer;π    tf    : boolean;ππbeginπ    new(queue,Init);π    tf := queue^.Empty;π    new(man,Init('Bill'));π    man^.Into(queue);π    new(man,Init('Tom'));π    man^.Into(queue);π    new(man,Init('Jerry'));π    man^.Into(queue);ππ    man := queue^.First;π    writeln('First man in queue is ',man^.name);π    man := queue^.Last;π    writeln('Last man in queue is ',man^.name);ππ    n := queue^.Cardinal;π    writeln('Length of queue is ',n);π    if not queue^.Empty then writeln('EMPTY reports queue NOT empty');ππ    new(man2,Init('Hugo'));π    man2^.Precede(man);ππ    new(man2,Init('Alfonso'));π    man2^.Follow(man);π    { should now be: Bill Tom Hugo Jerry Alfonso }π    writeln('After PRECEDE and FOLLOW calls, list should be:');π    writeln('  {Bill, Tom, Hugo, Jerry, Alfonso}');π    writeln('Actual list is:');ππ    man := queue^.First;π    while man <> NIL doπ      beginπ          write(man^.name,' ');π          man := man^.Suc;π      end;π      writeln;ππ    man := queue^.Last;π    writeln('The same list backwards is:');π    while man <> NIL doπ      beginπ         write(man^.name,' ');π         man := man^.Pred;π      end;π      writeln;ππ    n := queue^.Cardinal;π    writeln('Queue size should be 5 now, is: ', n);ππ    queue^.Clear;π    writeln('After clear operation,');π    n := queue^.Cardinal;π    writeln('   Queue size is ',n);π    tf := queue^.Empty;π    if tf then writeln('    and EMTPY reports queue is empty.');π    writeln;π    writeln('Done with test.');πend.ππ                                                                                                                               17     08-24-9413:32ALL                      KEN BURROWS              Duplicate File/String    SWAG9408    !╖û    16     ╙═   {π MG>    Trying to figure out the fastest wayπ MG> to find and delete duplicate strings,π MG> which are actually file names in anπ MG> ASCII file.ππUsing the strings and objects unit, pstringcollections can be used to sort andπtest for dupes quite easilly.π}ππUses Objects,Strings,Dos;ππConstπ  inFile  : String = '';π  OutFile : String = '';π  DupFile : String = '';ππTypeπ  NewPCol = Object(TStringCollection)π              function compare(key1,key2:pointer):integer; virtual;π            end;π PSColl  = ^NewPCol;ππFunction NewPCol.Compare(key1,key2:pointer):integer;π   Beginπ     Compare := StrIComp(key1,key2);π   End;ππProcedure Doit;π   Var NewLst,π       DupLst : PSColl;π       s      : string;π       ps     : pstring;π       f      : text;π       i      : integer;π   Procedure WriteEm(pst:Pstring); far;π      beginπ        writeln(f,pst^);π      end;π   Beginπ     New(NewLst,init(5,5));π     New(DupLst,init(5,5));π     DupLst^.Duplicates := true;π     assign(f,InFile);  reset(f);π     While not Eof(f) doπ       Beginπ         readln(f,s);π         if   s <> ''π         then beginπ                ps := newstr(s);π                i := NewLst^.Count;π                NewLst^.insert(ps);π                if i = NewLst^.Count then DupLst^.insert(ps);π              end;π       End;π     close(f);π     if   NewLst^.count > 0π     then beginπ            assign(f,OutFile); rewrite(f);π            NewLst^.forEach(@WriteEm);π            close(f);π          end;π     if   DupLst^.Count > 0π     then beginπ            assign(f,DupFile); rewrite(f);π            DupLst^.forEach(@WriteEm);π            close(f);π          end;π     dispose(DupLst,done);π     dispose(NewLst,Done);π  End;ππBeginπ  if paramcount < 2 then halt;π  InFile := paramstr(1);π  OutFile := paramstr(2);π  DupFile := OutFile;π  Dec(DupFile[0],3);π  DupFile := DupFile + 'DUP';π  if DupFile = OutFile then halt;π  Doit;πEnd.ππ         18     08-24-9413:44ALL                      SWAG SUPPORT TEAM        Example of LINKED RecordsSWAG9408    εε╒    35     ╙═   program LinkLst2;ππusesπ  Crt;ππconstπ  FileName = 'LinkExp.dta';ππtypeπ  PMyNode = ^TMyNode;π  TMyNode = recordπ    Name  : String;π    Flight: integer;π    Day   : String;π    Next  : PMyNode;  {Used to link each field}π  end;ππprocedure CreateNew(var Item: PMyNode);πbeginπ  New(Item);π  Item^.Next := nil;π  Item^.Name := '';π  Item^.Flight := 0;π  Item^.Day := '';πend;ππprocedure GetData(var Item: PMyNode);πbeginπ  ClrScr;π  repeatπ    GotoXY(1, 1);π    Write('Enter Name: ');π    Read(Item^.Name);π  until (Item^.Name <> '');π  GotoXY(1, 2);π  Write('Enter Flight number: ');π  ReadLn(Item^.Flight);π  GotoXY(1, 3);π  Write('Enter Day: ');π  ReadLn(Item^.Day);πend;ππprocedure DoFirst(var First, Current: PMyNode);πbeginπ  CreateNew(Current);π  GetData(Current);π  First := Current;πend;ππprocedure Add(var Prev, Current: PMyNode);πbeginπ  Prev := Current;π  CreateNew(Current);π  GetData(Current);π  Prev^.Next := Current;πend;ππprocedure DeleteNode(var Head, Node, Current: PMyNode);πvarπ  Temp: PMyNode;πbeginπ  Temp := Head;π  while Temp^.Next <> Node doπ    Temp := Temp^.Next;π  if Temp^.Next^.Next <> nil thenπ    Temp^.Next := Temp^.Next^.Nextπ  else beginπ    Temp^.Next := nil;π    Current := Temp;π  end;π  Dispose(Node);πend;ππfunction Find(Head: PMyNode; S: String): PMyNode;πvarπ  Temp: PMyNode;πbeginπ  Temp := nil;π  while Head^.Next <> nil do beginπ    if Head^.Name = S then beginπ      Temp := Head;π      break;π    end;π    Head := Head^.Next;π  end;π  if Head^.Name = S then Temp := Head;π  Find := Temp;πend;ππprocedure DoDelete(var Head, Current: PMyNode);πvarπ  S: String;π  Temp: PMyNode;πbeginπ  ClrScr;π  Write('Enter name from record to delete: ');π  ReadLn(S);π  Temp := Find(Head, S);π  if Temp <> nil thenπ    DeleteNode(Head, Temp, Current);πend;ππprocedure ShowRec(Item: PMyNode; i: Integer);πbeginπ  GotoXY(1, i); Write('Name: ', Item^.Name);π  GotoXY(25, i); Write('Flight: ', Item^.Flight);π  GotoXY(45, i); Write('Day: ', Item^.Day);πend;ππprocedure Show(Head: PMyNode);πvarπ  i: Integer;πbeginπ  i := 1;π  ClrScr;π  while Head^.Next <> nil do beginπ    Head := Head^.Next;π    ShowRec(Head, i);π    Inc(i);π  end;π  WriteLn;π  WriteLn('==========================================================');π  WriteLn(i, ' records shown');π  ReadLn;πend;ππprocedure FreeAll(var Head: PMyNode);πvarπ  Temp: PMyNode;πbeginπ  while Head^.Next <> nil do beginπ    Temp := Head^.Next;π    Dispose(Head);π    Head := Temp;π  end;π  Dispose(Head);πend;ππprocedure CreateNewFile(Head: PMyNode);πvarπ  F: File of TMyNode;πbeginπ  Assign(F, FileName);π  ReWrite(F);π  while Head^.Next <> nil do beginπ    Write(F, Head^);π    Head := Head^.Next;π  end;π  Write(F, Head^);π  Close(F);πend;ππprocedure ReadFile(var First, Prev, Current: PMyNode);πvarπ  F: File of TMyNode;πbeginπ  Assign(F, FileName);π  Reset(F);π  CreateNew(Current);π  Read(F, Current^);π  First := Current;π  while not Eof(F) do beginπ    Prev := Current;π    CreateNew(Current);π    Read(F, Current^);π    Prev^.Next := Current;π  end;π  Close(F);πend;ππprocedure Main(var First, Prev, Current: PMyNode);πvarπ  F      : Text;πbeginπ  {$I-}π  Assign (f, 'HW2FILE.TXT');π  Reset(f);π  {$I+}π  if (IOResult <> 0) then beginπ    WriteLn('error Reading File');π    Halt;π  end;π  CreateNew(Current);π  ReadLn(F, Current^.Name);π  ReadLn(F, Current^.Flight);π  ReadLn(F, Current^.Day);π  First := Current;π  while not Eof(F) do beginπ    Prev := Current;π    CreateNew(Current);π    ReadLn(F, Current^.Name);π    ReadLn(F, Current^.Flight);π    ReadLn(F, Current^.Day);π    Prev^.Next := Current;π  end;π  Close(F);π  Show(First);π  CreateNewFile(First);πend;ππfunction WriteMenu: Char;πvarπ  Ch: Char;πbeginπ  ClrScr;π  GotoXY(1, 1);π  WriteLn('A) Add');π  WriteLn('D) Delete');π  WriteLn('S) Show');π  WriteLn('W) Write File');π  WriteLn('X) Exit');π  repeatπ    Ch := UpCase(ReadKey);π  until Ch in ['A', 'D', 'S', 'W', 'X'];π  WriteMenu := Ch;πend;ππvarπ  Ch: Char;π  First,π  Prev,π  Current: PMyNode;ππbeginπ  ClrScr;π  {  Main(First, Prev, Current); Use this option to read text file }π  ReadFile(First, Prev, Current);π  repeatπ    Ch := WriteMenu;π    case Ch ofπ      'A': Add(Prev, Current);π      'D': DoDelete(First, Current);π      'S': Show(First);π      'W': CreateNewFile(First);π    end;π  until Ch = 'X';πend.πend. { main program}π            19     08-24-9413:45ALL                      SWAG SUPPORT TEAM        Linked List Routine      SWAG9408     UJ╒    12     ╙═   typeπ  PDataRec = ^TDataRec;π  TDataRec = recordπ    Name: String;π    Next: PDataRec;π  end;ππconstπ  DataRecList: PDataRec = nil;π  CurRec :PDataRec = nil;ππprocedure AddRec(AName: String);πvar Temp: PDataRec;πbeginπ  New(CurRec);π  CurRec^.Name := AName;π  CurRec^.Next := nil;π  Temp := DataRecList;π  if Temp = nil thenπ    DataRecList := CurRecπ  elseπ    beginπ      while Temp^.Next <> nil do Temp := Temp^.Next;π      Temp^.Next := CurRec;π    end;πend;ππprocedure PrevRec;πvar Temp: PDataRec;πbeginπ  Temp := DataRecList;π  if Temp <> CurRec thenπ    while Temp^.Next <> CurRec do Temp := Temp^.Next;π  CurRec := Temp;πend;ππprocedure NextRec;πbeginπ  if CurRec^.Next <> nil then CurRec := CurRec^.Next;πend;ππprocedure List;πvar Temp: PDataRec;πbeginπ  Temp := DataRecList;π  while Temp <> nil doπ    beginπ      Write(Temp^.Name);π      if Temp = CurRec thenπ        Writeln(' <<Current Record>>')π      elseπ        Writeln;π      Temp := Temp^.Next;π    end;πend;ππbeginπ  AddRec('Tom');  AddRec('Dick'); AddRec('Harry');  AddRec('Fred');π  Writeln('Original List');π  List;π  Writeln;π  Readln;ππ  PrevRec; PrevRec;π  Writeln('After Two PrevRec Calls');π  List;π  Writeln;π  Readln;ππ  NextRec;π  Writeln('After One NextRec Call');π  List;π  Writeln;π  Readln;ππ  Writeln('End of Program.');πend.                                                                                                 20     08-24-9413:49ALL                      GUY MCLOUGHLIN           Double Linked Lists      SWAG9408    ╒@pÑ    39     ╙═   πprogram Demo_Doubly_Linked_List_Sort;ππconstπ  co_MaxNode = 1000;ππtypeπ  T_St15   = string[15];ππ  T_PoNode = ^T_Node;ππ  T_Node   = recordπ               Data : T_St15;π               Next,π               Prev : T_PoNodeπ             end;ππ  T_PoArNodes  = ^T_ArNodePtrs;π  T_ArNodePtrs = array[1..succ(co_MaxNode)] of T_PoNode;πππ  function RandomString : {output}π                           T_St15;π  varπ    by_Index : byte;π    st_Temp  : T_St15;π  beginπ    st_Temp[0] := chr(succ(random(15)));π    for by_Index := 1 to length(st_Temp) doπ      st_Temp[by_Index] := chr(random(26) + 65);π    RandomString := st_Tempπ  end;ππ  procedure AddNode({update}π                     varπ                       po_Node : T_PoNode);π  beginπ    if (maxavail > sizeof(T_Node)) thenπ      beginπ        new(po_Node^.Next);π        po_Node^.Next^.Next := nil;π        po_Node^.Next^.Prev := po_Node;π        po_Node^.Next^.Data := RandomStringπ      endπ  end;ππ  procedure DisplayList({input}π                         po_Node : T_PoNode);π  varπ    po_Temp : T_PoNode;π  beginπ    po_Temp := po_Node;π    repeatπ      write(po_Temp^.Data:20);π      po_Temp := po_Temp^.Nextπ    until (po_Temp^.Next = nil);π    write(po_Temp^.Data:20)π  end;ππ  procedure ShellSortNodes ({update}π                             varπ                               ar_Nodes   : T_ArNodePtrs;π                            {input }π                             wo_NodeTotal : word);π  varπ    Temp   : T_PoNode;π    Index1,π    Index2,π    Index3 : word;π  beginπ    Index3 := 1;π    repeatπ      Index3 := succ(3 * Index3)π    until (Index3 > wo_NodeTotal);π    repeatπ      Index3 := (Index3 div 3);π      for Index1 := succ(Index3) to wo_NodeTotal doπ        beginπ          Temp := ar_Nodes[Index1];π          Index2 := Index1;π          while (ar_Nodes[(Index2 - Index3)]^.Data > Temp^.Data) doπ            beginπ              ar_Nodes[Index2] := ar_Nodes[(Index2 - Index3)];π              Index2 := (Index2 - Index3);π              if (Index2 <= Index3) thenπ                breakπ            end;π          ar_Nodes[Index2] := Tempπ        endπ    until (Index3 = 1)π  end;        (* ShellSortNodes.                                      *)ππ  procedure RebuildList({input }π                         varπ                           ar_Nodes : T_ArNodePtrs;π                        {update}π                         varπ                           po_Head  : T_PoNode);π  varπ    wo_Index   : word;π    po_Current : T_PoNode;π  beginπ    wo_Index := 1;π    po_Head := ar_Nodes[wo_Index];π    po_Head^.Prev := nil;π    po_Head^.Next := ar_Nodes[succ(wo_Index)];π    po_Current := po_Head;π    repeatπ      inc(wo_Index);π      po_Current := po_Current^.Next;π      po_Current^.Next := ar_Nodes[succ(wo_Index)];π      po_Current^.Prev := ar_Nodes[pred(wo_Index)]π    until (ar_Nodes[succ(wo_Index)] = nil)π  end;ππvarπ  wo_Index    : word;ππ  po_Heap     : pointer;ππ  po_Head,π  po_Current   : T_PoNode;ππ  po_NodeArray : T_PoArNodes;ππBEGINπ              (* Initialize pseudo-random number generator.           *)π  randomize;ππ              (* Mark initial HEAP state.                             *)π  mark(po_Heap);ππ              (* Initialize list head node.                           *)π  new(po_Head);π  with po_Head^ doπ    beginπ      Next := nil;π      Prev := nil;π      Data := RandomStringπ    end;ππ              (* Create doubly linked list of random strings.         *)π  po_Current := po_Head;π  for wo_Index := 1 to co_MaxNode doπ    beginπ      AddNode(po_Current);π      if (wo_Index < co_MaxNode) thenπ        po_Current := po_Current^.Nextπ    end;ππ  writeln('Total Nodes = ', wo_Index);π  readln;ππ  DisplayList(po_Head);π  writeln;π  writeln;ππ              (* Allocate array of node pointers on the HEAP.         *)π  if (maxavail > sizeof(T_ArNodePtrs)) thenπ    new(po_NodeArray);ππ              (* Set them all to NIL.                                 *)π  fillchar(po_NodeArray^, sizeof(po_NodeArray^), 0);ππ              (* Assign pointer in array to nodes.                    *)π  wo_Index := 0;π  po_Current := po_Head;π  repeatπ    inc(wo_Index);π    po_NodeArray^[wo_Index] := po_Current;π    po_Current := po_Current^.Nextπ  until (po_Current^.Next = nil);ππ              (* ShellSort the array of nodes.                        *)π  ShellSortNodes(po_NodeArray^, wo_Index);ππ              (* Re-build the doubly linked-list from array of nodes. *)π  RebuildList(po_NodeArray^, po_Head);ππ              (* Deallocate array of nodes.                           *)π  dispose(po_NodeArray);ππ  writeln;π  writeln;π  DisplayList(po_Head);ππ              (* Release HEAP memory used.                            *)π  release(po_Heap)ππEND.ππ                                                                                                                           21     08-24-9413:49ALL                      MARK GAUTHIER            OOP Linked Lists         SWAG9408    ;¿y    70     ╙═   Unit MgLinked;ππinterfaceππconstππ      { Error list. }π      Succes       = $00;π      Need_Mem     = $01;π      Point_To_Nil = $02;ππtypeππ  DoubleLstPtr = ^DoubleLst;π  DoubleLst    = recordπ                   Serial       : longint;π                   Size         : word;π                   Addresse     : pointer;π                   Next         : DoubleLstPtr;π                   Previous     : DoubleLstPtr;π                 end;πππ  PDoubleLst = ^ODoubleLst;π  ODoubleLst = objectππ    privateπ    LastCodeErr : word;          {-- Last error.         --}ππ    publicπ    TotalObj    : longint;       {-- Total obj allocate. --}π    CurentObj   : DoubleLstPtr;  {-- Curent obj number.  --}ππ    constructor Init(var Install:boolean; Serial:longint; Size:word;πData:pointer);π    {-- Initialise all variables, new curent.    ---}ππ    destructor Done;ππ    {--- get and clear the last err. ---}π    function  LastError:word;ππ    {--- Seek to end and add an object.                            ---}π    procedure Add(Size:word; Data:pointer);ππ    {--- Change the size of data of a object. 0 = change curent.   ---}π    procedure ChangeSize(Serial:longint; NewSize : word);ππ    {--- Insert an object before the curent obj. 0 = insert curent pos ---}π    procedure Insert(Serial:longint; Size:word; Data:pointer);ππ    {--- Delete an object from the list.  0 = delete curent.       ---}π    procedure Delete(Serial:longint);ππ    {--- Pointe on next or end, etc.                               ---}π    procedure SeekFirst;π    procedure SeekLast;π    procedure SeekNext;π    procedure SeekPrevious;π    procedure SeekNum(Serial:longint);ππ    {--- Move data from obj to user buffer                          ---}π    {--- 0 = use curent object.                                     ---}π    function MoveObjToPtr(Serial:longint; p:pointer):word;ππ    {--- Move user buffer to obj data.  obj data take ObjSize bytes ---}π    {--- 0 = use curent object.                                     ---}π    function MovePtrToObj(Serial:longint; p:pointer):word;ππ  end;ππimplementationππ(****************************************************************************)ππ procedure move(Src,Dst:pointer; Size:word);assembler;π asmπ    lds si,Srcπ    les di,Dstπ    mov cx,Sizeπ    cldπ    rep movsbπ end;πππ(****************************************************************************)ππconstructor ODoubleLst.Init(var Install:boolean; Serial:longint; Size:word;πData:pointer);π{-- Initialise all variables, new curent.    ---}πbeginπ     Install := false;π     if Serial = 0 then exit;π     New(CurentObj);π     if CurentObj = nil then exit;π     GetMem(CurentObj^.Addresse, Size);π     if CurentObj^.Addresse = nil thenπ     beginπ          LastCodeErr := Need_Mem;π          exit;π     end;ππ     CurentObj^.Next     := nil;π     CurentObj^.Previous := nil;π     CurentObj^.Size     := Size;π     CurentObj^.Serial   := Serial;π     move(Data, CurentObj^.Addresse, Size);ππ     TotalObj := 1;ππ     Install             := true;π     LastCodeErr         := Succes;πend;ππ(****************************************************************************)ππdestructor ODoubleLst.Done;π{-- Initialise all variables, new curent.    ---}πbeginπ     repeat delete(0);π     until (LastError <> Succes) or (TotalObj <= 0);πend;ππ(****************************************************************************)ππfunction  ODoubleLst.LastError:word;π{--- get and clear the last err. ---}πbeginπ     LastError   := LastCodeErr;π     LastCodeErr := 0;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.Add(Size:word; Data:pointer);π{--- Seek to end and add an object.                            ---}πbeginπ     repeat SeekNext until LastError <> Succes; { SeekEnd }ππ     New(CurentObj^.Next);π     if CurentObj^.Next = nil thenπ     beginπ          LastCodeErr := Need_Mem;π          exit;π     end;ππ     GetMem(CurentObj^.Next^.Addresse, Size);π     if CurentObj^.Next^.Addresse = nil thenπ     beginπ          LastCodeErr := Need_Mem;π          exit;π     end;ππ     CurentObj^.Next^.Size := Size;ππ     { Store information data. }π     move(Data, CurentObj^.Next^.Addresse, Size);ππ     { Increment the total number of reccords. }π     inc(TotalObj);ππ     CurentObj^.Next^.Next := nil;π     CurentObj^.Next^.Previous := CurentObj;ππ     LastCodeErr := Succes;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.ChangeSize(Serial:longint; NewSize : word);π{--- Change the size of an object.                             ---}πvar p:pointer;πbeginπ     getmem(p,NewSize);π     if p = nil thenπ     beginπ          LastCodeErr := Need_mem;π          exit;π     end;π     SeekNum(Serial);π     move(CurentObj^.Addresse, p, NewSize);π     freemem(CurentObj^.Addresse, CurentObj^.Size);π     CurentObj^.Size := NewSize;π     CurentObj^.Addresse := p;π     LastCodeErr := Succes;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.Insert(Serial:longint; Size:word; Data:pointer);π{--- Insert an object before the curent obj.                   ---}πVar n:DoubleLstPtr;πbeginπ     new(n);π     if n = nil thenπ     beginπ          LastCodeErr := Need_mem;π          exit;π     end;π     SeekNum(Serial);π     getmem(n^.Addresse, Size);π     if n^.Addresse = nil thenπ     beginπ          LastCodeErr := Need_mem;π          exit;π     end;ππ     n^.Size := Size;π     move(Data, n^.Addresse, Size);ππ     n^.Previous := CurentObj^.Previous;π     n^.Next     := CurentObj;ππ     CurentObj^.Previous^.Next := n;π     CurentObj^.Previous       := n;ππ     inc(TotalObj);πend;ππ(****************************************************************************)ππprocedure ODoubleLst.Delete(Serial:longint);π{--- Delete an object from the list.                           ---}πbeginπ     SeekNum(Serial);π     if CurentObj^.Addresse <> nil thenπ     beginπ           FreeMem(CurentObj^.Addresse,CurentObj^.Size);π          CurentObj^.Addresse := nil;π     end;ππ     CurentObj^.Next^.Previous := CurentObj^.Previous;π     CurentObj^.Previous^.Next := CurentObj^.Next;ππ     if CurentObj <> nil then Dispose(CurentObj);π     CurentObj := CurentObj^.Previous;ππ     dec(TotalObj);πend;ππ(****************************************************************************)ππprocedure ODoubleLst.SeekLast;πbeginπ     repeat SeekNext until LastError <> Succes;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.SeekFirst;πbeginπ     repeat SeekPrevious until LastError <> Succes;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.SeekNext;πbeginπ     if CurentObj^.Next = nil thenπ     beginπ          LastCodeErr := Point_To_Nil;π          exit;π     end;π     CurentObj := CurentObj^.Next;π     LastCodeErr := Succes;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.SeekPrevious;πbeginπ     if CurentObj^.Previous = nil thenπ     beginπ          LastCodeErr := Point_To_Nil;π          exit;π     end;π     CurentObj := CurentObj^.Previous;π     LastCodeErr := Succes;πend;ππ(****************************************************************************)ππprocedure ODoubleLst.SeekNum(Serial:longint);πbeginπ     if Serial = 0 then exit;π     SeekFirst;π     repeatππ           SeekNext;ππ           if CurentObj^.Serial = Serial thenπ           beginπ                LastCodeErr := Succes;π                break;π           end;ππ           if LastError <> Succes thenπ           beginπ                LastCodeErr := Point_To_Nil;π                break;π           endπ           else continue;ππ     until false;ππend;ππ(****************************************************************************)ππfunction ODoubleLst.MoveObjToPtr(Serial:longint; p:pointer):word;π{--- Move data from obj to user buffer                         ---}πbeginπ     SeekNum(Serial);π     if (CurentObj^.Addresse = nil) or (p = nil) thenπ     beginπ          LastCodeErr := Point_To_Nil;π          exit;π     end;π     move(CurentObj^.Addresse, p, CurentObj^.Size);π     LastCodeErr := Succes;π     MoveObjToPtr := CurentObj^.Size;πend;πππ(****************************************************************************)ππfunction ODoubleLst.MovePtrToObj(Serial:longint; p:pointer):word;π{--- Move user buffer to obj data.  obj data take ObjSize bytes ---}πbeginπ     SeekNum(Serial);π     if (CurentObj^.Addresse = nil) or (p = nil) thenπ     beginπ          LastCodeErr := Point_To_Nil;π          exit;π     end;π     move(p, CurentObj^.Addresse, CurentObj^.Size);π     LastCodeErr := Succes;π     MovePtrToObj := CurentObj^.Size;πend;πππend.π                     22     08-24-9413:50ALL                      MARIUS ELLEN             Pointers                 SWAG9408    K┤+█    13     ╙═   {πDVE>> What I want to do is to make it point to the next byte in memory,πDVE>> sort of "apointer:=[byte ptr] apointer + 1"πDVE>> Apointer:=ptr(seg(apointer^),Ofs(apointer^) + 1);ππAGB> That won't work if the pointer is equal to 0FFFFh (Segment must beπAGB> adjusted!). A shorter (and faster?) method of coding this (wrong) way :πAGB> Inc(LongInt(APointer));ππOeps, this doesn't work either, especially in the case $ffff ! (unwantedπparagraph increase and in protected mode a RunTime Error 216 "Generalπprotection fault")ππFor non segm. overrides this should work fine: Aptr:=pchar(Aptr)+1;πand if youre planning segments overrides than you should use this:π}ππfunction GetDosPtr(Point:Pointer;Offs:Longint):pointer;πassembler;{offs in [$0..$fffff}πasmπ        mov     dx,point.word[2]π        mov     cx,offs.word[2]π        mov     bx,offs.word[0]π        add     bx,point.word[0]π        adc     cx,0π        mov     ax,bxπ        and     ax,0fhπ        shr     cx,1;rcr bx,1π        shr     cx,1;rcr bx,1π        shr     cx,1;rcr bx,1π        shr     cx,1;rcr bx,1π        add     dx,bxπend;ππ{And for protected mode: }ππfunction GetPtr(BASE:Pointer;Offs:Longint):Pbyte;πassembler;πasmπ        MOV     AX,word ptr [OFFS+2]π        MOV     BX,word ptr [OFFS+0]π        ADD     BX,word ptr [BASE+0]π        ADC     AX,0π        MUL     SelectorIncπ        ADD     AX,word ptr [BASE+2]π        MOV     DX,AXπ        MOV     AX,BXπend;π                                                                                                    23     08-24-9413:58ALL                      MARK GAUTHIER            Match Strings in Array   SWAG9408    1}₧M    44     ╙═   π{* Stack Research string for turbo pascal unit *}π{* Public Domain, 21/07/94 by Mark Gauthier.   *}π{* Fidonet 1:242/818.5, FM 101:190/805.5       *}ππUnit Search;ππ{ What for?, it use stack function to search for a matching stringπ  in an array. }ππInterfaceππConstππ        MaxString : Word = 4096;π        MaxStack  : Word = 500;ππVarπ        StrAddr         : Array[1..4096] of Pointer;π        { Addresse for all strings. }ππ        TotalStr        : Word;π        { Curent strings number }ππ        StrFreq         : Array[1..4096] of Word;π        { Search frequence for each string }ππ        procedure ClearAllStack;π        { Clear stack.  You must call this procedure to tell unitπ          you will change the searchstring. }ππ        procedure AddString (S:String);π        { Add a string in array, only if totalstr if < maxstring. }ππ        function  SearchString (S:String) : boolean;π        { Search for a string, if stack is not clear previous search asπ          been made. Example: you search for 'ABC' and this functionπ          return true.  If you search for 'ABCD' then this functionπ          will go in stack and get all the old addr for 'ABC' and seeπ          if 'D' is the next letter for the check strings.ππ          * This unit is usefull to build compression unit.π        }ππimplementationππVarπ        SearchStr       : Pointer;π        LastFound       : Word;π        CurentStack     : Byte;π        StackPos        : Array[1..2] of Word;π        StackData       : Array[1..2,1..500] of Word;ππ{*===================================================================*}ππ{ Return true is stack is empty }πfunction StackIsEmpty:boolean;πbeginπ     StackIsEmpty := false;π     if StackPos[CurentStack] = 0 then StackIsEmpty := true;πend;ππ{*===================================================================*}ππ{ Pop an element from stack }πfunction MgPop:Word;πbeginπ     MgPop := 0;π     If Not StackIsEmpty thenπ     beginπ          MgPop := StackData[CurentStack, StackPos[CurentStack]];π          Dec(StackPos[CurentStack]);π     end;πend;ππ{*===================================================================*}ππ{ Push an element on stack }πprocedure MgPush(Number:word);πvar x:byte;πbeginπ     if CurentStack = 1 then x := 2 else x := 1;π     If StackPos[x] < MaxStack thenπ     beginπ          Inc(StackPos[x]);π          StackData[x, StackPos[x]] := Number;π     end;πend;ππ{*===================================================================*}ππ{ Clear the curent stack }πprocedure ClearStack;πbeginπ     StackPos[CurentStack] := 0;πend;ππ{*===================================================================*}ππ{ Inverse pop and push stack }πprocedure InverseStack;πbeginπ     ClearStack;π     If CurentStack = 1 then CurentStack := 2 else CurentStack := 1;πend;ππ{*===================================================================*}ππ{ Compare SearchStr(global var) and DATA(parameter) }π{$F+}πfunction Compare(Data:Pointer):boolean;assembler;πasmπ          push      bpπ          mov       bp,spππ          push      dsππ          lds       si,SearchStrπ          lodsbπ          mov       cl,alπ          mov       ch,0ππ          les       di,[Bp+8]π          inc       diππ          mov       al,0π          cldπ          repe      cmpsbπ          jne       @NotMatchπ          mov       al,1ππ@NotMatch:ππ          pop       dsπ          pop       bpπend;π{$F-}ππ{*===================================================================*}ππ{ Search procedure execute this procedure if stack is not empty. }πfunction SearchWhitPop:boolean;πVar Start : Word;πbeginπ     SearchWhitPop := false;π     While not StackIsEmpty doπ     beginπ          Start := MgPop;π          if Compare(StrAddr[Start]) thenπ          beginπ                LastFound := Start;π                SearchWhitPop := true;π                MgPush(Start);π                Inc(StrFreq[Start]);π          end;π     end;π     InverseStack;πend;ππ{*===================================================================*}ππ{ Search procedure execute this procedure if stack is empty. }πfunction CompleteSearchPush:boolean;πvar i : word;πbeginπ     CompleteSearchPush := false;π     For i := 1 to TotalStr doπ     beginπ          if Compare(StrAddr[i]) thenπ          beginπ                LastFound := i;π                CompleteSearchPush := true;π                MgPush(i);π                Inc(StrFreq[i]);π          end;π     end;π     InverseStack;πend;ππ{*===================================================================*}ππ{ Public Search routine }πfunction SearchString(S:String):boolean;πbeginπ     SearchStr := Addr(S);π     If StackIsEmptyπ     then SearchString := CompleteSearchPushπ     else SearchString := SearchWhitPop;πend;ππ{*===================================================================*}ππ{ Add a string in heap }πprocedure AddString(S:String);πbeginπ     Inc(TotalStr);π     GetMem(StrAddr[TotalStr], Length(S));π     Move(S,StrAddr[TotalStr]^, Length(S)+1);πend;ππ{*===================================================================*}ππ{ Clear pop and push stack }πprocedure ClearAllStack;πbeginπ     InverseStack;π     ClearStack;πend;ππ{*===================================================================*}ππ{ Unit Initialisation }πvar i : word;πBeginπ     TotalStr    := 0;π     CurentStack := 0;π     StackPos[1] := 0;π     StackPos[2] := 0;π     for i := 1 to 4096 do StrFreq[i] := 0;πEnd.π                                                                24     08-24-9413:59ALL                      SWAG SUPPORT TEAM        Nth array item in BASM   SWAG9408    Å$▒≡    5      ╙═   {πCC> I want to know how to retrieve the n(th) element from theπCC> table in BASM.ππSolution:π}ππ program _getvalue;ππ const table:array[0..9] of integer=π   (1001,1002,1003,1004,1005,1006,1007,1008,1009,1010);ππ function getvalue(nth:word):integer; assembler;π asmπ   mov si,nth                 { get index }π   add si,si                  { 'multiply' by two (word-sized) }π   mov ax,word ptr table[si]  { put table[index] in ax -> function-result }π end;ππ beginπ   writeln(getvalue(7));π end.π                25     08-24-9414:00ALL                      MATT BOUSEK              Avl Tree Tally           SWAG9408    ┐╚_    59     ╙═   (*πHere is TALLY.PAS, a program that Matt Bousek <MBOUSEK@intel9.intel.com> wroteπto do a word frequency analysis on a text file.  It uses an AVL tree.  Itπshould compile under TP 6.0 or BP 7.0π*)πprogram word_freq(input,output);ππtypeπ    short_str = string[32];ππ{************AVLtree routines*********}πtypeπ    balance_set = (left_tilt,neutral,right_tilt);π    memptr      = ^memrec;π    memrec = recordπ        balance     : balance_set;π        left,right  : memptr;π        count       : longint;π        key         : short_str;π    end;ππ    {**************************************}π    procedure rotate_right(var root:memptr);π    var ptr2,ptr3 : memptr;π    beginπ        ptr2:=root^.right;π        if ptr2^.balance=right_tilt then beginπ            root^.right:=ptr2^.left;π            ptr2^.left:=root;π            root^.balance:=neutral;π            root:=ptr2;π        end else beginπ            ptr3:=ptr2^.left;π            ptr2^.left:=ptr3^.right;π            ptr3^.right:=ptr2;π            root^.right:=ptr3^.left;π            ptr3^.left:=root;π            if ptr3^.balance=left_tiltπ                then ptr2^.balance:=right_tiltπ                else ptr2^.balance:=neutral;π            if ptr3^.balance=right_tiltπ                then root^.balance:=left_tiltπ                else root^.balance:=neutral;π            root:=ptr3;π        end;π        root^.balance:=neutral;π    end;ππ    {*************************************}π    procedure rotate_left(var root:memptr);π    var ptr2,ptr3 : memptr;π    beginπ        ptr2:=root^.left;π        if ptr2^.balance=left_tilt then beginπ            root^.left:=ptr2^.right;π            ptr2^.right:=root;π            root^.balance:=neutral;π            root:=ptr2;π        end else beginπ            ptr3:=ptr2^.right;π            ptr2^.right:=ptr3^.left;π            ptr3^.left:=ptr2;π            root^.left:=ptr3^.right;π            ptr3^.right:=root;π            if ptr3^.balance=right_tiltπ                then ptr2^.balance:=left_tiltπ                else ptr2^.balance:=neutral;π            if ptr3^.balance=left_tiltπ                then root^.balance:=right_tiltπ                else root^.balance:=neutral;π            root:=ptr3;π        end;π        root^.balance:=neutral;π    end;ππ    {*****************************************************************}π    procedure insert_mem(var root:memptr; x:short_str; var ok:boolean);π    beginπ        if root=nil then beginπ            new(root);π            with root^ do beginπ                key:=x;π                left:=nil;π                right:=nil;π                balance:=neutral;π                count:=1;π            end;π            ok:=true;π        end else beginπ            if x=root^.key then beginπ                ok:=false;π                inc(root^.count);π            end else beginπ                if x<root^.key then beginπ                    insert_mem(root^.left,x,ok);π                    if ok then case root^.balance ofπ                        left_tilt  : beginπ                                rotate_left(root);π                                ok:=false;π                            end;π                        neutral    : root^.balance:=left_tilt;π                        right_tilt : beginπ                                root^.balance:=neutral;π                                ok:=false;π                            end;π                    end;π                end else beginπ                    insert_mem(root^.right,x,ok);π                    if ok then case root^.balance ofπ                        left_tilt  : beginπ                                root^.balance:=neutral;π                                ok:=false;π                            end;π                        neutral    : root^.balance:=right_tilt;π                        right_tilt : beginπ                                rotate_right(root);π                                ok:=false;π                            end;π                    end;π                end;π            end;π        end;π    end;ππ    {*****************************************************}π    procedure insert_memtree(var root:memptr; x:short_str);π    var ok:boolean;π    beginπ        ok:=false;π        insert_mem(root,x,ok);π    end;ππ    {*********************************}π    procedure dump_mem(var root:memptr);π    beginπ        if root<>nil then beginπ            dump_mem(root^.left);π            writeln(root^.count:5,' ',root^.key);π            dump_mem(root^.right);π        end;π    end;πππ{MAIN***************************************************************}π{*** This program was written by Matt Bousek sometime in 1992.   ***}π{*** The act of this posting over Internet makes the code public ***}π{*** domain, but it would be nice to keep this header.           ***}π{*** The basic AVL routines came from a book called "Turbo Algo- ***}π{*** rythms",  Sorry, I don't have the book here and I can't     ***}π{*** remember the authors or publisher.  Enjoy.  And remember,   ***}π{*** there is no free lunch...                                   ***}ππconstπ    wchars:set of char=['''','a'..'z'];ππvarπ    i,j         : word;π    aword       : short_str;π    subject     : text;π    wstart,wend : word;π    inword      : boolean;π    linecount   : longint;π    wordcount   : longint;π    buffer      : array[1..10240] of char;π    line        : string;π    filename    : string;π    tree        : memptr;ππBEGINπ    tree:=nil;ππ    filename:=paramstr(1);π    if filename='' then filename:='tally.pas';π    assign(subject,filename);π    settextbuf(subject,buffer);π    reset(subject);ππ    wordcount:=0;π    linecount:=0;π    while not eof(subject) do beginπ        inc(linecount);π        readln(subject,line);π        wstart:=0; wend:=0;π        for i:=1 to byte(line[0]) do beginπ            if line[i] in ['A'..'Z'] then line[i]:=chr(ord(line[i])+32);π            inword:=(line[i] in wchars);π            if inword and (wstart=0) then wstart:=i;π            if inword and (wstart>0) then wend:=i;π            if not(inword) or (i=byte(line[0])) then beginπ                if wend>wstart then beginπ                    aword:=copy(line,wstart,wend+1-wstart);π                    j:=byte(aword[0]);π                    if (aword[j]='''') and (j>2) then begin {lose trailing '}π                        aword:=copy(aword,1,j-1);π                        dec(wend);π                        dec(j);π                    end;π                    if (aword[1]='''') and (j>2) then begin {lose leading '}π                        aword:=copy(aword,2,j-1);π                        inc(wstart);π                        dec(j);π                    end;π                    if (j>2) and (aword[j-1]='''') and (aword[j]='s') thenπbegin {lose trailing 's}π                        aword:=copy(aword,1,j-2);π                        dec(wend,2);π                        dec(j,2);π                    end;π                    if (j>2) then beginπ                        inc(wordcount);π                        insert_memtree(tree,aword);π                    end;π                end; { **if wend>wstart** }π                wstart:=0; wend:=0;π            end; { **if not(inword)** }π        end; { **for byte(line[0])** }π    end; { **while not eof** }ππdump_mem(tree);πwriteln(linecount,' lines, ',wordcount,' words.');πEND.π                                                                                                 26     08-25-9409:10ALL                      LEE BARKER               Sorting Linked Lists     SWAG9408    ╡à·    11     ╙═   {π│ I'm looking for a routine to swap two nodes in a doubleπ│ linked list or a complete sort.ππThere has been a thread on the TP conf area in CIS on quickπsorting a (double) linked list. To swap two nodes, remove one,πthen add it in where desired. Quick sample-π}ππtypeπ  s5       = string[5];π  ntp      = ^nodetype;π  nodetype = recordπ               prv,nxt : ntp;π               data    : s5;π             end;πconstπ  nbr : array[0..9] of string[5] = ('ZERO','ONE','TWO',π        'THREE','FOUR','FIVE','SIX','SEVEN','EIGHT','NINE');πvarπ  node,root : ntp;π  i : integer;ππprocedure swap (var n1,n2 : ntp);π  var n : ntp;π  beginπ    n := n1;π    n1 := n2;π    n2 := n;π  end;ππprocedure addnode (var n1,n2 : ntp);π  beginπ    swap(n1^.nxt,n2^.prv^.nxt);π    swap(n1^.prv,n2^.prv);π  end;ππprocedure getnode(i:integer);π  var n : ntp;π  beginπ    getmem(n,sizeof(nodetype));π    n^.nxt := n;π    n^.prv := n;π    n^.data := nbr[i];π    if root=nilπ    then root := nπ    else addnode(n,root);π  end;ππbeginπ  root := nil;π  for i := 0 to 9 doπ  beginπ    getnode(i);π    node := root;π    writeln;π    writeln('The linked now is-');π    repeatπ      writeln(node^.data);π      node := node^.nxt;π    until node = root;π  end;πend.π                                             27     08-25-9409:11ALL                      DEAVON EDWARDS           Stacks                   SWAG9408    τ "█    76     ╙═   {πFrom: Deavon@sound.demon.co.uk (Deavon Edwards)ππI am having some problem with this program. I would like to modified it toπdo the following....π i). To simulate the operation of a queue (Last In First Out).π ii) To use a linked list instead of arrays(simulating a stack and queue).πIf anyone out there can help it would be greatly appreciated.ππ This program will simulate the operation of a stack and a queue with aπ 10 items maximum. It will give the user the opportunity to insert andπ delete items from the data structures, display the data on screen,π it on a printer, and save and load the data from a diskπ}ππPROGRAM StackSimulation(input, output);ππUSES CRT,DOS,PRINTER;ππVARπ  Stack      : ARRAY [1..10] OF STRING[20];π  StackFull  : BOOLEAN;π  StackEmpty : BOOLEAN;π  Pointer    : INTEGER;π  Choice     : CHAR;ππ    {*******************************************************************}ππPROCEDURE PressAKey;πBEGINππ  WRITELN;π  WRITELN;π  WRITELN ('                 ************************************');π  WRITELN ('                 ***   PRESS RETURN TO CONTINUE   ***');π  WRITELN ('                 ************************************');π  READLN;π  CLRSCR;πEND;π    {*******************************************************************}πPROCEDURE Jump_a_Line(Jump: INTEGER);πVARπ   Skip : INTEGER;ππBEGINπ   FOR Skip := 1 TO Jump DOπ   WRITELN;πEND;π    {*******************************************************************}ππProcedure Introduction;              {Display an introduction message to user}π  BEGINπ  CLRSCR;π  gotoxy (1,10);π  Textcolor(Cyan);π  writeln('        ********************************************************');π  writeln('        ********************************************************');π  writeln('        *                                                      *');π  writeln('        *     WELCOME TO STACK & QUEUE SIMULATION PROGRAM      *');π  writeln('        *                                                      *');π  writeln('        ********************************************************');π  writeln('        ********************************************************');π  Jump_a_line(3);π  DELAY (1000);π  end;ππ    {*******************************************************************}ππPROCEDURE Initialise (VAR StackFull, StackEmpty : BOOLEAN);ππBEGINπ  CLRSCR;π  gotoxy (1,10);π  Jump_a_line(2);π  WRITELN ('        ******************************************************');π  WRITELN ('        THE STACK IS INITIALISING...........PLEASE WAIT.......');π  WRITELN ('        ******************************************************');π  Jump_a_line(3);π  SOUND (240);π  DELAY (1000);π  CLRSCR;π  NOSOUND;π  Pointer := 0;π  StackFull := FALSE;π  StackEmpty := TRUE;πEND;ππ    {*******************************************************************}ππPROCEDURE Add (VAR StackFull, StackEmpty : BOOLEAN);πBEGINπ IF StackFull THENπ   BEGINπ     gotoxy (1,10);π     Jump_a_line(2);π     WRITELN ('************************************************************');π     WRITELN ('** SORRY, THE STACK IS FULL, NO MORE DATA CAN BE ENTERED ***');π     WRITELN ('************************************************************');π     Jump_a_line(3);π     PressAKey;π   ENDπ ELSEπ   BEGINπ     INC (Pointer);π     Jump_a_line(3);π     WRITE ('PLEASE ENTER THE ITEM TO BE ADDED TO THE STACK :=>  ');π     READLN (Stack [Pointer]);π     CLRSCR;π     IF StackEmpty THEN StackEmpty := FALSE;π     IF Pointer = 10 THEN StackFull := TRUE;π   END;πEND;ππ    {*******************************************************************}ππPROCEDURE Take (VAR StackFull, StackEmpty : BOOLEAN);πBEGINπ  IF StackEmpty THENπ    BEGINπ      gotoxy (1,10);π      Jump_a_line(3);π      WRITELN ('    *******************************************************');π      WRITELN ('    *** THE STACK IS EMPTY, NO MORE DATA CAN BE REMOVED ***');π      WRITELN ('    *******************************************************');π      Jump_a_line(3);π      PressAKey;π    ENDπ  ELSEπ    BEGINπ      gotoxy (1,10);π      Jump_a_line(3);π      WRITE ('THE FOLLOWING ITEM HAVE BEEN REMOVE FROM THE STACK :=>  ');π      WRITELN (Stack [Pointer]);π      DEC (Pointer);π      IF Pointer = 0 THEN StackEmpty := TRUE;π      IF StackFull THEN StackFull := FALSE;π      Jump_a_line(3);π      PressAKey;π    END;πEND;ππ    {*******************************************************************}ππPROCEDURE Display_to_Screen (StackEmpty : BOOLEAN);πVARπ  Counter : INTEGER;πBEGINπ  CLRSCR;π  GOTOXY (1,10);π  IF StackEmpty THENπ    WRITELN ('                      THE STACK IS CURRENTLY EMPTY ');π    Jump_a_Line (3);π  FOR Counter := 1 TO Pointer DOπ  WRITELN (Counter:2 ,'     ', Stack [Counter]);π  Jump_a_Line(2);π  PressAKey;πEND;ππ    {*******************************************************************}πPROCEDURE Print_to_Printer (StackEmpty : BOOLEAN);πVARπ  Counter : INTEGER;πBEGINπ  CLRSCR;π  GOTOXY (1,10);π  {$I-}π  WRITELN (lst,#0);π  IF IORESULT <> 0 THENπ  WRITELN ('       >>>>>>   PRINTING ERROR.......PRINTER OFF LINE   <<<<<<  ')π  ELSEπ   BEGINπ    IF StackEmpty THENπ    WRITELN ('THE STACK IS CURRENTLY EMPTY, THERE IS NO DATA TO BE PRINTED.')π    ELSEπ    WRITELN (' THE CONTENTS OF THE STACK IS PRINTING........');π    FOR Counter := Pointer DOWNTO 1 DOπ    WRITELN (Lst,Counter:2 ,'     ', Stack [Counter]);π   END;π   {$I+}π   PressAKey;πEND;πππ      {****************************************************}ππPROCEDURE Save_to_File;ππVARπ    Write_to_File       : TEXT;π    Output_to_File      : STRING[20];π    Read_File           : BOOLEAN;π    Counter             : INTEGER;ππBEGINπ  CLRSCR;π  Jump_a_Line(3);π  WRITE('PLEASE ENTER THE NAME YOU WISH TO CALLED THE FILE :=> ');π  READLN(Output_to_File);π  ASSIGN(Write_to_File,Output_to_File);π  REWRITE(Write_to_File);π  FOR Counter := 1 TO Pointer DOπ    BEGINπ      Writeln(Write_to_File,Stack[Counter]);π      Writeln('SAVING... ',Counter:2,' ... ',Stack[Counter]);π    END;π    CLOSE(Write_to_File);π    PressAKey;πEnd;ππ                {**************************************************}ππPROCEDURE Open_A_File (StackEmpty : BOOLEAN);ππVARπ    Read_File       : TEXT;π    Input_to_File   : STRING[20];ππ BEGINπ   CLRSCR;π   Jump_a_Line(3);π   WRITE ('PLEASE ENTER THE NAME OF THE FILE YOU WHICH TO OPENED :=> ');π   READLN(Input_to_File);π   ASSIGN(Read_File,Input_to_File);π   {$I-}π   RESET(Read_File);π   IF IOResult = 0 THENπ    BEGINπ     Jump_a_Line(2);π     Pointer := 0;π     WHILE NOT EOF(Read_File) DOπ       BEGINπ         INC (Pointer);π         READLN(Read_File,Stack [Pointer]);π         WRITELN(Pointer:2,' : ',Stack[Pointer]);π       END;π       CLOSE(Read_File);π       StackEmpty := FALSE;π       ENDπ       ELSEπ       CLRSCR;π       Jump_a_Line(2);π       WRITELN ('                 ***********************************');π       WRITELN ('                 ***   FILE NAME DOES NOT EXIT   ***');π       WRITELN ('                 ***********************************');π       {$I+}π       PressAKey;πEND;ππ               {****************************************************}ππPROCEDURE Menu;ππ BEGINπ    gotoxy (1,10);π    Textcolor(White);π    WRITELN ('           **************************************************');π    WRITELN ('           **************************************************');π    WRITELN ('           ****       A : Add to Stack                  *****');π    WRITELN ('           ****       T : Take from Stack               *****');π    WRITELN ('           ****       D : Display Stack List to Screen  *****');π    WRITELN ('           ****       P : Print Stack List              *****');π    WRITELN ('           ****       I : Initialise Stack List         *****');π    WRITELN ('           ****       S : Save Stack to disk            *****');π    WRITELN ('           ****       L : Load Stack from disk          *****');π    WRITELN ('           ****       Q : Quit program                  *****');π    WRITELN ('           **************************************************');π    WRITELN ('           **************************************************');π    WRITELN;π    WRITELN;π    WRITELN ('           PLEASE ENTER AN OPTION >> ');π    Choice := READKEY;ππ END;ππPROCEDURE QuitProgram;ππBEGINπ  gotoxy (1,10);π  WRITELN ('                  ***********************************');π  WRITELN ('                  """""""""""""""""""""""""""""""""""');π  WRITELN ('                  [[[[[      GOODBYE!!!!!!     ]]]]] ');π  WRITELN ('                  """""""""""""""""""""""""""""""""""');π  WRITELN ('                  ***********************************');π  WRITELN;π  WRITELN;πEND;ππ    {*******************************************************************}π    {*******************************************************************}ππBEGINπ   Introduction;π   Initialise (StackFull, StackEmpty);π  REPEATπ    Menu;π    CLRSCR;π    CASE Choice OFπ     'A', 'a' : Add (StackFull, StackEmpty);π     'T', 't' : Take (StackFull, StackEmpty);π     'D', 'd' : Display_to_Screen (StackEmpty);π     'P', 'p' : Print_to_Printer (StackEmpty);π     'I', 'i' : Initialise (StackFull, StackEmpty);π     'S', 's' : Save_to_File;π     'L', 'l' : Open_a_File(StackEmpty);π     'Q', 'q' : QuitProgramπ    ELSEπ      BEGINπ        gotoxy (1,10);π        WRITELN ('                       **************************');π        WRITELN ('                       **  Invalid key pressed **');π        WRITELN ('                       **************************');π        WRITELN;π        PressAKey;π      END;π    END;π  UNTIL (Choice = 'Q') OR (Choice = 'q');πEND.π                           28     08-26-9408:32ALL                      SWAG SUPPORT TEAM        Binary Tree Example      SWAG9408    
  2. ┐╫·    44     ╙═   PROGRAM BinaryTreeSample ( INPUT, OUTPUT );ππUSES Crt;ππTYPE NodePtr     = ^Node;ππ     Node        = RECORDπ                    Left,π                    Parent,π                    Right     : WORD;π                    KeyWord   : POINTER;   { Will hold in STRING format }π                   END;                    { Where 1st byte is length   }ππ     Comparison  = (Less, Greater, Equal);πππVAR NewWord  : STRING;                     { Holds word typed in        }π    StartMem : LONGINT;                    { Holds starting memory      }π    Counter,                               { Used for FOR Loop          }π    LastNode : WORD;                       { Holds last node stored     }π    BTree    : ARRAY[1..16000] OF NodePtr; { Entire Binary Tree         }ππππFUNCTION PtrStr ( Ptr    : POINTER ) : STRING; { Ptr --> String conversion }ππVAR Str : STRING;ππBEGINπ Move( Ptr^, Str, Mem[Seg(Ptr^):Ofs(Ptr^)]+1 );   { +1 to copy count byte }π PtrStr := Str;πEND;πππPROCEDURE Destroy ( VAR P : POINTER );πBEGINπ FreeMem (P,Mem[Seg(P^):Ofs(P^)]+1);              { Dispose ptr to free mem }πEND;πππFUNCTION Compare( Ptr1,                            { Compares two ptrs like }π                  Ptr2   : POINTER ) : Comparison; { strings, returning: <, }π                                                   { >, or =                }πVAR Str1,π    Str2   : STRING;π    Result : Comparison;ππBEGINπ Move( Ptr1^, Str1, Mem[Seg(Ptr1^):Ofs(Ptr1^)]+1 );π Move( Ptr2^, Str2, Mem[Seg(Ptr2^):Ofs(Ptr2^)]+1 );π IF Str1=Str2 THENπ  Result := Equalπ ELSEπ  IF Str1>Str2 THENπ   Result := Greaterπ  ELSEπ   Result := Less;π Compare := Result;πEND;πππPROCEDURE Str_To_Pointer (     Str : STRING;      { Converts Str to Ptr }π                           VAR Ptr : POINTER  );ππBEGINπ GetMem(Ptr,Ord(Str[0])+1);π Move (Str,Ptr^,Ord(Str[0])+1);πEND;πππPROCEDURE PlaceWord ( Str : STRING );  { Sort through binary tree, and if }π                                       { the word does not exist, add the }πVAR NewNode        : Node;             { node to the binary tree          }π    Index          : WORD;π    Found,π    SearchFinished : BOOLEAN;π    Comp           : Comparison;ππBEGINπ SearchFinished := (LastNode=0);π Found := FALSE;π Index := 1;π WITH NewNode DO                        { Constructs initial full node     }π  BEGINπ   Left := 0;                           { Don't know yet                   }π   Right := 0;                          {  "      "   "                    }π   Parent := 0;                         {  "      "   "                    }π   Str_To_Pointer ( Str, KeyWord );     { This should store the word in ^  }π  END;π IF SearchFinished THENπ  BEGINπ   Inc(LastNode);                          { Increase LastNode +1    }π   New(BTree[LastNode]);                   { Create next node        }π   BTree[LastNode]^ := NewNode;            { Store new node now      }π  END;π WHILE NOT (SearchFinished OR Found) DOπ  BEGINπ   Comp := Compare(NewNode.Keyword,BTree[Index]^.KeyWord);π   IF Comp=EQUAL THENπ    Found := TRUEπ   ELSEπ    IF Comp=Less THENπ     BEGINπ      IF BTree[Index]^.Left = 0 THEN            { IF Last branch then     }π       BEGIN                                    { .. lets make a new one  }π        Inc(LastNode);                          { Increase LastNode +1    }π        New(BTree[LastNode]);                   { Create next node        }π        BTree[Index]^.Left := LastNode;         { Point left to next node }π        NewNode.Parent := Index;                { Set parent to index     }π        BTree[LastNode]^ := NewNode;            { Store new node now      }π        SearchFinished := TRUE                  { All finished!           }π       ENDπ      ELSEπ       Index := BTree[Index]^.Leftπ     ENDπ    ELSE                                        { Must be greater then }π     BEGINπ      IF BTree[Index]^.Right = 0 THEN           { IF Last branch then..   }π       BEGIN                                    { .. lets make a new one  }π        Inc(LastNode);                          { Increase LastNode +1    }π        New(BTree[LastNode]);                   { Create next node        }π        BTree[Index]^.Right := LastNode;        { Point left to next node }π        NewNode.Parent := Index;                { Set parent to index     }π        BTree[LastNode]^ := NewNode;            { Store new node now      }π        SearchFinished := TRUE                  { All finished!           }π       ENDπ      ELSEπ       Index := BTree[Index]^.Rightπ     END;π  END;πEND;ππPROCEDURE Init;πBEGINπ LastNode := 0;πEND;πππPROCEDURE DisposeAll;ππVAR Counter : WORD;ππBEGINπ FOR Counter := 1 TO LastNode DOπ  BEGINπ   Destroy(BTree[Counter]^.KeyWord);π   Dispose(BTree[Counter]);π  ENDπEND;πππBEGINπ ClrScr;π StartMem := MemAvail;π Init;π REPEATπ  Write ('Insert new word ["stop" to finish] : ');π  Readln (NewWord);π  IF NewWord <> 'stop' THENπ   PlaceWord ( NewWord );π UNTIL NewWord='stop';π Writeln;π Writeln ('  Node    Left     Parent     Right      Word');π Writeln ('-----------------------------------------------');π FOR Counter := 1 TO LastNode DOπ  WITH BTree[Counter]^ DOπ   Writeln (Counter:5,Left:8,Parent:11,Right:10,'       ',PtrStr(KeyWord));π Writeln;π Writeln ('Initial memory availible        : ',StartMem);π Writeln ('Memory availible before dispose : ',MemAvail);π DisposeAll;π Writeln ('Memory availible after clean-up : ',MemAvail);π Readln;πEND.π