home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
CLIPPER
/
CLIPTIPS.ZIP
/
LINKERS.ZIP
/
LINKERS.DOC
Wrap
Text File
|
1990-07-07
|
109KB
|
2,602 lines
════════════════════════════════════════════════════════════════
-- CLIPPER LINKERS --
THE NEW DIRECTION OF CLIPPER DEVELOPMENT
════════════════════════════════════════════════════════════════
Since the introduction of the Clipper-compiler in Winter, 1985,
a plethora of Clipper third-party products have flooded the
Clipper aftermarket. These add-on libraries have successfully
extended the Clipper language into the most powerful database
development system for microcomputers. Applications developed
with Clipper and third-party libraries are growing larger and
more powerful, thereby causing some new development problems:
1. Slower development time
2. Excessive application memory usage
The new direction of Clipper Add-on products is to help solve
these new problems. The most popular of the new products are
those which work towards improving the speed of development and
the memory usage at runtime - "dynamic" linkers.
In this article, I hope to be able to convey information based
on my own experience as a Clipper developer. In my opinion,
there is too much discussion about future products, and too
little discussion about products which are solving big
development problems - right now! The development community
is moving away from software packages which promise a
"complete database solution" to those which offer an
"open architecture" so we developers are free to choose our
own tools, libraries and development environment. As the
developer of dCLIP, a Clipper development platform, we have
used or are using at least 12 different Clipper linker
products.
Case studies of successful Clipper applications point to the
fact that the developer has learned not only to become a
"library-an" but is also "multi-linkeral". The professional
Clipper developer is now accustomed to using more than one
linker in development projects. One of our development
projects consists of 5 Clipper .EXE programs and uses the
technology of 4 different linkers.
The discussion of linkers raises a lot of questions. Why can't
a developer use a single linker for all of his projects? If
new linkers are getting better, then why not ring out the old
and ring in the new? Are not linkers just a final process in
converting the compiled object code to be machine readable code?
The purpose of this article is to help dispel a lot of the myths,
hype, and (most-of-all) fears that confront the Clipper
developer today when it comes to the subject of linking. I am
constantly amazed at the amount of time a professional Clipper
programmer will spend in learning the nuances and power of the
the Clipper language, yet that same professional probably has
the equivalent of a kindergarten education in the subject of
linking.
Page 1 - Copyright (c) DONNAY Software
Today, the Clipper developer must be more educated about linkers
to remain competitive. If you ask the Clipper programmer about
his biggest frustrations, he/she will virtually always answer
the same way - memory usage and development time. The new
series of linkers are designed to address these problems and
many others. Some do it better than others. Some will use
"dynamic" techniques, others will use "static" techniques. Some
are designed to work best with only Clipper code, others are
designed to work best with applications that are Clipper/C/ASM.
Some are designed to link very fast, others are slow but produce
better memory management. Some are designed for small
applications, others are designed for huge applications and
networks. Some are designed to help with distribution and disk
usage, others are designed to help with debugging. Some are
designed for ease-of-use and quick-starting, others are designed
to solve complicated memory and symbol issues. Some are
designed to work well with any combination of library and object
format, others will choke on just about anything. Some linkers
are mature, slow and reliable, others are young, frisky and not
very well-behaved.
As a developer who creates programmer's tools, I talk to many
Clipper programmers every day, because I also handle technical
support for our product, dCLIP. I am constantly amazed at the
number of Clipper programmers who still use only one linker -
PLINK86. Why is this so? Are their applications so small that
they don't need better memory management? Is their time so
well managed that the speed of linking is not important? Most
often, the answer is none of the above. Clipper programmers,
like many other professionals, are afraid of making a wrong
choice, and feeling like a fool for spending good money on a
folly. You have heard it said that "the only stupid question is
the one that is never asked". Well, I my philosophy is "the only
folly is one that is never ventured". My knowledge of linkers
came from purchasing every one and using each one. Over the
years I have developed an understanding of linking by trial and
error and have gained quite an education.
To the Clipper developer, the quality of his/her end product is
everything, that is why Clipper is the most popular database
development language for microcomputers. Choosing the right
linker for each job will improve the performance and quality of
your applications. This article is designed to help you make
those choices. It is not the intent of the author to dump a lot
of sophisticated "linking terms" on the reader of this article.
I am a Clipper programmer who has had to work out a knowledge of
linkers all by myself. There is still a lot I do not understand
about linking, but what I have learned has helped me develop a
sufficient competitive edge and made it possible to produce a
product such as dCLIP. I expect that I will learn a lot more as
you, the reader, responds with your own experiences and
knowledge, therefore I welcome any feedback.
Together, I think we can battle our way through this linker
"war zone" and emerge victorious.
Page 2 - Copyright (c) DONNAY Software
The subject of linkers will be addressed in 5 sections:
1. Introduction/Background
a. What is linking?
b. Glossary of linking terms
2. Linking tips for memory management
a. Static Overlays
b. Reloadable Overlays
c. Dynamic Overlays
d. Dynamic Linking
e. Virtual Overlays
f. Symbol Management
3. Linking tips for productivity and project management
a. Pre-linked Libraries
b. Dynamic Linking
c. Incremental Linking
d. Speed-Linking
e. Library-Module Linking
4. Feature, price, performance comparison and chart
a. RTLINK, RTLINK-5.0, RTLINKplus
b. PLINK86s87, PLINK86plus
c. BLINKER
d. ALINK
e. TLINK
f. MS-LINK
g. WARPLINK
h. NOLINK
i. dCLIP, dCLIPRUN
5. Choosing a linker for your projects
a. Case studies of 5 projects
Page 3 - Copyright (c) DONNAY Software
════════════════════════════════════════════════════════════════
Introduction/Background
════════════════════════════════════════════════════════════════
What is linking?
Linkers are a subject which most Clipper programmers don't
like to talk about because of a "fear" that the technology
will be too sophisticated to understand. The process of
linking is no more sophisticated than the compiler itself, it
is just done at a lower level and produces machine-readable
code. It is really the compiler which produces the machine
readable code, but the linker has the responsibility of insuring
that the compiled code is accessible or "linked" to other
code segments. Linking or "fixing up" references made by the
the code to external variables and functions is necessary to
insure that the program will address or call other programs,
including DOS functions.
Linking can be accomplished at many different stages in the
development or running of an application. Most linking occurs at
the time that an .EXE file is created. This is usually the most
sophisticated and time consuming of linking processes. Linking
also occurs during "load-time" when an application is being
loaded into memory for execution. Even DOS has a built-in linker.
It fixes up references to specific code segments in an .EXEcutable
file at the time that it loads the .EXE into memory. Some linkers
provide additional load-time linking by using pre-link libraries
and fixing up references between several files at load-time.
Other linkers are "dynamic" and load code into memory during
the running of the application. Each one of these linking
techniques provides a specific advantage to the developer. If
you don't understand what these advantages are, your development
projects are probably not "state-of-the-art" and may be lacking
at some level of performance, usually, in the management of
memory at runtime.
A linker's basic job is to combine objects which have been
compiled separately. Objects contain symbols of three types:
a. PUBLIC symbols - those symbols which are callable from
other objects
b. STATIC symbols - those symbols which are callable only
from within the same object
c. UNDEFINED symbols - symbols which exist in other objects
and are referenced or used by this object
(also referred to as EXTERNAL symbols).
Page 4 - Copyright (c) DONNAY Software
The linker "resolves" an object's external symbols by scanning
the other objects public lists either in their object files or
in library cross-reference indexes. Linkers usually accomplish
this task in "2 passes". The first pass is to locate all the
symbols by reading the symbol references into memory from all the
object files and libraries and assigning a segment address to
each symbol. The second pass is the actual "fixing up" of the
symbols and generation of the .EXEcutable program. During pass 2,
the linker searches all the object files and libraries again to
see if one contains a PUBLIC definition for each unresolved
symbol. When it finds one, it links the object by assigning an
address or "fixing-up" the reference from the calling symbol to
the called symbol. If none of an object's PUBLIC symbols are
referenced by another object, that object is not linked into the
.EXEcutable.
GLOSSARY of Linking Terminology
.EXEcutable file - A linked program that the operating system
can execute.
OBJECT file - A file produced by the compiler used as an input
file by the linker. Also referred to as a
relocatable file because it contains code that can
be modified by the linker to execute at any memory
address.
MODULE - Another term of reference for an OBJECT. A module
name is assigned by the compiler to each object
so it can be referenced in libraries.
SECTION - A section is a unit of linked, executable code for
handling by the overlay manager. A section is
usually an overlay - a portion of the executable
file that is loaded into memory as a single unit.
SEGMENT - A piece of code or data that is manipulated by the
linker as an indivisble unit.
PUBLIC - Segments of code or data that can be combined
SEGMENTS with other segments of the same segment and class
name to occupy adjacent locations in memory.
PRIVATE - Segments of code or data that cannot be
SEGMENTS combined with other segments to occupy adjacent
memory locations.
OVERLAY - A section of code or data that shares all or part
of its memory allocation with other sections.
LIBRARY - A file containing relocatable modules which are
individually available to the linker. Libraries
usually include indexes of PUBLIC symbols.
Page 5 - Copyright (c) DONNAY Software
SYMBOL - The assigned name for a value that is a constant
(absolute symbol) or the address of a program
component (relative symbol).
PUBLIC - A symbol whose relative address is designated by
SYMBOL the compiler to be available for modules other than
the module that defines it.
STATIC - A symbol whose relative address is designated by
SYMBOL the compiler to be available only for the module
that defines it.
EXTERNAL - A symbol that is not defined in a module that
SYMBOL references it. The linker "fixes" these references
when their values become known.
Page 6 - Copyright (c) DONNAY Software
════════════════════════════════════════════════════════════════
Linking Tips for Memory-Management
════════════════════════════════════════════════════════════════
In almost all cases, memory management is accomplished by the
use of "overlays". Many Clipper programmers have been reluctant
to use overlay linkers because they heard how difficult they are
to manage. This may have been true in the past, but overlay
managers have become much more sophisticated in the past two
years. In order to understand how to choose a linker for memory
management, we must first examine the methods in which linkers
accomplish this task. They are as follows:
1. Static Overlays
2. Reloadable Overlays
3. Dynamic Overlays
4. Dynamic Linking
5. Virtual Overlays
6. Symbol Management
7. Memory Packing
8. Memory Allocation
STATIC OVERLAYS
"Static overlays" are segments of code which are placed into
overlay sections that occupy the same memory space at runtime.
Static overlay segments usually look like this in your link
file:
# area 1
BEGINAREA
SECTION FILE A
SECTION FILE B
SECTION FILE C
ENDAREA
# area 2
BEGINAREA
SECTION FILE D
SECTION FILE E
SECTION FILE F
ENDAREA
If your linker uses static overlays (PLINK86, PLINK86plus),
then you must be sure that you properly place your objects in
the overlay segments to prevent computer "lock-up" or "crashing"
at runtime. In the above example, any procedure or function in
FILE A may call any procedure or function in FILE D - F because
they are in different areas, however if a function in FILE A
calls a procedure or function in FILE B, then your program will
crash as soon as the program returns to FILE A because FILE A
was removed from memory to load FILE B.
Page 7 - Copyright (c) DONNAY Software
Overlay management with "static overlays" is the most time-
consuming because it requires extensive analysis of the
structure of the program to insure that the modules are placed
properly in the overlay areas.
RELOADABLE OVERLAYS
"Reloadable overlays" are segments of code which are placed
into overlay sections that occupy the same memory space at
runtime, however the "calling module" is automatically
"reloaded" into memory when returning from the "called module".
Reloadable overlay segments usually look like this in your link
file:
RELOAD FAR 200
# area 1
BEGINAREA
SECTION FILE A
SECTION FILE B
SECTION FILE C
ENDAREA
# area 2
BEGINAREA
SECTION FILE D
SECTION FILE E
SECTION FILE F
ENDAREA
If your linker allows reloadable overlays (RTLINK, RTLINK+),
then you are not in danger of "lockup" in the event that a
procedure or function in FILE A calls a function or procedure
in FILE B because FILE A will be reloaded into memory on return
from FILE B.
Your application will experience slowing, however, if overlays
are not structured properly, because each time an overlay is
reloaded the application must go to disk. In the above example
if a function in FILE A repetitiveley calls a function in FILE B
then your application will be very "disk intensive" and will run
slowly. If a function in FILE A repetitively calls a function
in FILE D there will be no slowing at all because both modules
will remain in memory.
Overlay management with "reloadable overlays" is the less time-
consuming than "static overlays" and provides an additional
advantage of allowing more modules to be overlayed, thereby
saving additional memory usage. Overlay managers which provide
"RELOAD" commands usually limit the automatic reloading to
either "NEAR" or "FAR" calls. The Clipper-compiler mixes both
near and far calls therefore Clipper-compiled code cannot be
overlayed in this manner. The generic versions of RTLINK,
RTLINK+ and PLINK86plus all support overlay reloading, but the
modules overlayed in this manner must be C/ASM modules from the
CLIPPER/EXTEND libraries or third-party libraries, NOT
clipper-compiled objects.
Page 8 - Copyright (c) DONNAY Software
DYNAMIC OVERLAYS
"Dynamic Overlays" are segments of code which are loaded into a
"memory pool" at runtime. Dynamic overlay segments usually
look like this in your link file:
# only 1 area needed
BEGINAREA
SECTION FILE A
SECTION FILE B
SECTION FILE C
SECTION FILE D
SECTION FILE E
SECTION FILE F
ENDAREA
In the above example, if a function in FILE A calls a function
in FILE B, then FILE B is loaded into the memory pool along with
FILE A and the memory pool is "dynamically" managed to insure
that modules which call each other repetitively will remain in
memory to improve speed performance. Some dynamic overlay
linkers also provide automatic "reloading" to insure that the
application will always have sufficient memory in the pool.
Modules which don't need to be in the memory pool will be
removed to allow room for others at runtime.
Dynamic overlay linkers (ALINK, BLINKER, WARPLINK) offer the
advantage of simpler overlay design and usually better memory
management. Some also have a tendency to "fragment" the
Clipper free memory pool because they share the heap with the
Clipper application rather than allocating a separate dos memory
area. This can cause applications to run out of memory after
prolonged running of the application if there is not sufficient
memory overhead at the start of the application. Some dynamic
overlay linkers also support overlay management by "frequency of
usage". If a module is called often during the running of an
application, it will remain in the overlay pool rather than
being "swapped out" to load other overlays. This insures
optimum runtime performance.
Dynamic-overlay linkers such as WARPLINK and BLINKER both
make a disclaimer in their documentation requiring that the
objects being overlayed are "well-behaved". There is no
specification for "well-behaved" objects, but there is a
specification for "well-behaved" linkers. It appears that
these new "dynamic overlay" linkers are hoping to change the
rules for compilers so they will be compatible with the
limitations of their technology. As a third-party products
developer, this is aggravating to me because it is now
necessary to develop a special release of the dCLIP
libraries for compatability with these linkers. In the long
run, I believe these linkers will survive only if they work
flawlessly with existing libraries.
Page 9 - Copyright (c) DONNAY Software
DYNAMIC LINKING
True "Dynamic linkers" should not be confused with "Dynamic
Overlay" linkers. Dynamic overlay linkers perform all the
linking and fix-ups for the entire application at one time
and then produce an .EXEcutable program. True "dynamic linkers"
perform all the linking and fix-ups at "runtime" by linking
from your .OBJ files or "dynamic-libraries" during the
running of the application.
Dynamic linkers (dCLIP, dCLIPRUN, NOLINK) provide the best
memory-management for very large applications. All other forms
of linkers still require that each symbol reference in the
application be resolved at link time and assigned an address in
the "root" memory area. Even the most sophisticated of overlay
management schemes cannot eliminate the need to create this
"symbol table", therefore the memory usage of a program will
always increase proportionally with the number of symbols in the
.OBJects regardless of the overlay technique.
Dynamic linkers solve this problem by adding to the "root-
memory" symbol table only if a function or procedure is called
at runtime. Dynamic linkers will load the executable portion of
the code into an "object pool" and perform the symbol fixups in
the main heap area. Once a symbol has been added to the heap,
it will stay in memory even after returning from the called
function, however the executable code may be removed from the
object pool to make space for new objects which may be called
by the application.
Dynamic linkers also allow linking from sets of dynamic
libraries during the running of an application therefore large
applications such as accounting systems can be distributed
with one .EXE (the "dynamic-link engine") and multiple "dynamic-
libraries".
VIRTUAL OVERLAYS
Virtual Overlaying is a technique developed by Pocket Soft,
Inc. and is being introduced in the special .RTLINK supplied
with Clipper 5.0. Unlike "dynamic overlays" which are "read-
only", virtual overlay managers not only overlay the CODE
portion of a module, but also the portion of a module which is
changed during the running of an application - the DATA. The
data changes are written out to disk in temporary files which
are managed during the running of the application.
When executing a program using virtual overlaying, the code is
paged from disk to memory on a "least recently used" basis.
This means that code which has not been used for a while is
overwritten to make room for the new code, leaving frequently
used code in memory.
Page 10 - Copyright (c) DONNAY Software
Virtual overlay linkers dynamically allocate the size of the
object pool for paging code in accordance with the memory
available during the start of the application. The more memory
that is available, the less "disk-intensive" the application
and the better the speed performance.
At the writing of this article, my experience with this type
of linking is very limited, therefore I cannot make a good
comparison of this technique to the more conventional methods
provided by ALINK, BLINKER and WARPLINK.
SYMBOL-MANAGEMENT
Symbol Management is a technique that can greatly reduce the
amount of memory overhead in a linked application. Symbol
management is a process in which the "symbol table" is managed
to prevent unneccessary symbols in the main root memory area.
There is usually very little that a linker can do to resolve
this problem because the problem is usually caused by the
compiler and the programmer. Every compiled object contains
symbols, constants, code and data. Overlay linkers can usually
do a good job of overlaying code and constants but symbols and
data must be treated differently. Symbols must always be placed
in "root" memory for overlay managers to be able to find and load
the module which contains the called symbol. Unfortunately,
most linkers are not sophisticated enough to eliminate the
"redundancy" of symbols which are placed in root memory. For
example, each Clipper-compiled object makes a call to the
symbol "__PLANKTON". The symbol "__PLANKTON" is assigned a
place in the symbol table for EACH Clipper-compiled object even
though _PLANKTON exists at only one address. If you have
100 Clipper-compiled objects, you will have 100 redundant
entries in this table. This consumes value memory. This
problem can usually be overcome by compiling your .PRG files
into less (and larger) .OBJects, thereby reducing the symbol
count. This can become a delicate balancing act, however, when
trying to find the proper balance of .OBJ file size verses
symbol count to make a difference in memory usage. Increasing
the .OBJect size may increase the overlay area size thereby
nullifying the memory savings from the reduced symbols.
ALINK and BLINKER excel in the area of symbol management.
.EXEcutables created with these "dynamic-overlay" linkers are
very memory efficient, because they overlay code segments down
to the "procedure" level rather than the "module" level. This
means that you can now compile your large clipper application
into just a few huge .OBJect files, thereby greatly reducing
the number of symbols which are placed into "root" memory.
It is really this "symbol management" of ALINK and BLINKER
which make them perform well as memory-management linkers
as much as their overlaying techniques.
Page 11 - Copyright (c) DONNAY Software
NOLINK, dCLIP and dCLIPRUN also provide good symbol management
because they only create symbols when called for during the
running of the application. The symbols from a huge report
that is run once a week will waste valuable memory with other
linkers, where "dynamic-linking" will create these symbols only
at the time the report is being run.
This article is basically intended to provide "linking" tips
for memory-management, however, it is incumbent upon me to
also offer additional tips on reducing symbol-count in your
applications which will work with ALL linkers.
a. USE CONSTANTS INSTEAD OF MEMVARS
Clipper memory variables are always treated as "symbols".
Refrain from using a memory variable if a constant is sufficient.
For example, an unnecessary symbol can be eliminated by changing
the code:
escapekey=27
DO WHILE INKEY()#escapekey
*clipper code
ENDDO
to:
DO WHILE INKEY()#27
*clipper code
ENDDO
b. USE ARRAYS INSTEAD OF MEMVARS
Every different Clipper memvar name creates a "symbol", whereas
an array name creates only ONE symbol. The following example
shows how to save considerable memory in a clipper application
by reducing the symbol count with an array.
This code produces 5 symbols:
mname=name
maddress=address
mcity=city
mstate=state
mzip=zip
@ 1,1 SAY 'Name ' GET mname
@ 2,2 SAY 'Address' GET maddress
@ 3,3 SAY 'City' GET mcity
@ 4,4 SAY 'State' GET mstate
@ 5,5 SAY 'Zip' GET mzip
READ
REPL name WITH mname, address WITH maddress,;
city WITH mcity, state WITH mstate, zip WITH mzip
Page 12 - Copyright (c) DONNAY Software
This code produces 1 symbol:
PRIVATE gets[5]
gets[1]=name
gets[2]=address
gets[3]=city
gets[4]=state
gets[5]=zip
@ 1,1 SAY 'Name ' GET gets[1]
@ 2,2 SAY 'Address' GET gets[2]
@ 3,3 SAY 'City' GET gets[3]
@ 4,4 SAY 'State' GET gets[4]
@ 5,5 SAY 'Zip' GET gets[5]
READ
REPL name WITH gets[1], address WITH gets[2],;
city WITH gets[3], state WITH gets[4], zip WITH gets[5]
c. USE THE SAME NAME MEMVARS WHENEVER POSSIBLE
Again, every "different" Clipper memvar in a module creates
a symbol. If an object contains several procedures, use the
same name for memvars even though they may not perform the same
or similar functions. For example, procedure A and procedure B
both need 5 memvars. If procedure A declares its memvars with
5 unique names and procedure B declares its memvars with 5
unique names, then 10 symbols are used in the linked application.
To eliminate 5 symbols, make sure that procedure B assigns the
same name to the memvars as procedure A. This is not possible
of course, if the memvars need to be public to both procedures
and perform different functions, only if they are private. This
also may not be practical in all programming situations because
of the "cryptic" method in which you must treat your memvar
declarations. Clipper 5.0 solves this problem and also makes
it easier to do steps 1 and 2 above by including a language
"pre-processor" which allows you to program using non-cryptic
language extensions then convert your code at compile time to
memory-efficient use of arrays or constants.
MEMORY-PACKING
Both BLINKER and dCLIP provide an "automatically-called" and
"user-callable" function which helps to prevent the common memory
fragmentation caused by Clipper applications. Some of the
fragmentation is actually caused by the linkers themselves
because "dynamic-linking" creates unresolved symbols at runtime.
These symbols are placed in the Clipper free-pool or "heap" at
the most prudent location determined by the Clipper memory
management system. Once a symbol has been created, it will
occupy the same memory space forever, therefore it is desirable
that the symbols all be placed in adjacent memory locations
rather than "fragmenting" the free pool.
Page 13 - Copyright (c) DONNAY Software
"Memory packing" is a technique developed by Steve Steiner and
was introduced in his product SMARTMEM. This is a very simple
process in which unneccesary memory control boundaries are removed
thereby giving the Clipper application a large contiguous block
of memory to work with rather many small blocks placed end to end.
BLINKER calls its memory pack routine at user-definable intervals
each time an overlay is loaded. For example, the command BLINKER
MEMORY PACK 10 will insure that memory is packed every tenth
time an overlay is loaded. BLINKER's overlay pool is also
"flushed" at this time to insure that fragmented code segments
are also removed. dCLIP calls its memory-pack function "every"
time a module is loaded into memory and only "flushes" its overlay
pool when it cannot find sufficient space to load a new module.
MEMORY ALLOCATION
Some linkers provide for complete control of memory allocation
to help the programmer manage the runtime environment of the
application.
PLINK86 and RTLINK support a STACK command for allocating the
amount of memory reserved as the call stack. This is very
necessary in sophisticated applications which use windowing
schemes and nest calls many levels deep. These linkers also
support a MEMORY command which will define the heap memory to
allocate to the application in addition to the .EXE load module.
If this command is not used, then Clipper grabs all the free
dos memory. This command is useful to insure that Clipper uses
only the memory you want it to use. This memory control can
also be accomplished with the SET CLIPPER=<memory parameters>
in your dos environment, but burning it into the .EXE can some-
times be more useful.
BLINKER provides a very useful feature for burning the SET
CLIPPER environment into the .EXEcutable program including the
files parameter. For example, the command -
BLINKER EXECUTABLE CLIPPER V10;R32;F39 will eliminate the
need to use this command in your AUTOEXEC.BAT file. BLINKER,
dCLIP and WARPLINK also provide control of the overlay pool size
to optimize the object memory allocation.
dCLIP follows the same guidelines as any Clipper application
and allocates memory from the SET CLIPPER environment variable.
dCLIP also incorporates a "virtual-memory" technique to allow
calls to other .EXEcutable programs which are larger than the
available memory. This "virtual-memory" is any disk device,
expanded memory, or a network server. Memory is released from
the application and saved as a temporary file, then reallocated
to dos as new free memory for calling the other program. After
returning from the called program, the original memory condition
is restored from the temporary file.
Page 14 - Copyright (c) DONNAY Software
════════════════════════════════════════════════════════════════
Linking Tips for Productivity
════════════════════════════════════════════════════════════════
When using a compiler language such as Clipper, there is no way
to eliminate the EDIT-COMPILE-LINK cycle. This is a necessary
to produce machine-readable code. There are a variety of new
linking techniques, however, which reduce this cumbersome task
to an acceptable, manageable process.
In order to understand how to choose a linker for productivity
and project management, we must first examine the methods in which
linkers accomplish this task. They are as follows:
1. Pre-linked Libraries
2. Dynamic Linking
3. Incremental Linking
4. Speed-Linking
5. Library-Module Linking
6. Debugging
PRE-LINKED LIBRARIES
NOLINK introduced the concept of pre-linked libraries to the
Clipper community about 3 years ago. Shortly after that,
RTLINK introduced their .RTL (runtime-library) system for all
languages.
Pre-linked libraries are files which are built from object
and libraries into and .EXEcutable format. The only step
remaining is the "fixing-up" of any references made by the code
in the pre-linked library to those in the rest of the application.
Unlike an .EXEcutable program, a pre-linked library cannot be
run from dos, but instead is used in conjunction with another
.EXEcutable program.
RTLINK developed their .RTL (runtime-library) system with the
intent of saving disk-space for applications which use common
routines. For example, every Clipper application links in about
150k of code from the CLIPPER.LIB library into the .EXE program.
If you have 10 Clipper .EXE programs, then this code redundancy
will use up 1.5megs of disk space. RTLINK allows you to build
a .RTL file which pre-links this "common" code. The .RTL file
is then referenced when you create the .EXE program with all
the "unique" code. When you run your .EXE program the pre-
linked .RTL file will be "fixed-up" to the rest of your
application code each time you startup your program.
NOLINK, dCLIP, and dCLIPRUN use pre-link libraries for a dual
purpose - disk management and memory management. These linkers
provide linking from .DLB files (dynamic-libraries) at "runtime"
whereas RTLINK's .RTL system is simply a "load-time" linker.
Linkers which use "true-dynamic" pre-link libraries will only
link code into memory if it is called by the application that is
running. These systems will also "manage" the object pool to use
a small amount of memory space for large applications.
Page 15 - Copyright (c) DONNAY Software
DYNAMIC-LINKING
Dynamic-linking is also covered under the "Memory Management"
section because of its inherent memory-management capabilities.
Dynamic-linking is probably more useful however in its ability
to provide a "turbo-style" development system. All other linkers
require that you QUIT the program being executed to make changes
to ANY part of the code. Even the smallest change, such as
adding a "CLEAR" to clear the screen will require that you
(1) Quit to dos, (2) Edit your code, (3) Compile the code,
(4) Link the code and (5) Restart the application.
The NOLINK dynamic-linker eliminates step (4), the Link cycle,
because it links code into memory from your .OBJect files. For
most Clipper developers, just saving the Link step will double
the programmer's productivity if he/she is using a slow linker
like ALINK, PLINK86 or RTLINK.
The dCLIP development platform takes the "dynamic-link"
concept two steps further and also eliminates step (1) and step
(5) of the EDIT-COMPILE-LINK cycle. For many applications this
is also a great time savings because sometimes it takes a lot of
time to "restart" an application and get back into the desired
sub-menu to test the changes. Some sophisticated application
development tools such as ARTFUL.LIB must open as many as 25
files, build arrays, set relations, etc. before you can even
get into the desired menu. dCLIP helps during development of
these larger application systems by allowing the programmer to
(1) suspend execution of the program, (2) Call his/her editor,
(3) recompiles the changes, (4) automatically de-links the old
code and re-links the new codes into memory, (5) return to
the program. This process does not in any way change the
program "environment", only the executable portion of the code,
thereby saving even more time in getting back to the desired
menu to test the changes.
dCLIP does have a limitation when being used in this manner.
Let's say that procedure A calls procedure B. The programmer
hits the ALT-D hotkey while running procedure B to get to the
interactive dot prompt, then calls his editor and changes
something in procedure B. dCLIP will allow the editing and
recompiling of the changes, however the procedure B code cannot
be replaced in memory until the application returns back to
procedure A and then comes back into B. It is suggested that
if a change needs to be made to a procedure on the fly like
this, that the programmer go back one menu in the program
before hitting the ALT-D hot key.
Page 16 - Copyright (c) DONNAY Software
INCREMENTAL-LINKING
Incremental Linking is a process in which only the code which
is changed is linked into the new .EXEcutable program. RTLINK,
NOLINK, dCLIP and dCLIPRUN all support incremental linking
however, each uses a different concept.
RTLINK's concept of incremental linking is to create an
information file (.INF) which is generated containing a list
of each module in the program along with a checksum and time
stamp. It is with the use of this file that RTLINK is able
to tell what has changed in the program. RTLINK's incremental
linker has the disadvantage of causing the .EXEcutable program
to grow larger than usual because of wasted space in the output
file which is needed to allow for the growth of modules. A
certain amount of extra space (25% is the default) is needed.
This is not really a problem because incremental linking is
usually done during the development cycle. The final product
can be linked with NOINCREMENTAL to disable the feature and
bring the .EXE back down to normal size.
NOLINK's incremental linking system must work differently since
linking is normally done "on the fly" and is always activated.
When running an application under NOLINK and using dynamic-
libraries, each time a module is called and needs to be linked
into memory, the date and time of the module in the dynamic
library is checked against the date and time of the .OBJ file on
the disk. If there is NO .OBJ file, then the module from the
library is linked, if there is an .OBJ file with a later date
and time then it is linked instead of the module in the library.
dCLIP's incremental linking system uses essentially the same
technique as NOLINK, except the DCLIP.SYS file allows the
programmer to define the location of the .OBJect files so they
may exist on another drive in another directory or on the
network server. This makes project management simpler. dCLIP
also allows the programmer to put a memory variable in the start
of his/her program to disable the incremental link system,
eliminating the constant disk access and date/time comparisions
and link only from the libraries thereby improving the speed of
operation. This feature is usually implemented when using
dCLIPRUN rather than dCLIP.
SPEED LINKING
All Clipper programmers want the link part of the EDIT-COMPILE-
LINK cycle to go faster. The general rule of thumb for speed
of linking, is: "The more sophisticated the linker, the longer
the link-time". Overlay linkers such as PLINK86, PLINK86plus,
RTLINK and RTLINKplus usally are quite slow because they were
developed as "general-purpose" linkers for all languages and
must conform to the requirements of all compilers.
Page 17 - Copyright (c) DONNAY Software
Special-purpose linkers such as NOLINK, BLINKER, dCLIP and
ALINK were designed to be used with Clipper only therefore
they can eliminate many of the checks such as "static-
symbols", "checksums", etc. and concentrate on what is needed
only for Clipper applications.
The fastest linking method is, and will always be, true
"dynamic-linking" because only the code that is called by the
application at runtime is linked into memory. Linking from
.OBJect modules does take a slight longer time than from
pre-linked "dynamic-libraries" and dynamic-link systems often
cause a slight "hesitation" when a module is being linked into
memory. This "hesitation" can be milliseconds for small OBJects
(1k - 5k) up to up to 1-2 seconds for large objects (30k - 60k).
BLINKER is by far the fastest overlay linker which produces an
.EXEcutable program. Jud Cole claims that he will never write
in any language other than assembly-language. BLINKER will
usually produce an .EXE in about 1/5 the time of PLINK86 or
RTLINK.
TLINK 1.0 is even faster than BLINKER but is limited to
non-overlay applications. TLINK was really designed to be used
with the Borland compilers and is not a general-purpose linker
therefore it does not work with some Clipper applications which
use third-party libraries.
WARPLINK was so named because it is supposed to be a fast linker.
As general-purpose overlay linkers go, it is definately faster
than PLINK86 and RTLINK (about 50%), however is cannot compare
with BLINKER or TLINK for speed in linking Clipper applications.
LIBRARY-MODULE LINKING
One of the most useful features I have found in some linkers
is the "MODULE" command. When a linker does not support this
command or a library is improperly created to use this command
I get very aggravated because it means that my whole development
environment is impacted by these limitations. PLINK86 and
RTLINK are examples of linkers which have a level of sophisti-
cation to provide this command.
The developers of the new, younger linkers, such as ALINK,
BLINKER and WARPLINK have not yet matured to the level of wisdom
that comes from developing "sophisticated applications". If
their applications were as complicated as some of mine, they
would not have ignored this very useful feature in their
products.
The development team at Nantucket was also short-sighted when
they produced the CLIPPER.LIB and EXTEND.LIB libraries and this
also added to my frustration. Brian Russell, the author of
Clipper, assures me that this will not be a problem in Clipper
5.0.
Page 18 - Copyright (c) DONNAY Software
The MODULE command is very useful in that it allows overlay
linkers to place "modules" from libraries into overlays.
This is an "undocumented" feature in PLINK86 that very few
Clipper programmers know how to use and even when they find out
that PLINK86 supports the MODULE command, they can't use it with
the CLIPPER.LIB/EXTEND.LIB libraries.
When a compiler creates an .OBJect file it also assigns a
"module" name for the linker. The Clipper compiler assigns the
same name as the .OBJ file, however many compilers will assign
the name of the SOURCE file as the module name including
drive letters and directories. You can organize your Clipper
projects by placing all your Clipper objects in libraries
with a library manager such as LIB.EXE or PLIB86.EXE then by
using the SECTION MODULE <module> command in your link file
you can place any module into any overlay area.
Example:
LIB mylib
BEGINAREA
SECTION MODULE myfileA,myfileB
SECTION MODULE myfileC
SECTION MODULE myfileD
ENDAREA
It is not only incumbent upon linker developers to support
this option, but also developers of third-party libraries.
Their documentation should include not only the name of the
function but the name of the "module" which includes each
function so that module can be overlayed. Nantucket did not
realize the value of this feature of PLINK86 in their Summer 87
release, otherwise they would have given each module in
CLIPPER.LIB and EXTEND.LIB a "unique" name. Instead, they
assigned the same module name to many different objects -
_ASM.ASM. For example, if the DBEDIT module were named
"DBEDIT" instead of "_ASM.ASM" and the MEMOEDIT module were
named "MEMOEDIT" instead of "_ASM.ASM" then they could be
be overlayed with PLINK86 as follows:
LIB extend
BEGINAREA
SECTION MODULE dbedit
SECTION MODULE memoedit
ENDAREA
The MODULE <module> command in PLINK86 and RTLINK requires that
<module> exists in one of the declared libraries and that the
name is "unique" to that module otherwise the command will be
ignored and the module will be linked into the root memory area.
dCLIPFUN.EXE is a development platform for CLIPPER and FUNCKY
which includes every module from CLIPPER.LIB, EXTEND.LIB and
FUNCKY.LIB. To accomplish this task and still provide
sufficient memory for running Clipper applications we needed to
overlay much of the CLIPPER libraries and FUNCKY library.
Page 19 - Copyright (c) DONNAY Software
Here is how we did it:
1. First we extracted all the modules from CLIPPER.LIB and
EXTEND.LIB with PLIB86.EXE. This gave us a set of files
with the same name as the original objects which were used
to create these libraries.
2. Next we rebuilt CLIPPER.LIB and EXTEND.LIB with PLIB86.EXE
and told PLIB86.EXE to "MODRENAME" all modules. This PLIB86
command renamed all the modules from "_ASM.ASM" to the name
of the file on disk.
3. Next using the LIBRA.EXE library utility, we examined the
FUNCKY.LIB library and got the names of each Funcky module.
We were lucky because Dirk Lesko's compiler assigned unique
names to each of his modules.
4. Now all we had to do was create a link file:
STACK 1024
FI dclip,dclipf1,dclipf2,dclipf3,funcky
LIB dclipnl,dclip,dclipr,funcky,dcextend,clipper
OUTPUT dclipfun
RELOAD FAR 300
OVERLAY CODE
VERBOSE
BEGINAREA
# Modules from CLIPPER.LIB and EXTEND.LIB
SECTION MODULE memoedit,memotran
SECTION MODULE memoline,memoread,memowrit,mlcount,mlpos
SECTION MODULE achoice,ascan,adir,afields,asort,ains,acopy,
MODULE afill,gete
SECTION MODULE report
SECTION MODULE dbedit
SECTION MODULE icreate,sort,sortof,examplea,examplec,recsize
# Modules from DCLIPNL.LIB
SECTION MODULE c_call,global,parseobj,msg,kern,omalloc,mtbuf,
MODULE mtobj,screen
# Modules from DCLIP.LIB
SECTION MODULE overlay,over_22,over_24,over_6
ENDAREA
BEGINAREA
# Modules from CLIPPER.LIB and EXTEND.LIB
SECTION MODULE ntx
# Modules from DCLIP.LIB
SECTION MODULE dbgbrow,dbgio,dbgscrn,dcega43,dcvga50,videoid,dckey
SECTION MODULE _dcinit
Page 20 - Copyright (c) DONNAY Software
# Funcky modules
SECTION MODULE aaverage.c,amax.c,amaxn.c,amin.c,atotal.c,
beep.asm,border.asm,checkdat.asm,checktim.asm,clusters.asm,
coldboot.asm,cominit.asm,comoff.asm,comon.asm,comset.asm,
comswap.asm,cputype.asm,crash.asm,csrbot.asm,csrtop.asm,
curdir.asm,curdrive.asm,datetype.asm,decimals.asm,default.asm,
iszip.asm,delimete.asm,delvolum.asm,disksize.asm,diskspac.asm,
dosmem.asm,dosvers.c,drivestr.asm,egamem.asm,execute.asm,
expmem.asm,extmem.asm,ferase.asm,ferror.asm,fgetattr.asm,
fgetdate.asm,fgettime.asm,fhide.asm,filecoun.asm,findfirs.asm
SECTION MODULE flen.asm,fprotect.asm,fre.asm,frename.asm,
fsetattr.asm,fsetdate.asm,funhide.asm,funprote.asm,getmode.asm,
getpage.asm,getvolum.asm,handles.asm,initscre.asm,insert.asm,
iscom.asm,isdir.asm,isdisk.asm,isdrive.asm,isems.asm,
isfixed.asm,isfloppy.asm,ishandle.asm,islpt.asm,ismouse.asm,
isqueue.asm,kbdstat.asm,lastdriv.asm,lprint.asm,lptset.asm,
lptswap.asm,margin.asm,maxcol.asm,maxhandl.asm,mediatyp.asm,
mono.asm,mouse.asm,m_pen.asm,m_reset.asm,m_restor.asm,
SECTION MODULE m_save.asm,m_speed.asm,m_setpag.asm,
m_getpag.asm,ndptype.asm,nexthand.asm,nstuff.asm,palette.asm,
prnreset.asm,prnstatu.asm,program.asm,prtscr.asm,q_cancel.asm,
q_delete.asm,q_file.asm,q_restar.asm,q_status.asm,q_submit.asm,
removeab.asm,romdate.asm,sectors.asm,sectorsi.asm,setdrive.asm,
sethandl.asm,setlogic.asm,setmode.asm,setpage.asm,setsnow.asm,
setscree.asm,settime.asm,systype.asm,vidtype.asm,warmboot.asm,
prnhandl.asm,althandl.asm,setvolume.asm,q_hold.asm,
filesize.asm,drivetyp.asm,turbo.asm,typeahea.asm,chdir.asm
ENDAREA
DEBUGGING
Linkers are becoming much more sophisticated in their ability
to provide debugging information while running an application.
Most often, the ability of the linker to provide adequate
debugging information is dependent on the information the
compiler provides to the linker in the object code. Some
linkers are very sophisticated in being able to provide
debugging at the symbol-level even though the compiler does
not provide for this. Microsoft's LINK.EXE and PocketSoft's
RTLINKplus are the only linkers that support Microsoft
CODE-VIEW for getting into a Clipper application and finding out
what is happening at the low levels. RTLINKplus is the only
"overlay" linker with this feature.
Most linkers provide a "DEBUG" command. This is not a very
sophisticated debugging feature and is usually supported in a
manner that is aggravating to the person trying to debug. The
DEBUG command in PLINK86 and RTLINK will force the overlay
manager to report to the screen each time an overlay segment is
being accessed. Sometimes it is necessary to use this command
to figure out overlay strategies. The annoying thing is that
both PLINK86 and RTLINK simply put the message on the screen at
line 24 and then scroll the screen up one line. If you are
trying to debug a program which puts information on the screen
this can be very aggravating. Also, once the DEBUG switch is
ON, you can't turn it OFF without relinking the application.
Page 21 - Copyright (c) DONNAY Software
NOLINK provides a feature that allows the programmers to see
a "snapshot" of the object overlay pool at any time while
running the program. This provides useful information by
showing the operator which modules are currently in memory,
which modules have been linked from .OBJ files and which
have been linked from .DLBs (dynamic-libraries), which modules
are currently "running" and the size, date and time of each
module.
dCLIP provides the same feature as NOLINK but also offers a
TRACE feature which writes debug information to a DCTRACE file
with the procedure name, line number and the current value of
any expression loaded into the "WATCH" table. This DCTRACE
file can then be "merged" with your source code to give you
a very useful "histogram" of your application. dCLIP also
provides a "source-level" debugger and an "interactive, dot-
prompt style" debugger which use nearly the entire Clipper-
language as a debugging tool. Since the Clipper libraries
are linked into the dCLIP engine, every Clipper function may
be used to help debug a Clipper application. This kind of
debug system lets you select work areas, open and close data
files, create memvars and arrays, browse files, jump to dos,
change your environment, load other libraries, etc.
BLINKER provides a "PROFILING MODE" which is really a User-
defined function. This feature is basically a set of "hooks"
for the Clipper programmer to write his/her own debug system
to determine the activity of the overlay manager for optimizing
the performance of the application.
Page 22 - Copyright (c) DONNAY Software
════════════════════════════════════════════════════════════════
PRODUCT COMPARISONS
════════════════════════════════════════════════════════════════
PLINK86s87
Current Version - Clipper Summer 87
List Price - Supplied with Clipper Summer 87
PLINK86s87 is the linker provided with Clipper and is
compatible with all Clipper-compiled objects, Clipper-compiled
libraries, the Clipper libraries, and all third-party libraries.
PLINK86 is a "static overlay" linker and requires careful
overlay design.
PLINK86s87 supports overlaying of "MODULES" from libraries to
allow you to take simplify your development environment and
work from libraries rather than .OBJ files.
PLINK86s87 is a mature, reliable linker which is sophisticated
enough to handle linking of most large Clipper applications which
requires overlays, provided that you are patient enough to
analyze your code and structure your overlays properly.
PLINK86plus
Current Version - 2.22
List Price - $295.00
PLINK86plus is a generic, general-purpose version of PLINK86 and
includes extra features such as a "RELOAD" command to support
"overlay reloading". It's "reloadable" overlay feature is
limited however to C/ASM object files and library modules. All
of the modules in CLIPPER.LIB, EXTEND.LIB and most third-party
libraries are reloadable because they were written in C/ASM.
All Clipper-compiled modules must be placed in "static-overlays"
in the same manner as PLINK86s87.
PLINK86plus also includes an overlay design utility which scans
your application objects and helps you develop an overlay
strategy which will prevent lockup at runtime and design the
most memory-efficient architecture. Caution - this type of
utility is not very useful in applications which call programs
through indirect symbol references such as "macros" because
they have no way of knowing that a call has been made until the
programming is actually running.
Page 23 - Copyright (c) DONNAY Software
RTLINK
Current Version - 3.1
List Price - $295.00
RTLINK.EXE is a general-purpose MS-DOS linker for all compiler
languages, assembly languages, and Clipper. RTLINK is compatible
with the Clipper libraries, Clipper-compiled objects and all
third-party libraries. RTLINK is is also compatible with all
PLINK86 commands and will link your applications from your
existing PLINK86 *.LNK files.
RTLINK is both a "static" overlay linker and a "reloadable"
overlay linker. It's "reloadable" overlay feature is limited
however to C/ASM object files and library modules. All of the
modules in CLIPPER.LIB, EXTEND.LIB and most third-party n
libraries are reloadable because they were written in C/ASM.
All Clipper-compiled modules must be placed in "static-overlays"
in the same manner as PLINK86.
RTLINK also allows use of .RTLs (runtime libraries) to help
reduce disk space usage of applications. RTLINK is a mature,
reliable linker which is sophisticated enough to handle linking
of any large application which requires overlays.
RTLINK has a "VIRTUAL OVERLAY" feature which provides the added
feature of including the DATA portion of object modules into
overlay segments, by writing the data to a "virtual overlay"
on disk and restoring the data whenever the overlayed code is
reloaded into memory.
RTLINK supports overlaying of "MODULES" from libraries to
allow you to take simplify your development environment and
work from libraries rather than .OBJ files.
RTLINK is an excellent linker for all applications, but
particularly for applications which are C/ASM code intensive
and NOT Clipper-code intensive.
RTLINKplus
RTLINKplus is an even more sophisticated version of RTLINK which
offer much more power in the area of debugging tools. RTLINKplus
includes MicroSoft CODE-VIEW support, a sophisticated runtime
PROFILER, and an overlay analyzing system which scans .MAP files
and produces graphs of overlay usage to help determine the
efficiency of your overlay structures.
Page 24 - Copyright (c) DONNAY Software
RTLINK-5.0
RTLINK-5.0 is a custom version of RTLINK which supports all the
basic features of RTLINK but with two important new features:
1. Automatic Clipper-code overlaying - this feature uses a
"dynamic-overlaying" technique which automatically manages
Clipper-code overlays in an overlay pool at runtime.
2. Incremental linking - this feature provides a faster link
cycle than normal linking by maintaining a work file which
is a history of past linking sessions. This work file is
then used to insure that only the code "changed" since the
last link session is linked into the new executable.
ALINK
Current Version - 1.08
List Price - $179.00
ALINK.EXE is a linker specially designed for Clipper
applications. ALINK is compatible with the Clipper libraries
and all third-party libraries. ALINK is also compatible with
many PLINK86 commands and will link your applications from your
existing PLINK86 *.LNK files with some modifications.
ALINK is a "dynamic overlay" linker which provides dynamic
overlays for Clipper-compiled object files only. ALINK will
NOT overlay from .LIBrary files therefore all functions from
.LIB files will be linked into the ROOT memory area.
ALINK is the only linker which is NOT a stand-alone linking
system. It is instead an overlay "pre-processor" which
extracts all the code segments from the Clipper-compiled objects
down to the function or procedure level, creates an .OVL file
of Clipper-executable code, then creates a set of .SYM (symbol)
files which are used by PLINK86 or Microsoft LINK to complete
the symbol "fix-ups" and generate the .EXEcutable program.
ALINK also includes a replacement for OVERLAY.LIB which is the
"dynamic overlay" manager. This manager is linked into the
.EXEcutable programs and manages the dynamic overlaying of all
the Clipper code. ALINK uses the Clipper free pool to link its
executable code segments, therefore it is recommended that you
use a memory-packing utility and call the AL_FLUSH() function
regularly in your ALINK-ed programs to reduce memory fragmentation.
ALINK is an excellent linker for applications which are
Clipper-code intensive. If you use many functions from third-
party libraries, then ALINK will not allow these to be
overlayed.
Page 25 - Copyright (c) DONNAY Software
BLINKER
Current Version - 1.1
List Price - $179.00
BLINKER.EXE is a linker specially designed for Clipper
applications.
BLINKER is compatible with the Clipper libraries, and all third-
party libraries. BLINKER is also compatible with many PLINK86
commands and will link your applications from your existing
PLINK86 *.LNK files with some modifications.
Like ALINK, BLINKER is a "dynamic overlay" linker which provides
dynamic overlays for Clipper-compiled objects and "some" C/ASM
objects. BLINKER will allow overlaying of entire libraries
with the "ALLOCATE" command. This is not always a useful feature
because very few libraries have modules which are ALL compatible
with BLINKER. BLINKER requires that C/ASM modules be "well-
behaved". It is not completely clear at this time what "well-
behaved" means, however, some libraries appear to fall into this
category. The EXTEND.LIB library is an example of a well-behaved
library, therefore, it may be ALLOCATEd in an overlay section.
BLINKER's dynamic overlay manager works excellently with
Clipper-compiled code and the EXTEND.LIB library. Once you
start experimenting with other libraries, you may find that it
is not worth the effort to go any further. Some third-party
library developers such as FUNCKY, FLIPPER, etc. have released
special versions of their libraries which are overlayable.
BLINKER's "well-behaved" disclaimer in their manual is more
of an indictment of BLINKER's behavior, not the third-party
products behavior. As of the writing of this article, BLINKER's
"dynamic-overlay" manager has experienced problems with modules
which are compiled using "optimization" and also with modules
which use STATIC symbols. These are valid compiler features
and it is incumbent upon the developer's of BLINKER to support
this capability in their linker rather than expect all the
third-party developers to change their products. Jud Cole
has assured me that he intends to upgrade BLINKER to handle
the level of sophistication which is necessary to be able to
use BLINKER on more complicated projects. Until then, I can
recommend BLINKER only for projects which are Clipper-code
intensive. Be careful when trying to overlay third-party
libraries.
Even with these limitations, BLINKER provides the best memory
management solution for Clipper-code intensive .EXEcutable
applications. BLINKER is not a simple linker. It also imbeds
functions into the linked program which are called between
loading of overlay segments for "memory-packing" to help reduce
the memory fragmentation caused by "dynamic-overlaying". This may
conflict with any memory-management system you may have built into
your application and should be taken into consideration.
Page 26 - Copyright (c) DONNAY Software
BLINKER evolved from ALINK's technology therefore it accomplishes
its "dynamic-overlaying" in much the same manner, however it is
a stand-alone linker and is 5 to 10 times faster than ALINK in
producing an executable program.
WARPLINK
Current version - 1.03b
List Price - $149.95
WARPLINK is a general-purpose linker designed for "dynamic-
overlay" applications.
WARPLINK is compatible with the Clipper libraries, and all
third-party libraries. WARPLINK is NOT compatible with PLINK86
commands and will NOT link your applications from your existing
PLINK86 *.LNK files.
WARPLINK is a "dynamic overlay" linker which provides dynamic
overlays for Clipper-compiled objects and "some" C/ASM objects.
WARPLINK will allow overlaying of called modules from complete
libraries by including the library name in (parenthesis).
Like BLINKER, WARPLINK requires that C/ASM modules be "well-
behaved". Because WARPLINK is a general-purpose linker it is
more compatible with third-party libraries than BLINKER,
however it does not produce as memory-efficient executables
as BLINKER if the application is Clipper-intensive. There are
applications, however, where WARPLINK will create better memory
models than BLINKER due to its ability to overlay code not
manageable by BLINKER and other situations where WARPLINK will
create better speed performance than RTLINK because its
"overlay-pool" technique is more efficient than RTLINK's disk-
intensive "overlay-reloading". WARPLINK "learns" how to manage
the pool most efficiently while the application is running.
WARPLINK can overlay entire libraries but is NOT capable of
overlaying "MODULES" like PLINK86 and RTLINK.
WARPLINK is an excellent linker for all applications. What
it lacks in features, it more than makes up for in performance.
NOLINK
Current Version - 2.1
List Price - $89.00
NOLINK is a true "dynamic-linker" which does NOT produce an
executable file but instead is an "executable-kernel" which
contains the CLIPPER.LIB/EXTEND.LIB libraries and runs Clipper
applications from .OBJ files and/or dynamic libraries.
Page 27 - Copyright (c) DONNAY Software
Like ALINK, NOLINK's dynamic link system is compatible with
Clipper-compiled code only and was designed to help develop
and test Clipper modules by eliminating the normal link cycle
that is required when producing .EXEcutable programs. NOLINK
only links objects into memory when they are "called" by the
application that is running. NOLINK's dynamic-link system is
by far the fastest linking technique of all link systems
because the symbol "fixups" occur at runtime and only when they
are needed by the application.
NOLINK's .EXE program is built from the Clipper libraries and
the NOLINK "Kernel Builder" library and is somewhat of a memory
hog. NOLINK is an excellent product for testing small portions
of Clipper programs or Clipper UDF's, but it can easily run out
of memory on large Clipper projects. NOLINK's standard .EXE
program is limited to virgin Clipper applications and is not
compatible with third-party libraries. It is recommended that
you use NOLINK's Kernel Builder to create a custom kernel for
your more sophisticated applications.
NOLINK - Kernel Builder
Current Version - 2.1
List Price - $89.00
The NOLINK Kernel Builder is a LIBRARY which allows the
programmer to build a custom "dynamic-link" kernel which also
includes compatibility with third-party libraries. Kernel
Builder's Library is used with another "overlay-linker" to
create the kernel. By using overlay segments, I have been
successful in creating complete NOLINK kernels in as small
as 200k with RTLINK and 230k with PLINK86.
dCLIP/dCLIPRUN
Current Version -2.50
List Price - $295.00
dCLIP is a complete development platform for Clipper
applications and uses "dynamic-linking" to run clipper .OBJ
files or dynamic libraries. dCLIPRUN has a 40k lower memory
overhead than dCLIP because the DOT prompt and debugging tools
have been removed. Both the dCLIP.EXE and dCLIPRUN.EXE
"engines" are included in the dCLIP package and a set of
.LIBraries are also included to allow the programmer to create
custom engines or use dCLIP features in his/her applications.
dCLIP also includes a royalty-free dCLIPRUN distribution license
to allow the developer to distribute the dCLIPRUN.EXE runtime
engine or "custom" runtime engines for running Clipper
applications from .OBJects and/or .DLBs.
Page 28 - Copyright (c) DONNAY Software
dCLIP's technology uses functions from the NOLINK library to
perform it's "dynamic-linking", but other than that, there is
absolutely no resemblance to NOLINK. dCLIP is much more
sophisiticated than NOLINK in its dBASE/FoxBASE-style user-
interface, memory management and debugging tools. dCLIP also
performs much better in network environments and includes complete
documentation for integrating with all other third-party products.
dCLIP is the only linking product that is a "runtime" system
rather than producing an .EXEcutable program. dCLIP's .EXE
can be customized by re-creating it from the dCLIP libraries,
therefore dCLIP provides the advantage of using any other
linking technology in conjunction with their "dynamic-linking"
system. This means that a dCLIP.EXE engine built with RTLINK
will support all the features of RTLINK .and. all the features
of dCLIP.
For many Clipper applications, distribution of an .EXEcutable
program is the most efficient and beneficial. dCLIP's runtime
system was designed to solve the distribution problems which can't
be managed very well in .EXE programs:
1. Alpha/Beta testing projects under development
Because dCLIPRUN executes the .OBJect files or dynamic
libraries, daily updates to offsite testers can be distributed
much more quickly and efficiently. Sending a few .OBJects
is quicker and easier than sending large .EXEcutables each
time changes are made.
2. Configuration control and customization.
dCLIPRUN offers a more efficient method of distributing
applications which require constant configuration or custom
changes. Custom configuration of a screen or report would
normally require rebuilding the .EXEcutable program. With
dCLIPRUN's "incremental linking" capability, a custom change
can be accomplished at the customer's site, compiled into
an object and ready to run.
3. Memory management for large applications.
Some applications cannot be linked into an .EXEcutable program
with any "overlay" linker because of the large number of
symbols which must always go into the "root" memory. For
example, Champion accounting distributes their system in 10
.EXEcutable programs. dCLIPRUN will run Champion's entire
accounting package as though it were one integrated system
by running the .OBJect files or dynamic-libraries. This also
provides the advantage of reducing the distribution from 10
diskettes to 4.
Page 29 - Copyright (c) DONNAY Software
Linker Comparison Chart - Memory Management Features
┌──────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ Linker │Dynamic │Dynamic │ Static │ Static │ True │Overlay │Memory │
│ │Overlays│Overlays│Overlays│Overlays│Dynamic │Reload │Packing │
│ │CLIPPER │ C/ASM │CLIPPER │ C/ASM │Linking │ C/ASM │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86+ │ NO │ NO │ YES │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86s87│ NO │ NO │ YES │ YES │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK │ NO │ NO │ YES *4 │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK-5.0│ YES │ NO │ NO │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK+ │ NO │ NO │ YES *4 │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│MS LINK │ NO │ NO │ NO │ NO │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│ALINK │ YES │ NO │ NO │ NO │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│BLINKER │ YES │ YES *2 │ NO │ NO │ NO │ NO │ YES │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│WARPLINK │ YES │ YES *2 │ NO │ NO │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│TLINK │ NO │ NO │ NO │ NO │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK │ YES │ NO │ YES *1 │ YES *1 │ YES │ YES *1 │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK-KB │ YES │ NO │ YES *1 │ YES *1 │ YES │ YES *1 │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIPRUN │ YES │ NO │ YES *1 │ YES *1 │ YES │ YES *1 │ YES │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIP │ YES │ NO │ YES *1 │ YES *1 │ YES │ YES *1 │ YES │
└──────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
Page 30 - Copyright (c) DONNAY Software
Linker Comparison Chart - Memory Management Features (cont.)
┌──────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ Linker │Virtual │Virtual │ Symbol │ Memory │Virtual │ │ │
│ │Overlays│Overlays│ Re- │ Alloc- │Memory │ │ │
│ │CLIPPER │ C/ASM │ duction│ ation │Swapping│ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86+ │ NO │ NO │ NO │ YES │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86s87│ NO │ NO │ NO │ YES │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK │ YES │ YES │ NO │ YES │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK-5.0│ YES │ YES │ YES │ YES │ YES │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK+ │ YES │ YES │ NO │ YES │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│MS LINK │ NO │ NO │ NO │ NO │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│ALINK │ NO │ NO │ YES │ NO │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│BLINKER │ NO │ NO │ YES │ YES *4 │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│WARPLINK │ NO │ NO │ NO │ NO │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│TLINK │ NO │ NO │ NO │ NO │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK │ NO │ NO │ YES │ YES *5 │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK-KB │ NO │ NO │ YES │ YES *5 │ NO │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIPRUN │ NO │ NO │ YES │ YES *5 │ YES │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIP │ NO │ NO │ YES │ YES *5 │ YES │ │ │
└──────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
Page 31 - Copyright (c) DONNAY Software
Linker Comparison Chart - Productivity Features
┌──────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ Linker │Incre- │Overlay │Overlay │Overlay │Pre- │Overlay │Source- │
│ │mental │complete│ lib │ .OBJ │Linked │de- │level de│
│ │Linking │ .LIBs │MODULES │ files │libs │bugging │-bugging│
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86+ │ NO │ NO │ YES │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86s87│ NO │ NO │ YES │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK │ NO │ NO │ YES │ YES │ YES │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK-5.0│ YES │ YES │ YES │ YES │ YES │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK+ │ NO │ NO │ YES │ YES │ YES │ YES │ YES │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│MS LINK │ NO │ NO │ NO │ NO │ NO │ NO │ YES │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│ALINK │ NO │ NO │ NO │ NO │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│BLINKER │ NO │ YES │ NO │ YES │ NO │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│WARPLINK │ NO │ YES │ NO │ YES │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│TLINK │ NO │ NO │ NO │ NO │ NO │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK │ YES │ YES │ YES │ YES │ YES │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK-KB │ YES │ YES │ YES │ YES │ YES │ YES │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIPRUN │ YES │ YES │ YES │ YES │ YES │ NO │ NO │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIP │ YES │ YES │ YES │ YES │ YES │ YES │ YES │
└──────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
Page 32 - Copyright (c) DONNAY Software
Linker Comparison Chart - Productivity Features (cont.)
┌──────────┬────────┬────────┬────────┬────────┬────────┬────────┬────────┐
│ Linker │ Link │ True │ │ │ │ │ │
│ │ Speed │Dynamic │ │ │ │ │ │
│ │ │Linking │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86+ │ Slow │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│PLINK86s87│ Slow │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK │ Slow │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK-5.0│Fast *6 │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│RTLINK+ │ Slow │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│MS LINK │ Medium │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│ALINK │ Slow │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│BLINKER │V. Fast │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│WARPLINK │ Fast │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│TLINK │V. Fast │ NO │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK │V. Fast │ YES │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│NOLINK-KB │V. Fast │ YES │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIPRUN │V. Fast │ YES │ │ │ │ │ │
├──────────┼────────┼────────┼────────┼────────┼────────┼────────┼────────┤
│DCLIP │V. Fast │ YES │ │ │ │ │ │
└──────────┴────────┴────────┴────────┴────────┴────────┴────────┴────────┘
Page 33 - Copyright (c) DONNAY Software
NOTES:
1. dCLIP, dCLIPRUN and NOLINK are "runtime" systems rather than
linkers which produce an .EXEcutable program. dCLIP's .EXE
can be customized by re-creating it from the dCLIP libraries,
therefore dCLIP provides the advantage of using any other
linking technology in conjunction with their "dynamic-linking"
system. This means that a dCLIP.EXE engine built with RTLINK
will support all the features of RTLINK .AND. all the features
of dCLIP.
2. Dynamic overlaying of C/ASM code is tricky and can cause
undesirable results when the code includes data or interrupts.
3. RTLINK seems to have occasional problems with Clipper-code
static overlays when the modules pass parameters.
4. BLINKER allows the SET CLIPPER=<environment> to be burned
into the .EXEcutable program.
5. dCLIP, dCLIPRUN use the SET CLIPPER=<environment> for free
pool memory allocation and the OBJMemory=<memory> in DCLIP.SYS
for object pool allocation.
6. If using Incremental Linking option then speed is improved
dramatically.
Page 34 - Copyright (c) DONNAY Software
════════════════════════════════════════════════════════════════
Choosing a Linker for your Clipper Projects
════════════════════════════════════════════════════════════════
Selecting a linker to use for a Clipper application is not
always an easy task. There are many factors which must be
considered before deciding which is the very best possible
solution. Then again, it may not be necessary to always choose
the best linker, but simply a linker which is adequate and will
solve the problem with the least effort.
To help you decide, I have chosen to use 6 real case studies,
in which our staff had to make a choice of a linker or linkers
for our different Clipper projects.
Case Study #1: FYI - Work Smarter (ALINK and BLINKER)
FYI - Work Smarter is a Clipper application that is almost
entirely written in Clipper with a few functions from
several third-party libraries (GET-IT, Overlay(), SMARTMEM, IDL).
When development started on Work Smarter, about 1-1/2 years ago,
the product was linked using PLINK86 and 4 "static overlay"
areas. As the product evolved, memory usage went up. No
matter how we managed the overlays, the symbol table grew to
the point where we had to use a new linker to get more memory.
We purchased ALINK, a "dynamic-overlay" linker and with only
a few hours effort reduced the memory overhead by 50k.
ALINK dynamically overlays ONLY Clipper-compiled .OBJ files.
This was not a problem for us since this project was "Clipper-
code" intensive.
With a little more effort and by compiling our application into
larger and less .OBJects we reduced the symbol count further and
were successful in reducing the memory overhead an additional
30k. A total investment of about 24 hours of time and $179.00
reduced our .EXE load module from 340k to 260k. ALINK likes
to fragment the Clipper memory pool and we were getting OUT OF
MEMORY during re-indexing, so we invested in a product named
SMARTMEM and made structured calls to the H_PACK() function
which packs the free pool.
As FYI - Work Smarter evolved, it grew more powerful and larger.
The .EXE load module increased another 10k over several months
and we were running into memory problems again because now
the program was designed to work with a 90k resident TSR.
Enter BLINKER, (designed by Jud Cole, the author of ALINK).
BLINKER uses the same basic overlaying concept as ALINK,
however it offers the ability to also dynamically overlay the
EXTEND.LIB library. This brought the .EXE load module down
from 270k to 230k.
Page 35 - Copyright (c) DONNAY Software
Our BLINKER link file:
FILE hoa,swapattr,resident
OUTPUT fyi.EXE
BLINKER MEMORY PACK 10
BLINKER OVERLAY OPSIZE 50
BLINKER EXECUTABLE CLIPPER V10;R32;F39
SECTION INTO fyi.OVL
BEGINAREA
FILE errorsys
FILE hoaovl1.OBJ
FILE hoaovl2.OBJ
FILE hoaovl3.OBJ
FILE hoaovl4.OBJ
FILE hoaovl5.OBJ
FILE hoaovl6.OBH
ALLOCATE overcl.LIB
ALLOCATE dclip.LIB
ALLOCATE extend.LIB
ENDAREA
LIB dclipr,getit,smartmem,clipper,idl
Case Study #2: FYI - LetterWriter (.RTLINK and .RTLINKplus)
FYI - LetterWriter is a Clipper application which is a data-
merging word-processor, spell-checker and thesaurus. FYI -
LetterWriter is approximately 30% Clipper-compiled code and 70%
C/ASM code. When this project started, about 1 year ago, it was
linked using PLINK86 and 5 "static overlay" areas. After
many "crashes" we determined that this application was far too
sophisticated to be managed with "static overlays", so we
purchased .RTLINK, reduced our overlay areas from 5 to 3, and
completely eliminated computer lock-up problems while reducing
the .EXE load module by 50k.
The Clipper-code portion of the program was still overlayed
"static" so we had to be careful to structure the Clipper-code
segments properly to prevent lockup, however the C/ASM code was
all automatically reloaded simply by entering the command:
"RELOAD FAR 300" in our link file.
We tried using dynamic-overlay linkers like BLINKER and
WARPLINK for this project, but they could not dynamically
overlay the sophisticated C/ASM routines we used in the spell
checker and thesaurus. During development we use RTLINK+
because it supports Microsoft Code-View, then we link the
final product with RTLINK 3.1.
Our link file:
Sorry, but this is information is proprietary
Page 36 - Copyright (c) DONNAY Software
Case Study #3: dCLIP/dCLIPRUN (.RTLINK and NOLINK 2.1)
dCLIP is a development platform and runtime system for Clipper
which runs Clipper applications from .OBJect files or dynamic
libraries. dCLIP is basically a Clipper application, however,
the dCLIP.EXE program contains about 5% Clipper-compiled code
and 95% C/ASM code. The dCLIP dot-prompt interpreter, debug
system, database manager, report writer, query-builder, etc.
are all written in Clipper, yet none of this Clipper-code is
included in the DCLIP.EXE program, but instead is included in
a "dynamic-library" which is linked into memory only as the
functions are needed.
dCLIP and dCLIPRUN are an example of 2 linking technologies
working together to produce the very best memory management
solution. NOLINK is a "dynamic link" library which is linked
into the dCLIP.EXE "engine" using .RTLINK. The engine also
includes the entire CLIPPER.LIB and EXTEND.LIB libraries and
makes provisions for including any third-party libraries.
When dCLIP development started 2 years ago, we used PLINK86
and NOLINK version 1.2. Our dCLIP.EXE engine load module
size was approximately 310k. This left very little room for
the Clipper application so dCLIP version 1.0 could handle
only small Clipper programs or it would run out of memory.
Like ALINK and BLINKER, the NOLINK-1.2 "dynamic linker" used
the Clipper free pool to link the Clipper-compiled code. This
caused memory fragmentation and eventually the program would
run out of memory.
dCLIP 2.0 used a whole new approach to the problem of overlay
linking. First, we threw away "static overlays" and found that
we could extract modules from the CLIPPER.LIB and EXTEND.LIB
libraries and overlay them using .RTLINK and the "MODULE"
command. The Clipper libraries are all C/ASM code, so we use
the "RELOAD FAR 200" command to insure that the overlayed
segments get properly reloaded. RTLINK allowed us to overlay
the "dynamic-link" functions from the new NOLINK-2.1 library as
well, so now our DCLIP.EXE load module was reduced from the
original 310k to only 230k. With this additional 80k memory
overhead, rewriting the "dynamic-linker" to allocate a seperate
object pool and including a "memory-packing" utility for memory
defragmentation, we improved dCLIP to now be capable of running
any large Clipper application without running out of memory.
Page 37 - Copyright (c) DONNAY Software
Our link file:
STACK 1024
FI dclip.OBJ
LIB dclipnl,dclip,dclipr,dcextend,clipper
OUTPUT dclip.EXE
RELOAD FAR 200
OVERLAY CODE
VERBOSE
BEGINAREA
#modules from DCEXTEND.LIB
SECTION MODULE memoedit,memotran
SECTION MODULE memoline,memoread,memowrit,mlcount,mlpos
SECTION MODULE achoice,ascan,adir,afields,asort,ains,acopy
MODULE afill,gete
SECTION MODULE report
SECTION MODULE dbedit
SECTION MODULE icreate,sort,sortof,examplea,examplec,recsize
#modules from DCLIPNL.LIB
SECTION MODULE c_call,global,parseobj,msg,kern,omalloc,mtbuf
MODULE mtobj,screen
#modules from DCLIP.LIB
SECTION MODULE overlay,over_6,over_22,over_24
ENDAREA
BEGINAREA
#modules from DCEXTEND.LIB
SECTION MODULE ntx
#modules from DCLIP.LIB
SECTION MODULE dbgbrow,dbgio,dbgscrn,dcega43,dcvga50,videoid,dckey
SECTION MODULE txtstuff
SECTION MODULE _dcinit
ENDAREA
Page 38 - Copyright (c) DONNAY Software
Case Study #4: dCLIPFLP.EXE -Flipper engine
(WARPLINK and dCLIP 2.5)
dCLIPFLP is a development platform and runtime system for
Clipper applications which use the FLIPPER graphics library.
WARPLINK was the best choice for this application for reasons
of speed performance more than memory performance. RTLINK
actually performed better from a memory-management point of
view, however, the constant "reloading" of overlay segments
proved to be too "disk-intensive" and very slow. WARPLINK's
link "pool" management scheme produces better speed performance
because it keeps routines which are called most often in memory.
WARPLINK is an example of a "dynamic-overlay" linker which
has limitations on the modules which can be overlayed. It is
very unclear how to determine which modules CAN be overlayed
other than by constant trial and error. The link file below
was developed after much of this trial and error. Objects and
libraries which are to be overlayed are placed in ()
parenthesis. Gary Prothero, the developer of Flipper is
currently working on breaking his libraries out into sub-
libraries which will allow all the (OVERLAYABLE) code to be
overlayed as a .LIBrary rather than many .OBJects. This, of
course, makes project management simpler.
/r /op:62 /em (dclipflp) + ovlmgr
# flipper objects
(ARC + AREASET + ASCIISET + AT_SET + AXISCALC + AXISSET) +
(BEE_BOP + CALLBIOS + CLIPSET + CLS + COLOR + COLORSET) +
(COM + CWAIT + DR_CURVE + EGA_HERC + ERRORSET + FALIGN) +
(FASTFILL + FASTLINE + FILLBOX + FIND_PEL + FLIPINIT + GETFHGT) +
(GETLNATT + GETLNLEN + GET_FATT) + GET_PEL + (GET_PT + GFXCLOSE) +
(GFXLSEEK + GFXOPEN + GFX_RDWR + GRAPHIC + GRAPHICS + HP_CLIP) +
(HP_PLOTS + INITSET LABELSET + LEGEND + LINE) +
(LINES + LN_JUST + LO_PRINT + MALOCPIC + MATHSET + MISS_SET) +
(MODESET + OPEN_FNT + PIC_ASM + PIECHART + PIE_CLIP + PRINT) +
(PSET + REGRESS + RESET + RETXYSET + ROTFCN) +
(ROT_180 + ROT_270 + ROT_90 + SAVEFONT + SAYMARK + SCALESET) +
(SCANKEY + SCL_DRAW + SCREEN + SET_XOR + TEXT + WORLDSET) +
(WRTCHAR + XAXISSET + XYSET + YAXISSET + _IDIV + _LINES)
# output file name
dclipflp
# map file name
dclipflp
# libraries
dclipnl+(dclip)+(dcextend)+dclipr+clipper+flip88
Page 39 - Copyright (c) DONNAY Software
Case Study #5: DONNAY Accounting System
(dCLIPRUN - dynamic linker)
Our DONNAY Software Accounting system is written entirely in
Clipper and handles Sales Orders, Customers, Accounts Receivable,
Accounts Payable, Inventory Control, General Ledger and reports.
Is also uses the entire SOFT.CLIP library, and has a gateway
system to call other programs such as FYI - Work Smarter.
This program was originally written in dBASE-II and has evolved
into a large, custom program which is about 1.5Meg of executable
code. Until 1 year ago, this system consisted of several
.EXEcutable sub-programs. Our accounting department was always
frustrated because we were reluctant to provide needed changes
due to the complexity of the system. Each one was linked with
PLINK86 and had a sophisticated internal overlay structure.
Finally we decided to solve this problem by converting the
program into several "dynamic-libraries" and then running it
entirely under the dCLIPRUN "dynamic-link" system. The conversion
took about 2 hours because all that was needed was to take all
the Clipper objects and "pre-link" them into sets of .DLB
(dynamic-library) files. Now, providing simple changes is easy
because we simply edit and compile the desired .PRG and distribute
the new .OBJect file. dCLIPRUN's incremental link system insures
that the new object is executed rather than the old one in the
dynamic library. About every two weeks we update the dynamic
libraries and distribute them.
ABOUT THE AUTHOR
Roger Donnay is the President and founder of DONNAY Software
Designs, a Newport Beach, California firm which specializes
in the development of database systems for microcomputers.
Roger is the creater of the SOFT.CLIP and TIME-TRAK add-on
libraries for Clipper, the dCLIP development platform/runtime
system for Clipper, and "FYI - Work Smarter", a home-office
management system. Roger's programming background includes
assembly-language in "real-time" applications, basic, pascal,
plz, dBASE-II, dBASE-III, Clipper and miscellaneous technical
support languages. Roger holds a BSEE degree from West Coast
University in Southern California and is a Vietnam veteran with
8-years of U.S. Navy electronics background in radar and
communications.
Roger J. Donnay
DONNAY Software Designs
1880 Park Newport, Suite 104
Newport Beach, CA 92660
Voice: 714-721-6720
Fax : 714-721-9495
BBS : 619-728-4318 or 619-728-0633
Compuserve ID : 73227,1225
This documented is dated July 7, 1990
Page 40 - Copyright (c) DONNAY Software