
How !Linker works



Linker takes an Image file (typically a !RunImage) and a Library file
(typically a DrWimp library) and produces an output file which
comprises the *untouched* Image file which has added to it only those
DEFs from the Library file which are necessary.

'Necessary' means those Library DEFs which are called by the original
Image file ('primary DEFs') plus any other Library DEFs which are, in
turn, called by the 'primary DEFs' - and this means recursively down
as many levels as necessary.

----------

The app firstly measures both Image and Library files and finds the
larger of the two. It then sets up a block in a dynamic area which is
*twice* the size of the larger file. The start of the block is called
Buffer% and the halfway point is called Bits%.

Buffer% is only created just before it is needed (in PROClink), and
is deleted again once it is no longer needed (at the end of PROClink).

----------

The Image file is copied into Buffer% and it is scanned to find the
names of all DEFs contained in it and the names of all PROC/FN calls
made in it. These two sets of names are stored in two arrays
Ifuncdef$() & Ifunccall$(). [Note 'I' for Image] If a call in the
Image is made to a DEF which also appears in the Image then the call
is eliminated. Also, of course, more than one call to the same DEF is
eliminated. The total number of Image calls and Image DEFs are also
logged - as well as the highest Line No. used by the Image.

----------

The Library file is then copied into Buffer% (i.e. overwriting the
Image) and a similar - but not identical - scan takes place. This
time, in addition to the DEF and PROC/FN call names being put into
arrays Lfuncdef$() & Lfunccall$() ['L' for Library], the position of
each DEF in the Library listing (its byte position) is put into the
array Lfunccallpos$(). Further, if that DEF *is called by* other
*Library* DEFs then  the reference number(s) of these other (calling)
DEF(s) is/are added as a comma-separated string in Lfunccallpos$().

[Note that the index of Lfuncdef$() is used as the reference number of
the Library DEFs - the number merely reflects the order in which the
DEFs appear in the Library listing.]

The logged byte position of a Library DEF is actually the position of
the byte after the &0D byte which signals the start of the first Basic
line of the DEF. [Note: Beware of using Zap to look at bytes - Zap
uses its own method for line header bytes.]

Again, duplicate calls are eliminated and any calls to DEFs which are
in the Image file (typically, the 'user-function' calls).

----------

So, the result of the initial scans is several arrays containing lists
of the *names* of the DEFs and PROC/FN calls for the untouched Image
and Library files - plus the Library file DEF positions and reference
numbers of any 'recursive' PROC/FN calls made by the Library DEFs to
any other Library DEF.

For the Library arrays only, the app stores the initial scan results
in a data file called 'PreviousLib' (in the 'Res' folder) - and if
exactly the same Library file is used again the saved file is used to
populate the arrays instead of a new scan - to save time.

----------

With the two sets of arrays in place the compilation of the output
file needs begins - and remember that the untouched Library file is
still in place in Buffer%.

The compilation is mainly done by manipulating the arrays and
progressively adding array elements to the Image arrays by copying
appropriate elements from the Library arrays. However, the actual
process is iterative, taking several passes (which are indicated
visually).

For the first pass, each PROC/FN call name in the initial Ifunccall$()
array - which, don't forget, only contains PROC/FN calls to Library
DEFs - is checked against the names in the array holding the names of
Library DEFs. If a match is found, the appropriate section of Buffer%
(the loaded Library listing) is accessed and just that DEF is copied
to the lowest available location in Bits% (empty at the start). Also
the Image array Ifuncdef$() has the copied DEF added to it and
Ifunctot% incremented.

After copying this match the stored 'recursive' calls detail is
scanned to see which other Library DEFs contain a reference indicating
that they are called by the above-matched DEF. If any are found then -
after checking that the corresponding DEFs are not already in the
Image DEF array (and which might have only just been added) - these
calls are added to the Image call list array (and its total number
adjusted correspondingly).

The first pass will thus copy cumulatively to Bits% extracts from
Buffer% corresponding to the Library DEFs that are needed to meet the
*initial* Image PROC/FN call list array. It will also add DEFs and
calls to the Image arrays, but the extra *calls* will not be actioned
this time round.

----------

The same process then starts again *from scratch* for the second pass.

That is, the (new) Image PROC/FN call list array is again scanned to
check the names in the array holding the names of Library DEFs. This
time, the calls which were in the original Image PROC/FN call list
array will be skipped over as they have been processed in Pass 1 and
this second pass will pick up the Image calls added in Pass 1 due to
the 'recursive' factor. The corresponding Library DEFs will be copied
to Bits%. And, in turn, it is likely that there will be a need to add
more 'recursive' calls to the Image call list.

----------

The passes continue until all Library calls are processed without a
need to add to the Library DEF list i.e. generally, no more
'recursive' calls are needed.

----------

When this state is reached, Bits% will contain only those parts of the
Library needed by Image.

Bits% is then scanned to change all of its Line Nos. to an increment
of 1.

----------

Finally, the Image is once more loaded into Buffer% and - depending on
choices set - Basic LIBRARY calls are eliminated from it.

The contents of Buffer% (i.e. just the first 'half' of the dynamic
area) are then saved as a new Basic output file. This file is then
opened and the contents of Bits% is appended to it.

----------

That's it Folks!


