Преглед на файлове

+ INitial implementation

michael преди 27 години
родител
ревизия
981e423a9e
променени са 2 файла, в които са добавени 866 реда и са изтрити 0 реда
  1. 192 0
      docs/heaptrc.tex
  2. 674 0
      docs/objects.tex

+ 192 - 0
docs/heaptrc.tex

@@ -0,0 +1,192 @@
+%
+%   $Id$
+%   This file is part of the FPC documentation.
+%   Copyright (C) 1998, by Michael Van Canneyt
+%
+%   The FPC documentation is free text; you can redistribute it and/or
+%   modify it under the terms of the GNU Library General Public License as
+%   published by the Free Software Foundation; either version 2 of the
+%   License, or (at your option) any later version.
+%
+%   The FPC Documentation is distributed in the hope that it will be useful,
+%   but WITHOUT ANY WARRANTY; without even the implied warranty of
+%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%   Library General Public License for more details.
+%
+%   You should have received a copy of the GNU Library General Public
+%   License along with the FPC documentation; see the file COPYING.LIB.  If not,
+%   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+%   Boston, MA 02111-1307, USA. 
+%
+\chapter{The HEAPTRC unit.}
+This chapter describes the HEAPTRC unit for \fpc. It was written by 
+Pierre Muller.
+
+\section{Purpose}
+
+The HEAPTRC unit can be used to debug your memory allocation/deallocation.
+It keeps track of the calls to getmem/freemem, and, implicitly, of
+New/Dispose statements.
+
+When the program exits, or when you request it explicitly.
+It displays the total memory used, and then dumps a list of blocks that
+were allocated but not freed. It also displays where the memory was
+allocated.
+
+If there are any inconsistencies, such as memory blocks being allocated
+or freed twice, or a memory block that is released but with wrong size,
+this will be displayed also.
+
+The information that is stored/displayed can be customized using
+some constants.
+
+\section{Usage}
+
+All that you need to do is to include \file{heaptrc} in the uses clause
+of your program. Make sure that it is the first unit in the clause,
+otherwise memory allocated in initialization code of units that precede the
+heaptrc unit will not be accounted for, causing an incorrect memory usage
+report.
+
+The following example shows how to use the heaptrc unit.
+
+\latex{\inputlisting{heapex/heapex.pp}}
+\html{\input{heapex/heapex.tex}}
+
+This is the memory dump shown when running this program:
+\begin{verbatim}
+Marked memory at 08052C48 invalid
+Wrong size : 128 allocated 64 freed
+  0x0804C29C
+  0x080509E2
+  0x080480A4
+  0x00000000
+Heap dump by heaptrc unit
+13 memory blocks allocated : 1416/1424
+6 memory blocks freed     : 708/712
+7 unfreed memory blocks : 708
+True heap size : 2097152
+True free heap : 2096040
+Should be : 2096104
+Call trace for block 0x08052C48 size 128
+  0x080509D6
+  0x080480A4
+Call trace for block 0x08052B98 size 128
+  0x08050992
+  0x080480A4
+Call trace for block 0x08052AE8 size 128
+  0x08050992
+  0x080480A4
+Call trace for block 0x08052A38 size 128
+  0x08050992
+  0x080480A4
+Call trace for block 0x08052988 size 128
+  0x08050992
+  0x080480A4
+Call trace for block 0x080528D8 size 128
+  0x08050992
+  0x080480A4
+Call trace for block 0x080528A0 size 4
+  0x08050961
+  0x080480A4
+\end{verbatim}
+
+\section{Constants, Types and variables}
+
+The \var{fill\_extra\_info\_type} is a procedural type used in the
+\seepl{Set\_Extra\_Info}{SetExtraInfo} call.
+
+\begin{listing}
+type
+    fill_extra_info_type = procedure(p : pointer);
+\end{listing}
+The following typed constants allow to fine-tune the standard dump of the
+memory usage by \seepl{Dump\_Heap}{DumpHeap}:
+
+\begin{listing}
+const
+  tracesize = 8;
+  quicktrace : boolean = true;
+  halt_on_error : boolean = true;
+  keepreleased : boolean = false;
+\end{listing}
+
+\var{Tracesize} specifies how many levels of calls are displayed of the 
+call stack during the memory dump. If you specify \var{keepreleased:=True}
+then half the \var{TraceSize} is reserved for the \var{GetMem} call stack, 
+and the other half is reserved for the \var{FreeMem} call stack.
+For example, the default value of 8 will cause eight levels of call frames
+to be dumped for the getmem call if \var{keepreleased} is \var{False}. If
+\var{KeepReleased} is true, then 4 levels of call frames will be dumped for
+the \var{GetMem} call and 4 frames wil be dumped for the \var{FreeMem} call.
+If you want to change this value, you must recode the \file{heaptrc} unit.
+
+\var{Quicktrace} determines whether
+
+If \var{halt\_on\_error} is set to \var{True} then an illegal call to 
+\var{FreeMem} will cause the memory manager to execute a \var{halt(1)} 
+instruction, causing a memory dump.
+
+If \var{keepreleased} is set to true, then a list of freed memory 
+blocks is kept. This is useful if you suspect that the same memory block is
+released twice. However, this option is very memory intensive, so use it
+sparingly, and only when it's really necessary.
+
+\section{Functions and procedures}
+
+\begin{procedurel}{Dump\_Heap}{DumpHeap}
+\Declaration 
+procedure Dump\_Heap;
+\Description
+\var{dump\_heap} dumps to standard output a summary of memory usage.
+It is called automatically by the heaptrc unit when your program exits
+(by instaling an exit procedure), but it can be called at any time
+\Errors
+None.
+\SeeAlso
+\seepl{Mark\_Heap}{MarkHeap}
+\end{procedurel}
+
+\begin{procedurel}{Mark\_Heap}{MarkHeap}
+\Declaration
+procedure Mark\_Heap;
+\Description
+\var{Mark\_Heap} marks all memory blocks with a special signature.
+You can use this if you think that you corruped the
+\Errors
+None.
+\SeeAlso
+\seepl{Dump\_Heap}{DumpHeap}
+\end{procedurel}
+
+\begin{procedurel}{Set\_Extra\_Info}{SetExtraInfo}
+\Declaration
+procedure Set\_Extra\_Info( size : longint;func : fill\_extra\_info\_type);
+\Description
+You can use \var{Set\_Extra\_Info} to store extra info in the blocks that
+the heaptrc unit reserves when tracing getmem calls. \var{Size} indicates the
+size (in bytes) that the trace mechanism should reserve for your extra
+information. For each call to \var{getmem}, \var{func} will be called,
+and passed a pointer to the memory reserved. 
+
+When dumping the memory summary, the extra info is shown as Longint values.
+
+\Errors
+You can only call \var{Set\_Extra\_Info} if no memroy has been allocated
+yet. If memory was already allocated prior to the call to
+\var{Set\_Extra\_Info}, then an error will be displayed on standard error
+output, and a \seepl{Dump\_Heap}{DumpHeap} is executed.
+\SeeAlso
+\seepl{Dump\_Heap}{DumpHeap}
+\end{procedurel}
+
+\latex{\inputlisting{heapex/setinfo.pp}}
+\html{\input{heapex/setinfo.tex}}
+
+
+%
+% $Log$
+% Revision 1.1  1998-12-14 23:17:02  michael
+% + INitial implementation
+%
+%

+ 674 - 0
docs/objects.tex

@@ -0,0 +1,674 @@
+%
+%   $Id$
+%   This file is part of the FPC documentation.
+%   Copyright (C) 1998, by Michael Van Canneyt
+%
+%   The FPC documentation is free text; you can redistribute it and/or
+%   modify it under the terms of the GNU Library General Public License as
+%   published by the Free Software Foundation; either version 2 of the
+%   License, or (at your option) any later version.
+%
+%   The FPC Documentation is distributed in the hope that it will be useful,
+%   but WITHOUT ANY WARRANTY; without even the implied warranty of
+%   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%   Library General Public License for more details.
+%
+%   You should have received a copy of the GNU Library General Public
+%   License along with the FPC documentation; see the file COPYING.LIB.  If not,
+%   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+%   Boston, MA 02111-1307, USA. 
+%
+\chapter{The Objects unit.}
+This chapte documents te \file{objects} unit. The unit was implemented by
+many people, and was mainly taken from the FreeVision sources.
+
+The methods and fields that are in a \var{Private} part of an object
+declaration have been left out of this documentation.
+
+\section{Constants}
+The following constants are error codes, returned by the various stream
+objects.
+
+\begin{verbatim}
+CONST
+   stOk         =  0; { No stream error }
+   stError      = -1; { Access error }
+   stInitError  = -2; { Initialize error }
+   stReadError  = -3; { Stream read error }
+   stWriteError = -4; { Stream write error }
+   stGetError   = -5; { Get object error }
+   stPutError   = -6; { Put object error }
+   stSeekError  = -7; { Seek error in stream }
+   stOpenError  = -8; { Error opening stream }
+\end{verbatim}
+These constants can be passed to constructors of file streams:
+\begin{verbatim}
+CONST
+   stCreate    = $3C00; { Create new file }
+   stOpenRead  = $3D00; { Read access only }
+   stOpenWrite = $3D01; { Write access only }
+   stOpen      = $3D02; { Read/write access }
+\end{verbatim}
+
+The following constants are error codes, returned by the collection list
+objects:
+\begin{verbatim}
+CONST
+   coIndexError = -1; { Index out of range }
+   coOverflow   = -2; { Overflow }
+\end{verbatim}
+
+Maximum data sizes (used in determining how many data can be used.
+
+\begin{verbatim}
+CONST
+   MaxBytes = 128*1024*1024;                          { Maximum data size }
+   MaxWords = MaxBytes DIV SizeOf(Word);              { Max word data size }
+   MaxPtrs = MaxBytes DIV SizeOf(Pointer);            { Max ptr data size }
+   MaxCollectionSize = MaxBytes DIV SizeOf(Pointer);  { Max collection size }
+\end{verbatim}
+
+\section{Types}
+The follwing auxiliary types are defined:
+\begin{verbatim}
+TYPE
+   { Character set }
+   TCharSet = SET Of Char;                            
+   PCharSet = ^TCharSet;
+
+   { Byte array }
+   TByteArray = ARRAY [0..MaxBytes-1] Of Byte;        
+   PByteArray = ^TByteArray;
+
+   { Word array }
+   TWordArray = ARRAY [0..MaxWords-1] Of Word;        
+   PWordArray = ^TWordArray;
+
+   { Pointer array }
+   TPointerArray = Array [0..MaxPtrs-1] Of Pointer;   
+   PPointerArray = ^TPointerArray; 
+
+   { String pointer }
+   PString = ^String;
+
+   { Filename array }
+   AsciiZ = Array [0..255] Of Char;
+
+   Sw_Word    = Cardinal;
+   Sw_Integer = LongInt;
+\end{verbatim}
+The following records are used internaly for easy type conversion:
+\begin{verbatim}
+TYPE
+   { Word to bytes}
+   WordRec = packed RECORD
+     Lo, Hi: Byte;     
+   END;
+
+   { LongInt to words }
+   LongRec = packed RECORD
+     Lo, Hi: Word;
+   END;
+
+  { Pointer to words }
+   PtrRec = packed RECORD
+     Ofs, Seg: Word;
+   END;
+\end{verbatim}
+The following record is used when streaming objects:
+
+\begin{verbatim}
+TYPE
+   PStreamRec = ^TStreamRec;
+   TStreamRec = Packed RECORD
+      ObjType: Sw_Word;
+      VmtLink: pointer;
+      Load : Pointer;
+      Store: Pointer;
+      Next : PStreamRec;
+   END;
+\end{verbatim}
+
+The \var{TPoint} basic object is used in the \var{TRect} object (see
+\sees{TRect}):
+\begin{verbatim}
+TYPE
+   PPoint = ^TPoint;
+   TPoint = OBJECT
+      X, Y: Sw_Integer;
+   END;
+\end{verbatim}
+
+\section{TRect}
+\label{se:TRect}
+
+The \var{TRect} object is declared as follows:
+\begin{verbatim}
+   TRect = OBJECT
+      A, B: TPoint;
+      FUNCTION Empty: Boolean;
+      FUNCTION Equals (R: TRect): Boolean;
+      FUNCTION Contains (P: TPoint): Boolean;
+      PROCEDURE Copy (R: TRect);
+      PROCEDURE Union (R: TRect);
+      PROCEDURE Intersect (R: TRect);
+      PROCEDURE Move (ADX, ADY: Sw_Integer);
+      PROCEDURE Grow (ADX, ADY: Sw_Integer);
+      PROCEDURE Assign (XA, YA, XB, YB: Sw_Integer);
+   END;
+\end{verbatim}
+
+\begin{function}{TRect.Empty}
+\Declaration
+Function TRect.Empty: Boolean;
+\Description
+\var{Empty} returns \var{True} if the rectangle defined by the corner points 
+\var{A}, \var{B} has zero or negative surface.
+\Errors
+None.
+\SeeAlso
+\seef{TRect.Equals}, \seef{TRect.Contains}
+\end{function}
+
+\latex{\inputlisting{objectex/ex1.pp}}
+\html{\input{objectex/ex1.tex}}
+
+\begin{function}{TRect.Equals}      
+\Declaration
+Function TRect.Equals (R: TRect): Boolean;
+\Description
+\var{Equals} returns \var{True} if the rectangle has the 
+same corner points \var{A,B} as the rectangle R, and \var{False}
+otherwise.
+\Errors
+None.
+\SeeAlso
+\seef{TRect.Empty}, \seef{TRect.Contains}
+\end{function}
+
+For an example, see \seef{TRect.Empty}
+
+\begin{function}{TRect.Contains}
+\Declaration
+Function TRect.Contains (P: TPoint): Boolean;
+\Description
+\var{Contains} returns \var{True} if the point \var{P} is contained
+in the rectangle (including borders), \var{False} otherwise.
+\Errors
+None.
+\SeeAlso
+\seep{TRect.Intersect}, \seef{TRect.Equals}
+\end{function}
+
+\begin{procedure}{TRect.Copy}
+\Declaration     
+Procedure TRect.Copy (R: TRect);
+\Description
+Assigns the rectangle R to the object. After the call to \var{Copy}, the
+rectangle R has been copied to the object that invoked \var{Copy}.
+\Errors
+None.
+\SeeAlso
+\seep{TRect.Assign}
+\end{procedure}
+
+\latex{\inputlisting{objectex/ex2.pp}}
+\html{\input{objectex/ex2.tex}}
+
+\begin{procedure}{TRect.Union}
+\Declaration
+Procedure TRect.Union (R: TRect);
+\Description
+\var{Union} enlarges the current rectangle so that it becomes the union
+of the current rectangle with the rectangle \var{R}.
+\Errors
+None.
+\SeeAlso
+\seep{TRect.Intersect}
+\end{procedure}
+
+\latex{\inputlisting{objectex/ex3.pp}}
+\html{\input{objectex/ex3.tex}}
+
+\begin{procedure}{TRect.Intersect}
+\Declaration
+Procedure TRect.Intersect (R: TRect);
+\Description
+\var{Intersect} makes the intersection of the current rectangle with
+\var{R}. If the intersection is empty, then the rectangle is set to the empty
+rectangle at coordinate (0,0).
+\Errors
+None.
+\SeeAlso
+\var{TRect.Union}
+\end{procedure}
+
+\latex{\inputlisting{objectex/ex4.pp}}
+\html{\input{objectex/ex4.tex}}
+
+\begin{procedure}{TRect.Move}
+\Declaration
+Procedure TRect.Move (ADX, ADY: Sw\_Integer);
+\Description
+\var{Move} moves the current rectangle along a vector with components
+\var{(ADX,ADY)}. It adds \var{ADX} to the X-coordinate of both corner
+points, and \var{ADY} to both end points.
+\Errors
+None.
+\SeeAlso
+\seep{TRect.Grow}
+\end{procedure}
+
+\latex{\inputlisting{objectex/ex5.pp}}
+\html{\input{objectex/ex5.tex}}
+
+\begin{procedure}{TRect.Grow}
+\Declaration
+Procedure TRect.Grow (ADX, ADY: Sw\_Integer);
+\Description
+\var{Grow} expands the rectangle with an amount \var{ADX} in the \var{X}
+direction (both on the left and right side of the rectangle, thus adding a 
+length 2*ADX to the width of the rectangle), and an amount \var{ADY} in 
+the \var{Y} direction (both on the top and the bottom side of the rectangle,
+adding a length 2*ADY to the height of the rectangle. 
+
+X and Y can be negative. If the resulting rectangle is empty, it is set 
+to the empty rectangle at \var{(0,0)}.
+\Errors
+None.
+\SeeAlso
+\seep{TRect.Move}.
+\end{procedure}
+
+
+\latex{\inputlisting{objectex/ex6.pp}}
+\html{\input{objectex/ex7.tex}}
+
+\begin{procedure}{TRect.Assign}
+\Declaration
+Procedure Trect.Assign (XA, YA, XB, YB: Sw\_Integer);
+\Description
+\var{Assign} sets the corner points of the rectangle to \var{(XA,YA)} and 
+\var{(Xb,Yb)}.
+\Errors
+None.
+\end{procedure}
+
+For an example, see \seep{TRect.Copy}.
+
+\section{TObject}
+\label{se:TObject}
+
+The full declaration of the \var{TObject} type is:
+\begin{verbatim}
+TYPE
+   TObject = OBJECT
+      CONSTRUCTOR Init;
+      PROCEDURE Free;
+      DESTRUCTOR Done;Virtual;
+   END;
+   PObject = ^TObject;
+\end{verbatim}
+\begin{procedure}{TObject.Init}
+\Declaration
+Constructor TObject.Init;
+\Description
+Instantiates a new object of type \var{TObject}. It fills the instance up
+with Zero bytes.
+\Errors
+None.
+\SeeAlso
+\seep{TObject.Free}, \seep{TObject.Done}
+\end{procedure}
+
+For an example, see \seep{TObject.Free}
+
+\begin{procedure}{TObject.Free}
+\Declaration
+Procedure TObject.Free;
+\Description
+\var{Free} calls the destructor of the object, and releases the memory
+occupied by the instance of the object.
+\Errors
+No checking is performed to see whether \var{self} is \var{nil} and whether
+the object is indeed allocated on the heap.
+\SeeAlso
+\seep{TObject.Init}, \seep{TObject.Done}
+\end{procedure}
+
+\latex{\inputlisting{objectex/ex7.pp}}
+\html{\input{objectex/ex7.tex}}
+
+\begin{procedure}{TObject.Done}
+\Declaration
+Destructor TObject.Done;Virtual;
+\Description
+\var{Done}, the destructor of \var{TObject} does nothing. It is mainly
+intended to be used in the \seep{TObject.Free} method.
+\Errors
+None.
+\SeeAlso
+\seep{TObject.Free}, \seep{TObject.Init}
+\end{procedure}
+
+\section{TStream}
+\label{se:TStream}
+
+The \var{TStream} object is the ancestor for all streaming objects, i.e.
+objects that have the capability to store and retrieve data.
+
+It defines a number of methods that are common to all objects that implement
+streaming, many of them are virtual, and are only implemented in the
+descendant types.
+
+Programs should not instantiate objects of type TStream directly, but
+instead instantiate a descendant type.
+
+This is the full declaration of the \var{TStream} object:
+\begin{verbatim}
+TYPE
+   TStream = OBJECT (TObject)
+         Status    : Integer; { Stream status }
+         ErrorInfo : Integer; { Stream error info }
+         StreamSize: LongInt; { Stream current size }
+         Position  : LongInt; { Current position }
+      FUNCTION Get: PObject;
+      FUNCTION StrRead: PChar;
+      FUNCTION GetPos: Longint; Virtual;
+      FUNCTION GetSize: Longint; Virtual;
+      FUNCTION ReadStr: PString;
+      PROCEDURE Open (OpenMode: Word); Virtual;
+      PROCEDURE Close; Virtual;
+      PROCEDURE Reset;
+      PROCEDURE Flush; Virtual;
+      PROCEDURE Truncate; Virtual;
+      PROCEDURE Put (P: PObject);
+      PROCEDURE StrWrite (P: PChar);
+      PROCEDURE WriteStr (P: PString);
+      PROCEDURE Seek (Pos: LongInt); Virtual;
+      PROCEDURE Error (Code, Info: Integer); Virtual;
+      PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual;
+      PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual;
+      PROCEDURE CopyFrom (Var S: TStream; Count: Longint);
+   END;
+   PStream = ^TStream;
+\end{verbatim}
+
+\section{TDosStream}
+\label{se:TDosStream}
+
+\begin{verbatim}
+TYPE
+   TDosStream = OBJECT (TStream)
+         Handle: THandle; { DOS file handle }
+         FName : AsciiZ;  { AsciiZ filename }
+      CONSTRUCTOR Init (FileName: FNameStr; Mode: Word);
+      DESTRUCTOR Done; Virtual;
+      PROCEDURE Close; Virtual;
+      PROCEDURE Truncate; Virtual;
+      PROCEDURE Seek (Pos: LongInt); Virtual;
+      PROCEDURE Open (OpenMode: Word); Virtual;
+      PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual;
+      PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual;
+   END;
+   PDosStream = ^TDosStream;
+\end{verbatim}
+
+\section{TBufStream}
+\label{se:TBufStream}
+
+\begin{verbatim}
+TYPE
+   TBufStream = OBJECT (TDosStream)
+         LastMode: Byte;       { Last buffer mode }
+         BufSize : Sw_Word;    { Buffer size }
+         BufPtr  : Sw_Word;    { Buffer start }
+         BufEnd  : Sw_Word;    { Buffer end }
+         Buffer  : PByteArray; { Buffer allocated }
+      CONSTRUCTOR Init (FileName: FNameStr; Mode, Size: Word);
+      DESTRUCTOR Done; Virtual;
+      PROCEDURE Close; Virtual;
+      PROCEDURE Flush; Virtual;
+      PROCEDURE Truncate; Virtual;
+      PROCEDURE Seek (Pos: LongInt); Virtual;
+      PROCEDURE Open (OpenMode: Word); Virtual;
+      PROCEDURE Read (Var Buf; Count: Sw_Word); Virtual;
+      PROCEDURE Write (Var Buf; Count: Sw_Word); Virtual;
+   END;
+   PBufStream = ^TBufStream;
+\end{verbatim}
+
+\section{TMemoryStream}
+\section{se:TMemoryStream}
+
+\begin{verbatim}
+TYPE
+   TMemoryStream = OBJECT (TStream)
+         BlkCount: Sw_Word;                           { Number of segments }
+         BlkSize : Word;                              { Memory block size }
+         MemSize : LongInt;                           { Memory alloc size }
+         BlkList : PPointerArray;                     { Memory block list }
+      CONSTRUCTOR Init (ALimit: Longint; ABlockSize: Word);
+      DESTRUCTOR Done;                                               Virtual;
+      PROCEDURE Truncate;                                            Virtual;
+      PROCEDURE Read (Var Buf; Count: Sw_Word);                      Virtual;
+      PROCEDURE Write (Var Buf; Count: Sw_Word);                     Virtual;
+      PRIVATE
+      FUNCTION ChangeListSize (ALimit: Sw_Word): Boolean;
+   END;
+   PMemoryStream = ^TMemoryStream;
+\end{verbatim}
+
+\section{TCollection}
+\label{se:TCollection}
+
+\begin{verbatim}
+TYPE
+   TItemList = Array [0..MaxCollectionSize - 1] Of Pointer;
+   PItemList = ^TItemList;
+
+   TCollection = OBJECT (TObject)
+         Items: PItemList;  { Item list pointer }
+         Count: Sw_Integer; { Item count }
+         Limit: Sw_Integer; { Item limit count }
+         Delta: Sw_Integer; { Inc delta size }
+      CONSTRUCTOR Init (ALimit, ADelta: Sw_Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION At (Index: Sw_Integer): Pointer;
+      FUNCTION IndexOf (Item: Pointer): Sw_Integer; Virtual;
+      FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
+      FUNCTION LastThat (Test: Pointer): Pointer;
+      FUNCTION FirstThat (Test: Pointer): Pointer;
+      PROCEDURE Pack;
+      PROCEDURE FreeAll;
+      PROCEDURE DeleteAll;
+      PROCEDURE Free (Item: Pointer);
+      PROCEDURE Insert (Item: Pointer); Virtual;
+      PROCEDURE Delete (Item: Pointer);
+      PROCEDURE AtFree (Index: Sw_Integer);
+      PROCEDURE FreeItem (Item: Pointer); Virtual;
+      PROCEDURE AtDelete (Index: Sw_Integer);
+      PROCEDURE ForEach (Action: Pointer);
+      PROCEDURE SetLimit (ALimit: Sw_Integer); Virtual;
+      PROCEDURE Error (Code, Info: Integer); Virtual;
+      PROCEDURE AtPut (Index: Sw_Integer; Item: Pointer);
+      PROCEDURE AtInsert (Index: Sw_Integer; Item: Pointer);
+      PROCEDURE Store (Var S: TStream);
+      PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
+   END;
+   PCollection = ^TCollection;
+\end{verbatim}
+
+\section{TSortedCollection}
+\label{se:TSortedCollection}
+
+\begin{verbatim}
+TYPE
+   TSortedCollection = OBJECT (TCollection)
+         Duplicates: Boolean; { Duplicates flag }
+      CONSTRUCTOR Init (ALimit, ADelta: Sw_Integer);
+      CONSTRUCTOR Load (Var S: TStream);
+      FUNCTION KeyOf (Item: Pointer): Pointer; Virtual;
+      FUNCTION IndexOf (Item: Pointer): Sw_Integer; Virtual;
+      FUNCTION Compare (Key1, Key2: Pointer): Sw_Integer; Virtual;
+      FUNCTION Search (Key: Pointer; Var Index: Sw_Integer): Boolean;Virtual;
+      PROCEDURE Insert (Item: Pointer); Virtual;
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PSortedCollection = ^TSortedCollection;
+\end{verbatim}
+
+\section{TStringCollection}
+\label{se:TStringCollection}
+
+\begin{verbatim}
+TYPE
+   TStringCollection = OBJECT (TSortedCollection)
+      FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
+      FUNCTION Compare (Key1, Key2: Pointer): Sw_Integer; Virtual;
+      PROCEDURE FreeItem (Item: Pointer); Virtual;
+      PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
+   END;
+   PStringCollection = ^TStringCollection;
+\end{verbatim}
+
+\section{TStrCollection}
+\label{se:TStrCollection}
+
+\begin{verbatim}
+TYPE
+   TStrCollection = OBJECT (TSortedCollection)
+      FUNCTION Compare (Key1, Key2: Pointer): Sw_Integer; Virtual;
+      FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
+      PROCEDURE FreeItem (Item: Pointer); Virtual;
+      PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
+   END;
+   PStrCollection = ^TStrCollection;
+\end{verbatim}
+
+
+\section{TUnSortedStrCollection}
+\label{se:TUnSortedStrCollection}
+
+\begin{verbatim}
+TYPE
+   TUnSortedStrCollection = OBJECT (TStringCollection)
+      PROCEDURE Insert (Item: Pointer); Virtual;
+   END;
+   PUnSortedStrCollection = ^TUnSortedStrCollection;
+\end{verbatim}
+
+\section{TResourceCollection}
+\label{se:TResourceCollection}
+
+\begin{verbatim}
+TYPE
+   TResourceCollection = OBJECT (TStringCollection)
+      FUNCTION KeyOf (Item: Pointer): Pointer; Virtual;
+      FUNCTION GetItem (Var S: TStream): Pointer; Virtual;
+      PROCEDURE FreeItem (Item: Pointer); Virtual;
+      PROCEDURE PutItem (Var S: TStream; Item: Pointer); Virtual;
+   END;
+   PResourceCollection = ^TResourceCollection;
+\end{verbatim}
+
+\section{TResourceFile}
+\label{se:TResourceFile}
+
+\begin{verbatim}
+TYPE
+   TResourceFile = OBJECT (TObject)
+         Stream  : PStream; { File as a stream }
+         Modified: Boolean; { Modified flag }
+      CONSTRUCTOR Init (AStream: PStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION Count: Sw_Integer;
+      FUNCTION KeyAt (I: Sw_Integer): String;
+      FUNCTION Get (Key: String): PObject;
+      FUNCTION SwitchTo (AStream: PStream; Pack: Boolean): PStream;
+      PROCEDURE Flush;
+      PROCEDURE Delete (Key: String);
+      PROCEDURE Put (Item: PObject; Key: String);
+   END;
+   PResourceFile = ^TResourceFile;
+\end{verbatim}
+
+\section{TStringList}
+\label{se:TStringList}
+
+\begin{verbatim}
+TYPE
+   TStrIndexRec = Packed RECORD
+      Key, Count, Offset: Word;
+   END;
+
+   TStrIndex = Array [0..9999] Of TStrIndexRec;
+   PStrIndex = ^TStrIndex;
+
+   TStringList = OBJECT (TObject)
+      CONSTRUCTOR Load (Var S: TStream);
+      DESTRUCTOR Done; Virtual;
+      FUNCTION Get (Key: Sw_Word): String;
+   END;
+   PStringList = ^TStringList;
+\end{verbatim}
+
+\section{TStrListMaker}
+\label{se:TStrListMaker}
+
+\begin{verbatim}
+TYPE
+   TStrListMaker = OBJECT (TObject)
+      CONSTRUCTOR Init (AStrSize, AIndexSize: Sw_Word);
+      DESTRUCTOR Done; Virtual;
+      PROCEDURE Put (Key: Sw_Word; S: String);
+      PROCEDURE Store (Var S: TStream);
+   END;
+   PStrListMaker = ^TStrListMaker;
+\end{verbatim}
+
+\begin{verbatim}
+FUNCTION NewStr (Const S: String): PString;
+PROCEDURE DisposeStr (P: PString);
+PROCEDURE Abstract;
+PROCEDURE RegisterObjects;
+PROCEDURE RegisterType (Var S: TStreamRec);
+FUNCTION LongMul (X, Y: Integer): LongInt;
+FUNCTION LongDiv (X: Longint; Y: Integer): Integer;
+
+CONST
+   StreamError: Pointer = Nil;                        { Stream error ptr }
+   DosStreamError: Word = $0;                      { Dos stream error }
+
+CONST
+   RCollection: TStreamRec = (
+     ObjType: 50;
+     VmtLink: Ofs(TypeOf(TCollection)^);
+     Load: @TCollection.Load;
+     Store: @TCollection.Store);
+
+   RStringCollection: TStreamRec = (
+     ObjType: 51;
+     VmtLink: Ofs(TypeOf(TStringCollection)^);
+     Load: @TStringCollection.Load;
+     Store: @TStringCollection.Store);
+
+   RStrCollection: TStreamRec = (
+     ObjType: 69;
+     VmtLink: Ofs(TypeOf(TStrCollection)^);
+     Load:    @TStrCollection.Load;
+     Store:   @TStrCollection.Store);
+
+   RStringList: TStreamRec = (
+     ObjType: 52;
+     VmtLink: Ofs(TypeOf(TStringList)^);
+     Load: @TStringList.Load;
+     Store: Nil);
+
+   RStrListMaker: TStreamRec = (
+     ObjType: 52;
+     VmtLink: Ofs(TypeOf(TStrListMaker)^);
+     Load: Nil;
+     Store: @TStrListMaker.Store);
+\end{verbatim}