Copyright (c) 1988 Nantucket Corp. All rights reserved.
"Clipper" refers to the Summer87 version of Nantucket's Clipper
compiler for dBASE. None of this information should be assumed to
apply to any other version of Clipper.
"MS-C" refers to Microsoft's DOS C compiler, version 5.0 or higher.
An "internal" is a function or storage location which is not part of the
published (or external) specification of a system.
An "intrinsic" refers to an element or feature of a system which is
"built in," and does not require explicit programming support. This
word is also used here to refer to the machine instructions or support
library function calls used to implement such a feature (in this case,
floating point math).
In Clipper, numeric values are represented internally as binary integers
wherever possible (operations on integers are faster than equivalent
floating point operations, even when a coprocessor is present). When an
operation is encountered whose result cannot be accurately represented as
an integer, the values associated with the operation are automatically
converted to double precision floating point.
Floating point operations are implemented via an augmented subset of the
MS-C "alternate" floating point system. This system was chosen because
it provides maximum execution speed when a coprocessor is not present.
Since the "alternate" system does not use the coprocessor, Clipper
manually checks for its presence and uses it for some operations.
All Clipper floating point operations are performed by calling a set of
standard low level numeric support functions. If a coprocessor is
present, these functions execute appropriate coprocessor instructions.
Otherwise they branch to the corresponding MS-C "alternate" functions.
The Clipper support library (CLIPPER.LIB) contains both the low level
functions and those parts of the MS-C "alternate" library which are
necessary for their operation. For more information on MS-C floating
point support, refer to the MS-C documentation.
The file "nsupport.h" is intended to allow C programs to perform
floating point operations by calling Clipper's low level support
functions. There are several potential advantages to doing this:
A smaller load image, since only a subset of the MS-C alternate
library is needed (and it is present in CLIPPER.LIB).
Faster execution, both because the "alternate" system is faster and
because the Clipper functions also use the coprocessor (if there is
one) for some operations.
Elimination of the necessity for extra C support library code
(useful to add-on product developers).
Compatibility with other C compilers; non-MS compilers (and certain
options of MS-C) generate math intrinsics which are incompatible
with the support code in CLIPPER.LIB. This system is designed so as
to suppress the generation of math intrinsics.
Better linker compatibility; some C compilers generate math
intrinsics which rely on special linking.
Whether any of these advantages are realized depends on the nature of
the application code (and on which C compiler is used). In any case,
there are also some potential disadvantages:
The function calling and parameter passing overhead may eat up
the code savings.
The source code will probably be less readable than if inline
numeric operations were used.
The definitions supplied in "nsupport.h" differ depending on whether
either (or both) of two key symbols is defined prior to its inclusion:
The REAL_DOUBLES symbol:
All of the definitions in "nsupport.h" are coded using a special data
type called XDOUBLE. If the REAL_DOUBLES symbol is defined before the
inclusion of "nsupport.h", then XDOUBLE will be defined simply as
'double' (the normal C double precision type). Otherwise, XDOUBLE is
defined as a structure containing a double (the default).
Defining XDOUBLE as a structure prevents the generation of floating
point intrinsics when passing XDOUBLE values to and from the low level
functions (most C compilers load and store double values using either
coprocessor instructions or emulator calls). Unless the C source is
compiled with MS-C using the "alternate" option (/FPa), any floating
point intrinsics are likely to cause problems. When XDOUBLE is defined
as a union, different intrinsics are used. These intrinsics are simpler
(typically 8086 MOVS instructions or calls to simple functions), and
are often tolerable, even when using a non-MS compiler. Despite all
this, the XDOUBLE structure is eight bytes long and should behave just
like a normal 'double' with regard to assignment and parameter passing.
Using the XDOUBLE structure has a second benefit: It causes the C
compiler to generate an error if an XDOUBLE value is used other than in
an assignment or as a function parameter. This helps to ensure that
your code is not attempting to perform math operations by means of
normal C operators or functions; troublesome math intrinsics will
(hopefully) be prevented at compile time. (Note that the XDOUBLE
structure will only work with C compilers that allow structured
If this symbol is defined before the inclusion of "nsupport.h", then
most of the low level numeric functions are defined as macros. These
macros are functionally equivalent to the Clipper low level functions,
but rely instead on standard C operators and library functions. This
allows code written to the Clipper low level spec to be recompiled for
use in other environments. (Note, however, that some of the low level
functions have no equivalent in standard C support.)
The operation of the low level functions themselves is, for the most
part, self explanatory. The functions (as actually implemented in
CLIPPER.LIB) are written primarily in assembler, but obey the standard
C calling conventions. For details on how the functions work, refer to
the file "nsupport.c" (described below).
Some C compilers may still be incompatible with the Clipper system, even
if "nsupport.h" is used. In particular, note that double values are
returned via a far pointer to a single floating point accumulator. This
is consistent with most C compilers (including MS-C and Turbo-C).
Most C compilers now allow assignment of structure and the passing of
structure by value. Some of them may flag such structure references
with a warning. Others may not support it at all.
"nsupport.h" would typically be used with "extend.h" (and "extor.h") to
create Clipper-callable numeric processing functions. In this case, you
should edit the "extend.h" and "extor.h" files, changing references to
type 'double' to type 'XDOUBLE' instead. Note also that "nsupport.h"
should be included first in your source (before "extend.h" or "extor.h")
so that XDOUBLE will be defined.
"nsupport.h" requires certain typedef's found in "nandef.h" (from the
Clipper distribution disks). Thus "nandef.h" should be included before
"nsupport.h" or other header files.
As always, Clipper callable code should use the large memory model.
Also, CLIPPER.LIB does not contain the MS-C stack checking code.
The appearance of undefined symbols named 'FIERQQ', 'FIDRQQ' and the
like, means that the C compiler is requesting the linker to include a
coprocessor emulator. (With MS-C this can occur even though no floating
point operations were performed in the program; the mere presence of a
double value can trigger it.)
Users of Borland's Turbo-C package will find that use of the XDOUBLE
structure requires one or more functions from the Turbo-C library. No
math functions should be required, however.
Elimination of numeric intrinsics (other than subroutine calls) appears
to be a prerequisite to linking MS-C objects using Borland's TLINK.
Other hints for MS-C users who wish to maintain TLINK compatibility:
Do not declare functions 'static', and be sure to supply initializers
for any static or global data items.
"nremove.scr" and "nsupport.c"
The file "nsupport.c" contains the C source code for a set of functions
which provide the same interface and functionality as the Clipper's low
level numeric functions. Operations are performed using a combination
of standard C operators and calls to standard C support routines.
The code is provided primarily as documentation on the workings of
Clipper's low level functions. Nonetheless it is compilable with MS-C,
and should be functionally identical to the code in CLIPPER.LIB.
As described above, all Clipper floating point operations are effected
by calling the low level support functions (which typically call MS-C
functions to do the real work). No other floating point mechanisms are
present in CLIPPER.LIB. This means that it is possible to remove the
standard low level functions (and associated MS-C support code) from
CLIPPER.LIB, and substitute some other floating point package. (Such a
package would, of course, have to obey the same calling conventions and
produce the same results as the standard low level functions.)
The file "nremove.scr" is a script file for Microsoft's Library Manager
(LIB.EXE, included with most Microsoft language products) which will
remove from CLIPPER.LIB the standard low level functions and the MS-C
"alternate" routines upon which they depend. The script produces a
library named NREMOVED.LIB; CLIPPER.LIB must be available, but is
unaffected by the operation.
One obvious use for "nsupport.c" would be to compile it using a
different MS-C floating point option. The resulting object (and any
necessary MS-C library support) could then be substituted for Clipper's
standard low level functions. All Clipper numeric operations would then
utilize the new option.
Theoretically, it should also be possible to recompile this file with
some other C compiler. Clipper numeric operations would then use the
other compiler's intrinsics and support code. This has not been tried
and any such attempt should be undertaken with caution; floating point
support packages typically rely on special initialization code which
would not be present in the standard Clipper startup module.
Clipper's startup code is a slightly modified version of the MS-C v5.0
startup module. For information, refer to the file "crt0.asm" supplied
with MS-C. The _dvinit() entry point in "nsupport.c" may be of use in
As noted above, "nsupport.c" is supplied primarily as documentation; it
was written with simplicity in mind, not efficiency.
"nsupport.c" requires both "nandef.h" (from the Clipper distribution
disks) and "nsupport.h" for compilation.
Use of "nremove.scr" and "nsupport.c" (other than for informational
purposes) is not for novices. Please be careful.