Lattice_C_Compiler_CPM 86 Lattice C Compiler CPM

Lattice_C_Compiler_CPM-86 Lattice_C_Compiler_CPM-86

User Manual: Lattice_C_Compiler_CPM-86

Open the PDF directly: View PDF PDF.
Page Count: 272 [warning: Documents this large are best viewed by clicking the View PDF Link!]

@LATTICE,INC.
P. O. BOX 3072 ·GLENÉLLYN·LLNOIS 60138· 3l2/858ñ9!5OU1NX9lO29l-2l9O
TECHNICAL BULLETIN
TB841101.001
DATE: November 1, 1984
PRODUCT: 8086/8088 CCompiler
SUBjECT: Known Bugs in Version 2.14
Recently three bugs concerning the Version 2.14 libraries and
startup modules have come to light. Two of these pertain to the
sensing and use of the 8087 co-processor, and the other concerns
the use of the "malloc'° and "getmem" functions under MS-DOS 1 in
the sand Pmodels of the compiler. In addition some code was
oMtted from the file "main.c".
1. Floating Point Bugs
(a) Sensing cjf the 8087
The technique employed in the run-time library to sense
the presence of the 8087 co-processor does not work in
V2.14 because the 8087 is not initialized prior to the
test. Correcting this problem is rather easy. You need
only add aline of code to the file °'c.asm" provided with
the compiler and reassemble this file to replace the
current "c.obj".
In the file "c.asm" you will find aline:
CALL JLAIN
just prior to this line, insert the fcülowing line
DB ODBh,OE3h ;FNINIT instruction
Then reassemble "c.asm" for each of the memory models as
follows:
-- Copy "c.asm" to the appropriate model subdirectory
(i.e., \lc\s, \lc\d, \lc\p, or \lc\l) so that it is
in the same directory as "dos.mac" for the
appropriate memory mcdel.
-- Use the command
1
@LATTICE,1NC.
W
P. O. BOX 3Q72 ·GL£N ELLYN ·ILLNO1S 60138 ·312/858-7950·TWX9lO291-2
masm c;
to assemble "c.asm" into "c.obj".
The instruction is specified here as a"DB" pseudo-op
rather than an "FFNIT' instruction since many assemblers
do not properly handle floating point instructions.
Should your assembler be able to handle such instructions,
be sure to use an "FNINIT" instruction rather than "FINIT"
Qr else the assembler will generate a"WAIT" instruction
prior to the °'FINIT" and resulting programs will wait
endlessly on machines not containing aco-processor.
(b) Floating Point in the Darid LMdels
In attempting to repair an earlier bug concerning the 8087
we accidentally broke its use in the Dand Lmodels. To
correct the problem you can use "debug" to patch the
libraries "lcmd.lib" and "lcml.lib" as follows.
(Underlined portions are what you must type. Each line
must be entered with acarriage return.)
(i) Patching lcmd.lib
>debuq lcmd.lib
-eA97A 10.12
-eA9CC 78.76
-W
-SI
>
(ii) Patching lcml.lib
Aebug Icínl.Iíb
-eBB71 12.14
-eBBC7 3D.3B
-W
-g
>
(C} Bug in 8087 Library Divide Routine
Under certain circumstances the floating point division
function Cxd55 will return the incorrect value when an
2
@LATTICE, INC.
P. O. BOX 3072 ·GLEN ELLYN ·LUNOIS 60138 ·312/858-7950 ·TWX 9lO29l-2l90
8087 is present since this function fails to save and
restore the DI register. This bug will be repaired in a
future release .
(2) Ma1loc and Getmem under MS-DOS 1
The Sand Pmodel library memory allocation functions
"malloc" and "getmem" will n<jt return the correct values in
an application running under MS-DOS 1when acall to one of
these would cause the total memory allocated to exceed 64K.
In particular the failure value of NULL will not be returned
in this case. This problem will be fixed in afuture
release, and it does not effect the Dand Lmodelm
(3) Omission in 'Lmain.c"
The last "exit(O);" statement should be replaced with
Ñifndef TINY
'exit(0);
#else
exit(0);
Tencí if *** END **"
3
@LATTICE,INC.
P. O. BOX 3072 ·awELLvN· LLINOQS 6Ol380 JR/B58J950·TWX9I029I-2I%
TECHNICAL BULLETIN
TB8410¶0.001
DATE: october TO, 1984
PRODUCT: 8086/8080 CCompiler
SUBjECT: Ver3ion 2.14 Update
VerMon 2.14 of the 8D86/808B Ccompiler hm been released to
correct the following problenm
1. In VerMon 2,¶3, the Smodel libr&ríeg were built in 8UCÍll
away that the floating poInt operattom did not me the
8087 chip ff pregent. The other memory model$ worked
correctly.
2. Klhíle ffxfng the PUTC problem In VerMon 2.fj, we broke
the level 2buffer flmh function 9n mich &way that buffer8
were mnnethnes written twice. Thlg would occur when you did
several FSEEKg without intervening re&dg or vrítm.
3. UNGETC did not alwayg work correctly under the dmd L
modelg, depending on where the buffer ma® lomted.
000END$0*
1
@LATTICE,INC.
P. OBOX 3on·cA£NELlNN·LLlNo|s6oí38· 3u/85B-795o0Twx9m9l.2l9o
TECHNICAL BULLETIN
TB8410¶0.002
DATE: October tO, 1984
PRODUCT: 8086/0088 CComplier
SUBjECT: Insufficient Memory Mesmge
In bulletfn TB840914.otn we mentioned aproblem observed during
the tesMng of vergjcyn 2.13 that resulted in an "!nsuff!cient
memory" message. At that tfme, we believed that the message was
orSgínatfng from Hs-ljOS. Hell, we must admit with ablush that
the message was coming from C.ASl'l, our start-up mdule.
The situation leading to this meggage wá3 that we forked achild
prDc'e53 wttcjse .EXE file jU9t barely fit into the available
memory. After loading the .EXE file, FfS-ljOS passed control to
the child procesg at the C.ASM entry point. C.ASM then attempted
to allocate gtack and he€p 8pace for the Cprogram, but there wá9
not enough memory. When that occurred, C.ASK dlmplayed the
'°ínsufficient memory" me33age and aborted with anon-zero exit
code.
The migtake we made in our tmt program w39 to examine only the
return code from the FORKL function. Thig wIll indicate an error
only If MS-DOS wá9 unable to obtain the needed gpace and load the
ch9ld program. He should have &Ííorj U3ed the WAIT functfon to
check the exit code from the child.
""END°""
E
@LATTICE,INC.
PO DOX 3072·GLENELLYN·LLNOS 60138· 312/858795O·TwX91O29i-2l9O
TECHNICAL BULLETIN
TBB41010.003
WLTE: October 10, 1984
PRODUCT: 8086/8088 CCompiler
SUBJEC"I); Combining LC and LCM Librar!eg
In TB840914.OQI we g&ve a Mmple procedure for combtnlng the LC
and LCM librarfes. Some people who tried this procedure became
concerned about the duplicate symbol me3gageg that regulted.
Here is abetter procedure:
1. Use your favorite editor to create the file MIXLC.LNK
containing the following:
bu Icc.lfb
lcm.líb
fL lc.lib
exc _pfmt,cprlntf,fprintf,printf,gprintf
exc gfmt,c8canf,fgcanf,gcanf,g5c8nf
2. For each memory model, copy MIXLC.LNK into the \lc\x
directory, where xis g, p, d, or I. Then U9é CD to get
into that directory, and execute PLIB86 &g follows:
plib86 émlxlc
Thig procedure creatm acombined library LCC.LIB which ínclude3
the complete verMons of the PRINTF/SCANF functlonm If you vant
8combined library that contains the abbreviated verMons, Mmply
Interchange the two "ft" commandg In HIXLC.LNK.
"'"END000
1
@LATTICE, INC.
P O BOX jon·gLENEtlYN·LlNcMs 6Olj8 ·312/858795O·TWx9l029l.2l9O
TECHNICAL BULLETIN
TB8U)9ICOO1
DATE: September u, 1984
PRODUCT: 8086/8088 CCompiler
SUBJECT: Version 2.¶3 UHate
VerMOn 2.1J of the 8086/8088 Ccompiler has been relemed to
correct the following problems:
I. STRCMP and STRNC6IP did not return the correct results
when ccmparlng string3 of unequal lengthm
2. The various form8 of PUTC did not work correctíY under
the Dand Lmodelm
j. The results of afloatfng-polnt divide-by-zero operation
with an 8087 installed were not the Bame 88 when the 8007
wag removed.
4. Several problems exi8ted in the varÍoü8 FORK functfonm
(a) The environment 8trlng array va8 sot pamed
correctly to the child Process under the S&nd Pmemory
models.
tb) An extra backslash wa8 appended to the PATH
variable. ThG wm usually accepted by PCDOS, but waB
rejected by 9otñe MSDOS fmplementationm
(C) The construction of default FCBS did not Hop vhen
an argument beginnfng with aUash w33 reached. This
caused problem for 8ocñe older programs that relied on
the FCB setup done by the MSDOS command processor.
(d) The fork logic searched for a.EXE file before a
.COM fije. Thi8 hag been reversed because some people
keep the .EXE version around even after they have
generated a.COM.
1
@LATÍ1CE, INC.
P. OBOX 3072 ·GLEN ELLYN ·UNOSS 60138 ·JJ2/858 7950· JWX 910 291 219'
(e )Acarriage return was not appended to the generated
command string, which caused some forked programs to
fatI.
These problems usually showed up when you tried to fork the
command processor or when the chi Id process attempted to use
the inherited environment. Td sImplify the invocation of
the command processor, we've addeQ &UNIX-compatfble SYSTEI·)
funct ion. The function has one argument, the command
gtríng, and returns the same results as FORKL. For exemple,
systemC"dir a:")
calls the command processor to display the directory frorn
drSve A.
Nhíle testing the fork functions, we observed what appears
to be an HS-IJOS bug. Hhen the operating system cannot
obtain enough memory to load the child prográm, it's
supposed to return error cocjé Bthat we wIll then pass back
to you In _oserr. However, En some cases, t·lS-DOS displays
the message "jnsuf flcient memDTy" on the screen and returns
asuccem code. This has been observed on PC-DOS 2.1 and
3.0 running on the IBH-XT and IBH-AT and in the version of
MS-DOS currently running on the TANDY 2000. We are pursuing
asolution, but if anybody can give us any further
informatfon, we vould appreciate the help.
5. The SETJHP/LONGJKP functions did not viork correctly under
the pmode! .Note that thh correctfon required achange in
the SETJMP.H header file and that ALL PROGRAPIS USING THIS
HEADER MUST BE RE-COHPILED regard)esg of which memory model
they employ.
6. Detection of the 8087 .did not work correctly on sYstems
using an 80286, such ag the IBI4-AT.
7. The POW function did not always return the correct
result.
B. Several people complained that the libraries became way
tejo larqqe uhen we added the math functions. Therefore, we
have sp it the library for each memory model into two
pieces. LCV.L,IB contains the "core functSons" for memorY
mode! x, and I.CMX.LIEj contains the floating point math
2
@LATTICE,INC.
POBOX 3072 ·GLEÑELLYN·LLNOS60138 ·3l2/858-7950·l"WX9lO-29l-2l9O
functions. If you need to use both libraries, make sure
that LCM is mentioned before LC at link time. If you are
also using our CF(JOD Smorgasbord, its library (LCX) should
be mentioned before LCFI. At this time we are pretty
confident that the library wa3 split in the correct place,
but if you find any interdependence problems that we
overlooked, please report them to lbS. If you want to re-
combine the two libraries, use PLIB86, as follows:
ren lc.lib lcc.lib
plib86 bu lc.lib fi lcc.lib,lcm.lib
Note that the batch files that we've been supplying for
linking, named LLNKx.BAT, OtÁY use LC.LIB. The release
disks include some new batch files named LINKMX.BAT that use
both LC61.LIB and LC.LIB.
You snould also be aware that two versions of the PRINTF and
SCÁNF families are provided. If you don't use LCM.LIB,
you'll get avergton that does not support floatln3 point
conversÍoñ3, which saves about 3Kbytes in the loa module.
With LCM.LIB, you get the full PRINTF and SCANF conversion
capabilities.
9. we've eliminated the need for TINYMAIN.C by putting
conditional compilation statements into _MAIN.C, and the
release disks now contain pre-comptled versiom of the
abbrev¡ated0_bjAIN under the names jQAINx.OBj, where xi3 the
memory model (S,P,D, or L). If you need to recompile MAIN,
use the LC option -dTINY=1 to get the abbreviated versTon.
The LC libraries still contain the full version of J4AIN,
which is the default. Because this full version supports
the stdin, stdout, and stderr files, it force3 all of the
level 2. I/O functions to be included. If you don't need
these standard files and don't use any level 2I/O, your
load module size will be reduced by using the abbreviated
version;
*'*END"°
J
LIFEBOAT
a8SOCiat08
LMtice CManual
kMiao ~~
cc·mNM
Fumtbnd DescripHon Released Nty 25, 1982
Nkmud
This document describes
Revision 2dthe compiler
and librory.
Copyright "1982, )984 by
Lattice, Inc.
Note: Supplement to üjttice Cv. 2.)
Qppended to this document
May 29, )984.
Published by:
Lifeboat Associates
1651 Third Avenue
New York, New York ÍOÍ28
Tefe: (212)8600300
Telex: 424490 (LBSOFT Ul)
PREFACE
Lattice, Inc., adeveloper of portable softwarz products based in
Chicago, Illinois originally developed Lattice Cfor its own
internal use on aminicomputer. When the IBM PC was introduced
in 1981, the company recognized the potential for developing a
full implementation of the Cprogramming language for 16-bit
microcomputers. Lifeboat Associates, aNew York-based software
publisher, then provided Lattice with funding which enabled the
company to make the conversion. It is believed that Lattice C
was the first minicomputer product successfully "ported" to the
IBM PC. In 1983, Microsoft, based in Bellevu.e, Washington,
selected Lattice Cto become Microsoft C. Also in 1983, Lattice
developed aversion of its compiler for the Motorola 68000
microprocessor and a280 cross-compiler for B-bit CP/M-based
microsystems. with Revision 2, Lattice Cimplements MS-DOS 2.0
pathnames and large memory models, giving software developers the
ability to create programs and data structures which can better
utilize the large memory available on 8086/8088-based systems.
TRADEMARK ACKNCMLEDOBNT8
Lattice is aregi8tered trademark of Lattice, Inc.
MS-DOS 18 aregi8tered trademark of Kicro8oft, Inc.
CP/M is aregistered trademark of Digital Re8earch, Inc.
UNIX is atrademark of Bell Telephone Laboratoriem
Intel 18 atrademark of Intel Corporation.
Motorola 18 atrademark of Motorola Corp.
280 is atrademark of Zilog, Inc.
TABLE OF CONTENTS
Section lIntroduction I-L
Section 2Language Definition
2.1 Summary of Mfferenc"."s 2-l
2.1.1 Differ>"nccs from the Standard 2-l
2.1.2 Arbitíary LimIt3tions 2-3
2.2 Major Language Features 2-4
2.2.1 Pre-processor Features 2-G
2.2.2 Arithmetic objects 2-5
2.2.3 Derived Objects 2-6
2.2.4 Storage Classes 2-6
2.2.5 Scopc' of Identifiers 2-B
2.2.6 Initializers 2-8
2.2.7 Expression Evaluation 2-9
2.2.8 Control Flow 2-ll
2.3 Comparison to the CReference Manual 2-ll
Section 3Portable Library Functions
3.1 mmory Allocation Functions 3-l
3.1.1 Level 3Memory Allocation 3-2
3.1.2 Level 2Memory Allocation 3-6
3.1.3 Level lMemory Allocation 3-12
3.2 I/O and System Functiom 3-lS
3.2.1 Level 2I/O FUnction8 and Macros 3-15
3.2.2 Level I I/O Functiom 3-40
3.2.3 Direct Console K/O Functions 3-49
3.2.4 program Exit Functiom 3-56
J.3 Utility Functions and Macros 3-59
3.3.1 Memory Utilities 3-59
3.3.2 Character Type lqacro8 3-63
3.3.3 String Utility Functions 3-64
3.3.4 Utility Macros 3-83
Section 4Compiler and Run-time Implementation
4.1 Operating Instructions 4-l
4.1.1 Phase l4-3
4.1.2 Phase 24-7
4.1.3 Program Linking 4-8
4.1.4 Program Execution 4-9
4.1.5 Function Extract Utility 4-13
4.1.6 object Module Dissassembler 4-15
4.2 Machine Dependencies 4-18
4.2.1 Data Elements 4-18
4.2.2 External Names 4-19
4.2.3 Include File Processing 4-20
4.2.4 Arithmetic Operations and Conversions 4-20
4.2.5 Floating Point Operations 4-21
4.2.6 Bit Fields 4-22
4.2.7 Register Variables 4-23
4.3 Compiler Processing 4-23
4.3.1 Phase l4-23
4.3.2 Phase 24-24
4.3.3 Error Processing 4-25
4.3.4 Code Generation 4-25
4.4 Memory Áddressing Models
4.4.1 Choo8ing the Memory Model 4-28
4.4.2 Compiling the Memory Models 4-29
4.4.3 Linking Program8 4-30
4.4.4 Code Generation for Pointer Operations 4-30
4.4.5 The -s option for Four-byte Pointers 4-32
4.4.6 Creating an Array Greater than 64K 4-33
4.5 Run-time Program Structure 4-34
4.5.1 object Code Conventiom 4-36
4.5.2 Linkage Conventions 4-37
4.5.3 Function Call Conventiom 4-38
4.5.4 Assembly Language Interface 4-40
4.5.4 Stack Overflow Detection 4-44
Section 5System Library Implementation
5.1 File I/O 5-l
5.2 Device I/O 5-2
5.3 Memory Allocation 5-4
5.4 Program Entry/Exit 5-5
5.5 Special Functions 5-5
Lattice 8086/8088 CCompiler Introduction
SECTION I:
Introduction
This document provides afunctional description of an
implementation of the Lattice Ccompiler, aportable compiler for
the high level programming language called Ca It makes no
attempt to discuss either programming fundamentals or how to
progEam in Citself. Extensive reference is made to the
definitive text The C, Proqramming Language, by Brian W. Kernighan
and Dennis M. Ritchie (Prentice-Hall, Inc., Englewood Cliffs, New
jersey, 1978). This description of Lattice Cis incomplete
without the Kernighan and Ritchie text, as it is called, which
also provides an excellent tutorial introduction to the language.
l.l Documentation
The manual is divided into five sections. First, this
introduction. Second, the language accepted by the compiler,
which differs from the standard in only afew minor details, is
described. The third section presents the portable library
functions in functional groups with calling sequences and
examples. Fourth, the details of the compiler and run-time
program execution are presented for this implementation,
including detailed operating instructions, machine dependencies,
and program structure. Fifth, the operating system interfaces
are described in terms of the portable library functions (file
naming conventions, etc.) and the special functions provided with
this implementation.
as this document is intended to serve as areference manual, each
topic is usually presented in full technical detail as it is
encountered. Some reference to'sections not yet encountered is
unavoidable, but thege references are gpecificalIy noted.
to get an overview of the compiler, read the first portion of
each of the major suMections in the implementation description
(Section 4), the language summary at the beginning of the
language definition (Section 2), and the function summaries at
the beginning of the library groups (Section 3), and the
introductions to the subsections in the system interface
information (Section S). Error messages are described in
Appendix Aand error reporting procedures in Appendix B. Method8
of converting Cprograms written for CP/M microcomputer gygtems
are de3cribed in Appendix c. alist of files Mipped with
Lattice Care contained in Appendix D.
I-l
Lattice 8086/8088 CCompiler Language Definition
SECTION 2:
Language Definition
The Lattice portable Ccompiler accepts aprogram written in the
Cprogramming language, determines the elementary actions
specified by that program, and eventually translates those
actions into machine language instructions. Although the final
result of these processes is highly machine-dependent, the actual
language accepted by the compiler is, for the most Dart,
independent of any sYstem or implementation details. This
section presents the language defined by the Lattice Ccompiler
using the Kernighan and Ritchie (K&R) text The CProgramming
Lanquaqe as a reference point. Since this language conforms
closely to that described in the text, only the major differences
are first presented. The major features of the language are then
discussed, not in any attempt at completeness, but simply for the
sake of showing them from adifferent perspective. Finally, a
comparison with the Kernigban and Ritchie "C Reference Manual" is
made to show more precisely how the Lattice implementation
differs from the standard.
2.1 Summary of Differences
There are two classes of differences that appear in adiscussion
of an implementation of aprogrammÍng language. The first class
is that of actual semantic differences; that is, variations which
cause the meaning of language constructs to differ. The second
class is merely areflection of the practical limitations to
which all programs -- including compilers -- are subject. Each
of the following subsections presents the respective details for
the Lattice implementation of C.
2.1.1 Differences from the Standard
Deviating from astandard has its own peculiar set of perils and
rewards. On the one hand, the differences create problems for
those who have conformed to the standard in the past; on the
other, they may make life easier for those who take advantage of
them in the future. Most of the differences listed below were
prompted by adesire to make the language both more portable and
more comprehensible. The vast majority of programs will not
encounter these Potential troublespots; those that do will in
most cases be improved by adjusting to conform to them. Here,
then, is asummary of the major differences:
oComments normally can be nested in the Lattice compiler; in
the standard, they cannot. Acompile-time option forces the
compiler back to the standard non-nesting mode.
oPre-processor macro substitutions using arguments must be
specified on a single line; for example, when max(a,b) is
used, the invocation text from max to the final closing
parenthesis must be defined within asingle input line.
2~1
Lattice 8086/8088 CCompiler Language Definition
oThe dollar sign (S) is permitted as an embedded (i.e., not
the first) character in identifiers.
oIdentically written string constants refer to the same
static storage location; that is, only one copy of the
string is generated by the compiler. This is in contrast to
the statement in Kernighan and Ritchie that all strings are
distinct, even when written identically.
oMultiple character constants are accepted by this compiler;
in the standard, only asingle character enclosed in single
quotes is legal. The resulting value may be @9,FE or long,
and its exact value is machine-dependent.
oIn processing structure and union member declarations, the
compiler builds aseparate iist of member names for each
structure (or union). Thus, identical names may be used for
members in different structures, even though both the offset
and the attributes may be different in each declaration.
The specific structure being referenced determines which
member name (and therefore which offset and set of
attributes) is meant. The typing rules for structure member
refeEences are strictly enforced so that the patticular list
of valid member names can be determined. In other words,
the expression in front of the .or -> operators must be
identifiable by the compiler as a structure or pointer to a
strueture of adefinite type.
oImplicit pointer conversion (by assignment) is legal but
generates awarning message; this occurs whenever any value
other than apointer of the same type or the constant zero
is assigned to apointer. Acast operator can be used to
eliminate the warning. Amore stringent requirement is
enforced for initializers, where the expression to
initialize apointer must evaluate to apointer of the same
type or to the constant zero; any other value is an error.
oIf astructure of union appears as a function argument
without being preceded by the address-of operator &, the
compiler generates awarning message and assumes that the
address of the aggregate was intended.
oAn array name may be preceded by the address-of operator &;
the meaning, however, is not that of apointer to the first
element but of apointer to the array. This construct
allows initialization of pointers to arrays.
oThe constant expression following an tif conditional
statement may not contain the sizeof operator and must be
completed in less than asingle line.
Amore systematic and detailed explanation of the above
differences is presented in Section 2.3, but some of the most
important items above deserve immediate clarification.
2-2
Lattice 8086/8088 CCompiler Language Definition
The intent behind making the structure and union member names a
separate class of identifiers for each structure is twofold.
First, the flexibility of member names is greatly increased,
since now the programmer need not worry about apossible conflict
of names between different structures. Second, the requirement
that the compiler be able to determine the type of the structure
being referenced generally improves the clarity of the code, and
disallows such questionable constructs as
int *p;
© D U
p->xyz =4;
which is considered an error by this compiler. Those who grumble
about this restriction should note that one can. accomplish the
equivalent sequence in Lattice Cby using acast:
((struct ABC ")p)->xyz =4;
The parentheses are required since the -> operator binds more
tightly than the cast. The idea is not that such code should be
prohibited unconditionally but that any such constructs should be
clearly visible for what they are; the cast operator serves this
purpose nicely.
Exactly the same intent is present in the pointer conversion
warning. By using acast operator, the programmer can eliminate
the warning; the conversion is then explicitly intentional, and
not simply the result of sloppy coding. In addition, there is a
more important reason for the warning. Although many Cprograms
make the implicit assumption that pointers of all types may be
stored in int variables (or other pointer types)" and retrieved
without difficulty, the language itself makes no guarantee of
this. On word-addressed machines, in fact, such conversions will
not always work properly; the warning message provides agentle
(and non-fatal) reminder of this fact.
Finally, the warning generated when astructure union is used
as afunction argument without the address-of operator is
intendeCi to remind programmers that this compiler does not allow
an aggregate to be passed to afunction -- only pointers to such
objects.
2.1.2 Arbitrary Limitationg
Although the definition of aprogramming language is an idealized
abstraction, any real implementation is constrained by anumber
of factors, not the least of which is practicality. Thé Lattice
compiler imposes the following arbitrary restrictions on the
language it accepts:
oThe maximum size, in bytes, of any declared object is the
largest positive integer which can be represented as an int.
This implies, for example, amaximum size of 32767 bytes for
2-3
Lattice 8086/8088 CCompiler Language Definition
l6—bit int machines. The total size of all objects declared
with the same storage class is also 6ubject to the same
restriction.
oThe maximum value of the constant expression defining the
size of asingle subscript of an array is one less than the
largest pQsitive int (32766 for a16-bit int).
oThe total size of the formal parameters for any function is
limited to amaximum of 256 bytes. Thus, the maximum number
of formal parameters depends on their sizes.
oThe maximum size of astring constant is 256 bytes.
oMacros with arguments are limited to amaximum number of 8
arguments.
oThe maximum level of Finclude file nesting is 4.
These limitations are impomd because of the way objects are
represented internally by the compiler; our hope is that they are
reasonably large enough for most real programs.
2.2 Major Language Features
The material presented in this section is meant to clarify some
of the language feature8 which are not always fully defined in
the Kernighan and Ritchie text. These are features which depend
on" implementation decisions made in the design of the compiler
itself, or on interpretations of the language definition. Those
language features which are specifically machine dependent are
described elsewhere in this manual.
2.2.1 Pre-processor Features
The Lattice Ccompiler supports the full set of pre-processor
commands described in Kernighan and Ritchie. Most
implementations perform the pre-processor commands concurrently
with lexical and syntactic analysis of the source file, because
an additional compilation step can be avoided by this technique.
Other versions of the compiler incorporate aseparate pre-
processor phase in order to reduce the size of the first phases
of the compiler. In either case, the analysis of the pre-
processor commands is largely independent of the compiler's C
language analysis. Thus, tdefine text substitutions are not
generally performed for any of the pre-processor commands,
although nesting of macro definitions is possible since
substituted text is always re-scanned for new #define symbols.
An exception Dccurs for the #if command, which is processed
differently., As noted in the list of differences, sizeof cannot
be used in áif expressions, and the expression must apDear
entirely on a single line. These restrictions result ftom a
desire to keep #if expressions simple, and because the pre-
processor generally has no information about the size of declared
2-4
Lattice 8086/8088 CCompiler Language Definition
objects. One other clarification should be noted: if asymbol
appears in an tif expression which has not been defined in a
tdefine command, it is interpreted as if avalue of zero had been
specified. This seems consistent with #ifdef usage and permits
the use of symbols which may or may not be defined. Otherwise,
#if expressions support the full range of operations described in
Section 15 of Appendix Aof Kernighan and Ritchie.
The Qdefine command, as noted in Section 2.1.1, has the
limitation that the macro invocation text must all be contained
on a single input line. Because the compiler uses atext buffer
of fixed size, aparticularly complex macro may occasionally
cause aline buffer overflow condition; usually, however, this
error occurs when more than one macro reference occurs in the
same source line, and can be circumvented by placing the macros
on different lines. Circular definitions such as
tdefine A B
tdefine B A
will be detected by the compiler if either Aor Bis ever used,
as will more subtle loops. Like many other implementations of C,
the Lattice compiler supports nested macro definitions, so that
if the line
tdefine XYZ 12
is followed later by
tdefine XYZ 43
the new definition takes effect, but the old one is not
forgotten. In other words, after encountering
#undef XYZ
the former definition (12) is restored. To completely undefine
XYZ, an additional tundef is required. The rule is that each
tdefine must be matched by acorresponding tundef before the
symbol is truly "forgotten".
2.2.2 Arithmetic objects
Six types of arithmetic objects are supported by the Lattice
compiler; along with pointers, these objectb represent the
entities which can be manipulated in aCprogram. The types are:
short or 8hort int
char
unsigned or unMgned int
long or long int
float
double or long float
2-5
Lattice 8086/8088 CCompiler Language Definition
Note that in this implementation, unsigned is not amodifier but
aseparate data type.
The natural size of integers for the target machine (the machine
for which code is being generated) is indicated by aplain int
type specifier; this type will be identical to either short or
long, depending on the architecture of the target machine.
Although the size of all these objects is technically machine-
dependent, the Lattice compiler assumes the target machine has an
B-bit, I6-bit, or 32-bit architecture and that the fundamental
storage quantity is an B-bit byte. Only in connection with bit
fields does this assumption ever become important.
The compiler follows the standard pattern for conversions between
the various arithmetic types, the so-called "usual arithmetic
conversions" described in the Kernighan and Ritchie text. The
only exception to this occurs in connection with byte-oriented
machines, where expansion of char to int uiay be avoided if both
operacds in an expression are char, and the target machine
supports byte-mode arithmetic and logical operations.
2.2.3 Derived objects
The Lattice Ccompiler supports the standard extensions leading
to various kinds of derived objects, including pointers,
functions, arrays, and structures and unions. Declarations of
these types may be arbitrarily complex, although not all
declarations result in alegal object. For example, arrays of
functions or functions returning aggregates are illegal. The
compiler checks for these kinds of declarations and also verifies
that structures or unions do not contain instances of themselves.
objects which are declared as arrays cannot have an array length
of zero, unless they are formal parameters or are declared extern
(see Section 2.2.4). All pointe,rs are assumed to be the same
size -- usually, that of aplain int -- with one exception. On
word-addressed machines, pointers which point to objects which
can appear on any byte boundary are assumed to require twice as
much storage as pointers to objects which must be word-aligned.
Note that the size of aggregates (arrays and structures) may be
affected by alignment requirements. For example, the array
struct {
short i;
char c;
}xtl0];
will occupy 40 bytes on machines which require short objects to
be aligned on an even byte address.
2.2.4 Storage Classes
Declared objects are assigned by the compiler to storage offsets
which are relative to one of several different storage bases.
The assigned storage base depends on the explicit storage class
2-6
Lattice 8086/8088 CCompiler Language Definiticm
specified in the declaration, or on the context of the
declaration, as follows:
External An object is classified as external if the extern
keyword is present in its declaration, and the
object is not later defined in the source file (that
is, it is not declared outside the body of any
function without the extern keyword). Storage is
not allocated for external items because they are
assumed to exist in some other file, and must be
included during the linking process that builds a
set of object modules into aload module.
Static An object is classified as static if the static
keyword is present in its declaration or if it is
declared outside the body of any function without an
explicit storage class specifier. Storage is
allocated for static items in the data section of
the object module; all such locations are
initialized to zero unless an initializer expression
is included in the declaration (see Section 2.2.6).
Static items declared outside the body of any
function without the static keyword are visible in
other files, that is, they are externally defined.
Note that string constants are allocated as static
items, and are treated as unnamed static arrays of
char.
Auto An object is classified as auto if the auto keyword
is present in its declaration, or if it is declared
inside the body of any function without an explicit
storage class specifier (it is illegal to declare an
object auto outside the body of afunction).
Storage is presumably allocated for auto items using
astack mechanism during execution of the function
in'which they are defined.
Formal An object is classified as formal if it is aformal
parameter to one of the functions in the source
file. Storage 18 presumably allocated for formal
items when afunction call is made during execution
of the program.
Note that the first phase of the compiler makes no assumption
about tbe validity of the reqister storage class declarator.
Items which are declared register are so flagged, but storage is
allocated for them anyway against either the auto or the formal
storage base. The implementation of register is machine-
dependent and may not be supported in some cases.
Note also that if the xcompile-time option is used, the implicit
storage class for items declared outside the body of any function
changes from static to extern. This allows asingle header file
to be used for all external data definitions. When the main
2-7
Lattice 8086/8088 CCompiler Language Definition
function is compiled, the xoption is not used, and so the
various objects are defined and made externally visible; when the
other functions are compiled the xoption causes the same
declarations to be interpreted as references to objects defined
elsewhere.
2.2.5 Scope of Identifiers
The Lattice compiler conforms almost exactly to the scope rules
discussed in Appendix Aof the Kernighan and, Ritchie text (pp.
205-206). The only exception arises in connection with structure
and union member names, where (as noted in Section 2.1) the
compiler keeps separate lists of member names for each structcre
or union; this means that additional classes of nm-conflicting
identifiers occur for the various structures and unions. Two
additional points are worth clarifying.
First, when identifiers are declared at the beginning of a
statement block internal to afunction (other than the first
block immediately following the fanction name), storage for any
auto items declared is allocated against the current base of auto
storage. When the statement block terminates, the next available
auto storage offset is reset to its value preceding those
declarations. Thus, that stQrage space may be reused by later
local declarations. Rather than generate explicit allocate and
dealLcxmte operations, the compiler uses this mechanism to
compute the totsl auto storage required by the function; the
resulting storage is allocated whenever the function is called.
With this scheme, functions will allocate possibly more storage
than will be needed (in the event that those inner statement
blocks are not executed), but the need for run-time dynamic
allocation witjÁn the function is avoided.
Second, when an identifier with aprevious declaration is
redefined locally in astatement block with the extern storage
class specifier, the previous definition is superseded in the
normal fashion but the compiler also verifies compatibility with
any preceding extern definitions of the same name. This is done
in accordance with the principle expressr"d in the text, namely
that all functions in agiven program which refer to the same
external identifier refer to the same object. Within asource
file, the compiler also verifies that all external declarations
agree in tjLE!e. The point is that in this particular case --
where alocal block redefines an identifier as extern -- the
declaration effectively does not disappear upon termination of
the block, since the compiler now has an additional external item
for which it must verify equivalent declarations.
2.2.6 IrÜtialiµers
objects which are of the static storage class (as defined in
Section 2.2.4) are guaranteed to contain binary zeros when the
program begins execution, unless an initializer expression is
used to define adifferent initial value. The Lattice compiler
2-8
Lattice 8086/8088 CCompiler Language Definition
supports the full range of initializer expressions described in
Kernighan and Ritchie, but restricts the initialization of
pointers somewhat. An arithmetic object may be initialized with
an expression that evaluates to an arithmetic constant which, if
not of the appropriate type, is converted to that of the target
object.
The expression used to initialize apointer is more restricted:
it must evaluate to the int constant zero or to apointer
expression yielding apointer OE exactly the same type as the
pointer being initialized. This pointer expression can include
the address of apreviously declared static or extern object,
plus or minus an int constant, but it cannot incorporate acast
(type conversion) operator, because pointer conversions are not
evaluated at compile time (exception: acast operator can be
used on an int constant but not on a variable" name). This
restriction makes it impossible to initialize apointer to an
array unless the &operator is allowed to be used on an array
name, because the array name without the preceding &is
automatically converted to apointer to the first element of the
array. Accordingly, as noted in Section 2.1, the Lattice
compiler accepts the &operator on an array name so that
declarations such as
int a[5]0 ("pa) [5] =&a;
can be made. Note that if apointer to astructure (or union) is
being initialized, the structure name used to generate an address
must be preceded by the &operator.
More complex objects (arrays and structures) may be initialized
by bracketed, comma-separated lists of initializer expressions,
with each expression corresponding to an arithmetic or pointer
element of the aggregate. Aclosing brace can be used to
terminate the list early; see Appendix Aof Kernighan and Ritchie
for examples. Unions may not be initialized under this
implementation, although the first part of astructure containing
aunion may be initialized if the expression list ends before
reaching the union. Acharacter array may be initialized with a
string constant which need not be enclosed in braces; this is the
only exception to the rule requiring braces around the list of
initializers for an aggregate.
Initializer expressions for auto objects can only be applied to
simple arithmetic or pointer types (not to aggregates), and are
entirely equivalent to assignment statements.
2.2.7 Expression Evaluation
All of the standard operators are supported by the Lattice
compiler, in the standard order of precedence (see p. 49 of
Kernighan and Ritchie). Expressions are evaluated using. an
operator precedence parsing technique which reduces complex
expressions 'to asequence of unary and binary operations
involving at most two operands. Operations involving only
2-9
Lattice 8086/8088 CCompiler Language Definition
constant operands (including floating point constants) are
evaluated by the compiler immediately, but no special effort is
made to re-order operands in order to group constants. Thus,
expressions such as
C-'A' +'a'
must be parenthesized so that the compiler can evaluate the
constant part:
C+('a' -'A')
If at least one operand in an operation is not constant, the
intermediate expression result is represented by atemporary
storage location, known as a temporary. The temporary is then
"plugged into" the larger expression and becomes an operand of
another binary or unary operation; the process continues until
the entire expression has been evaluated. The lifetimes of
temporaries and their assignment to storage locations are
determined by asubroutine internal to the first phase of the
compiler, which recognizes identically generated temporaries
within astraight-line block of code and eliminates recomputation
of equivalent results. Thus, common sub-expressions are
recognized and evaluated only once. For example, in the
statement
a[i+l] =b{i+l);
the expression i+l will be evaluated once and used for both
subscripting operations. Expressions which produce aresult that
is never used and which have no side effects, such as
i+j;
are discarded by this same subroutine.
Within the block of code examined by the temporary analysis
subroutine, operations which produce atemporary result are noted
and remembered so that later equivalent operations may be
deleted, as noted above. Two conditions (other than function
calls, which may have undetermined side effects) cause the
subroutine to discard an operation and no longer check for the
equivalent operation later: (I) if either of its operands
appears directly as a result of asubsequent operation; or (2) if
asubsequent operation defines an indirect (i.e., through a
pointer) result for the same type of object as one of the
original operands. The latter condition is based on the
compiler's assumption that pointers are always used to refer to
the correct type of target object, so that, for example, if an
assignment is made using an int pointer only objects of type int
can be changed. Only when the programmer indulges in tjLEe
punning -- using apointer to inspect an object as if it were a
different type -- is this assumption invalid, and it is hard to
conceive of acase where the common sub-expression detection will
cause aprob"1em with this somewhat dubious practice. Such
2-ID
Lattice 8086/8088 CCompiler Language Definition
inspections are generally better left to assembly language
modules in any case.
with the exception of this common sub-expression detection, which
may replace an operation with aprevious, equivalent one,
expressions ate evaluated in strict left-to-right order as they
are encountered, except, of course, where that is prevented by
operator precedence or parentheses. It is best not to make any
assumptions, however, about the order of evaluation, since the
code generation phase is generally free to re-order the sequence
of many operations. The most important exceptions are the
logical OR (||) and logical AND (&&) operators, 'for which the
language definition guarantees left-to-right evaluation. The
code generation phase may have other effects on expression
evaluation; usually, some favorable assumptions about pointer
assignments are made, though these can be shut off by acompile-
time option. Check the implementation section of this manual for
full details.
2.2.8 Control Flow
Coffers arich set of statement flow constructs, and the Lat"tice
compiler supports the full complement of them. Some minor
points of clarification are noted here. First of all, the
compiler does verify that switch statements contain (I) at least
one case entry; (2) no duplicate case values; and (3) not more
than one "default" entry. In addition, the first phase of the
compiler recognizes certain statement flow constructs involving
constant test values, and may discard certain portions of code
accordingly. (Even those portions ultimately discarded are fully
analyzed, lexically and syntactically, before being eliminated.)
If an if statement has aconstant test value, only the code for
the appropriate clause (the then or else portion) is retained;
while, do, and for statements with zero test values are entirely
.
discarded.
The code generation phase generally makes aspecial effort to
generate efficient sequences for control flow. In particular,
the size and number of branch instructions is kept to aminimum
by extensive analysis of the flow within afunction, and switch
statements are analyzed to determine the most efficient of
several possible machine language constructs. Check the
impleñentation section of this manual for the details regarding
this particular code generator.
2.3 Comparison to the Kernighan &Ritchie "C Reference Manual"
The -most precise definition of the Cprogramming language
generally available is in Appendix Aof the Kernighan and Ritchie
text, which is entitled C. Reference Manual. This section
presents, in the saíne order defined in the text, aseries of
amendments or annotations to that 'manual; this commentary
explicitly states any deviations of the Lattice Clanguage
implementation from the features described. Because this
implementation is very close to the Kernighan and Ritchie
2-ll
Lattice 8086/8088 CCompiler Language Definition
standard, many of the sections appjY exactly as written; these
sections will riot be commented upon. Any section not listed here
can be assumed to be fully valid for the language accepted by the
Lattice Ccompiler.
CRM 2.1 Colnment6
The Lattice compiler allows comments to be nested, that is,.each
/" encountered must be matched by acorresponding */ before the
comment terminates. This feature makes it easy to "comment out"
large sections of code which themselves contain comments. The c
compile-time option forces the compiler to process comments in
the standard, non-nesting mode.
2.4.3 Character constant8
Two extensions to character constants ate provided. First, more
than one character may be enclosed in single quotes; the result
may be int or long, depending on the number of characters, and
its value is machine-dependent. Second, if the first character
following the backslash in an escape sequence is x, the next one
or two digits are interpreted as ahexadecimal value. Thus,
'\xf9'
generates acharacter with the value 0XF9.
CRM 2.5 Strings
The Lattice compiler recognizes identically wíitten string
constants and oñiY generates one copy of the string. (Note that
strings used to initialize char arrays -- not char *-- are not
actually generated, because they are really just shorthand for a
comma-separated list of single-character constants.) The same \X
convention described above can be employed in strings, where it
is generally more useful.
CRM 2.6 Hardware characteristics
See the implementation section of this manual for hardware
characteristics.
CRt'l 7.1 primary expressions
The Lattice compiler always enforces the rules for the use of
structures and unions for the simple reason that it cannot
otherwise determine which list of member names is intended.
Recall from Section 2.1 that the compiler maintains aseparate
list of members for each type of structure or union. Therefore,
the primary expression preceding the .or -> operator must be
immediately recognizable as a structure or pointer to astructure
of aspecific type.
2-12
Lattice 8086/8088 CCompiler Language Definition
CRM 7.2 Unary operators
The requirement that the &operator can only be applied to an
lvalue is relaxed slightly to allow application to an array" name
(wtÜch is not considered an lvalue). Note that the meaning of
such aconstruct is apointer to the array itself, which is'quite
different from apointer to the first element of the array. The
difference between apointer to an array and to an array's first
element is only important when the pointer is used in an
expression with an int offset, because the offset must be sealed
(multiplied) by the size of the object to which the pointer
points. In this case the target object size is the size of the
whole array, rather than the size of asingle element, if the
pointer points to the array as awhole.
CRPf 7.6 Relational operators
When pointers of different types are compared, the right-hand
operand is converted to the type of the left-hand operand;
comparison of apointer and one of the integral types causes a
conversion of the integer to the pointer type. Both of these are
operations of questionable value and are certainly machine-
dependent.
CRM 7.7 Equality operators
The same conversions noted above are applied.
CRM 8.1 Storage class-specifiers
The text states that the storage class-specifier, if omitted from
adeclaration outside afunction, is taken to be extern. This is
somewhat misleading, if not plainly inaccurate; in fact (as the
text points oUt in CRM 11.2), the presence or absence of extern
is critical to determining whether an object is being defined or
referenced. As noted in Section 2.2.4 of this document, if
extern is ptesent, then the declared object either exists in some
other file or is defined later in the same file; if no storage
class specifier is present, then the declared object is being
defined and will be visible in other files. If the static
specifier is present, the object is also defined but is not made
externally visible. The only exception to these rules occurs for
functions, where it is the presence of adefining statement body
that determines whether the function is being defined.
The Lattice compiler can be forced to assume extern for all
declarations outside afunction by means of the xcompile time
option. Declarations which explicitly specify static or extern
are not affected.
CRM 8.5 Structure and union declarations
The Lattice compiler treats the names of structure members quite
differently from Kernighan and Ritchie. The names of members and
tags do not conflict with each other or with the identifiers used
2-13
Lattice 8086/8088 CCompiler Language DefinitÁon
for ordinary variables. Both structure and union tags are in the
same class of names, so that the same tag cannot be used for both
astructure and aunion. Aseparate list of members is
maintained for each structure; thus, amember name may not appear
twice in aparticular structure, but the same name may be used in
several different structures within the same scope.
CRM 8.7 Type name8
Although astructure or union may appear in atype name
specifier, it must refer to an already known tag, that is,
structure definitions cannot be wade inside atype name. Thus,
the sequence
(struct {int high, low; }*) x
is not permitted, but
struct HL {int high, low; };
OO0
(struct HL ") x
is acceptable.
CRM l0.l External function definitions
AS noted in the text, formal parameters declared float are
actually interpreted as double; similarly, formals áeclared char
or short ate read as int. For co.nsistency, the Lattice compiler
applies the same rules to functions: afunction declared to
return float is assumed to return double, and char or short
functions to return int.
CRM 10.2 External data definitions
The Lattice compiler applies asimple rule to external data
declarations: if the keyword extern is present, the actual
storage will be allocated elsewhere, and the declaration is
simply areference to it. Otherwise, it is interpreted as an
actual definition which allocates storage (unless the xoption
has been used; see the comments on CRM 8.1).
CRM 12.3 Condi-tional compilation
As noted in Section 2.2.1 of this document, the constant
expression following #if may not contain the sizeof operator, and
must appear on asingle input line.
Crm 12.4 Line control
Although the filename for #line is denoted as identifier, it need
not conform to the characteristics of Cidentifiers. The
compiler takes whatever string of characters is supplied; the
only lexical requirement for the filename is that it cannot
contain any white space.
2-14
Lattice 8086/8088 CCompiler Language Definition
CRM 14.1 Structures and unions
The escape from typing rules described in the text is explicitly
not allowed by the Lattice compiler. In areference to a
structure or union member, the name on the right must be amember
of the aggregate named or pointed to by the expression of the
left. This implementation, however, does not attempt to enforce
any restrictions on reference to union members, such as requiring
avalue to be assigned to aparticular member before allowing it
to be examined via that member.
Future versions of the compiler may support structure assignment,
but the value of other operations (such as passing aggregates
directly to or returning them from functions) seems questionable.
2~15
Lattice 8086/8088 CCompiler portable Library Functions
Section 3:
Portable Library Functions
In order to provide real portability, aCprogramming environment
must provide -- in amachine-independent way -- ñOit only awell-
defined language but alibrary of useful functions as well. The
portable library provided with the Lattice Ccompiler attempts to
fulfill this requirement. Álthough not all of the features of
these functions can be implemented on every system supported by
the compiler, all systems must be able to provide the basic
functions of memory allocation, file input/output, and ch.3racter
string manipulation; otherwise, the compiler itself could not be
implemented. An important side benefit of presenting the
functions from amachine-independent viewpoint is that it helps
the programmer think of them as such.
when referring to the function descriptions presented in this
seccion, remember that the compiler assumes that afunction will
return an int value unless it is explicitly declared otherwise.
Any function which returns any other kind of value must be
declared as that kind of function in advance of its first usage
in the same file.
3.1 Memory Allocation Functions
The standard library provides memory allocation capabilities at
several different levels. The higher level functions call the
lower levels to perform the work, but provide easier interfaces
in exchange for the extra overhead. The actual amount of memory
available is system-dependent and usually depends on the size of
the program. In most systems the memory made available' for
dynamic allocation by these functions is the same memorjj' used for
the run-time stack (used for function calls and auto variables).
On these systems adefault number of bytes is reserved for the
stack, and the remainder of the memory is used by the memory
allocation functions. In order to allow programs to adjust the
amount of memory reserved for the stack (and thus the amount
available for dynamic allocation), the main program usually
supports aspecial =n option to override the default stack size;
altermatively, aprogram may define the size internally. Check
the implementation section of the manual for details. The user
is. cautioned that o,n. many systems there ,i,s, no, check aqainst the
stack overrunninq its allotted size and destroying portions o_f,
the memory pooI.
All" of the memory allocation functions return apointer which is
of type char *, but is guaranteed to be properly aligned to store
any object.
3-I
Lattice 8086/8088 CCompiler portable Library Functions
3.1.1 Level 3Memory Allocation
The functions described in this section provide aÚNIX-compatible
memory-allocation facility. The blocks of memory obtained may br
released in any order, but it is an error to release somethinq
not obtained by calling one of these functions. Recause thcsc>
functions use overhead locations to keep track of allocation
sizes, the free function does not require asize auíument. The
overhead does, however, decrease the efficiency with which thesr·
functions use the available memory. If many small allocmtinn':
are requested, the available memory will be more efficié"ntly
utilized if the level 2functions are used instead.
3~ 2
Lattice 8086/8088 CCompiler Portable Library Functions
name
malloc -- UNIX-compatible memory allocation
SYNOPSIS
p=malloc(nbytes);
char *p; block pointer
unsigned nbytes; number of bytes requested
DESCRIPTION
Allocates ablock of memory in a way that is compatible with
UNIX. The primary difference between malloc and getmem is
that the former allocates astructure at the front of each
block. This can result in very inefficient use of memory
when making many small allocation requests.
returns
p=null if not enough space available
=pointer to block of nbytes of memory otherwise
CAUTIONS
Return value must be checked for NULL. The function should
be declared char " and acast operator used if defining a
pointer to some other kind of object, as in:
char *mal1oc();
int "pi;
0 D O
pi =(int *)malloc(N);
3-3
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
calloc -- allocate memory and clear
SYNOPSIS
p = calloc(ne1tf eltsiz);
char *p; block pointer
unsigned ne.lt; number of elements
unsigned eltsiz; element size in bytes
Allocates and clears (sets to all zeros) ablock of memory.
The size of the block is specified by the product of the two
parameters; this calling technique is obviously convenient
for allocating arrays. Typically, the second argument is a
sizeof expression.
RETURNS
p = NULL jr not enough space available
=pcñnter to block of memory otherwise
CAUTIONS
Return value must be checked for NULL. The function should
be declared char * and acast used if defining apointer to
some other kind of object, as in:
char "calloc();
struct buffer "pb;
D U e
pb =(struct buffer ")calloc(4, sizeof(struct buffer));
3-4
Lattice 8086/8088 CCompiler Portable Library Functions
name
free -- UNIX-compatible memory release function
SYNOPSIS
ret =free(cp);
int ret; return code
char *cp; block pointer
DESCRIPTION
Releases ablock of memory that was previously allocated by
malloc or calloc. The pointer should be char "and is
checked for validity; that is, verified to be an element of
the memory pool.
RETURNS
ret =0if successful
=-I if invalid block pointer
cautions
Remember to cast the pointer back to char "u as in:
char "malloc();
int "pi;
* * 0
pi =(int *) malloc(N);
P P *
if (free((char *)pi) != D) {... error ... }
3-5
P
Lattice 8086/8088 CCompiler portable Library Functions
3.1.2 Level 2Memory AlloCation
The functions described in this section provide an efficient arid
convenient memory allocation capability. Like the level 3
functions, allocation and de-allocation requests may be made in
any order, and it is an error to free memory not obtained by
means of one of these functions. The caller must retain both the
pointer and the size of the block foF use when it is freed;
failure to provide the correct length may lead to wasted memory
(the functions can detect an incorrect length when it is too
large, but not when it is too small). An additional convenience
is provided by the sizmem function, which can be used to
determine the total amount of memory available.
The level 2functions maintain alinked list of the blocks of
memory released by calls to rlsmem, called the free space list.
Initially, this list is null, and getmem acquires memory by
calling the level lmemory allocator sbrk. As blocks are
released by the program, the free space list is created; when a
block adjacent to one already on the list is freed, it is
combined with any adjacent blocks. Thus, the size of the largest
block available may be smaller than the total amount of free
memory, due to breakage.
3-6
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
getmem, getml -- get amemory block
SYNOPSIS
p=getmem(nbytes);
p=getml (lnbytes);
char "p; block pointer
unsigned nbytes; number of bytes requested
long lnbytes; long number of bytes requested
DESCRIPTION
Gets ablock of memory from the free memory pool. If the
pool is empty or ablock of the requested size is not
available, more memory is obtained via the level I function
sbrk.
RETURNS
p=null if not enough space available
=pointer to memory block otherwise
CAUTIONS
Return value must be checked for NULL. The function should
be declared char * and acast used if defining apointer to
some other kind of object, as in:
char *getmem();
struct xyz "px;
O0O
px =(struct xyz ")getmem(sizeof(struct XYZ));
3-7
Lattice 8086/8088 CCompiler Portable Library Functions
name
rlsmem, rlsml -- release amemory block
synopsis
ret =rlsmem(cp, nbytes);
ret =rlsml(cp, lnbytes);
int ret; return code
char *cp; block pointer to be freed
unsigned nbytes; size of block
long lnbytes; size of block as long integer
description
Releases the memory block by placing it on a free block
list. If the new block is adjacent to ablock on the list,
they are combined.
returns
ret =0if successful
=-I if supplied block is not obtained by getmem or
getml or if it overlaps one of the blocks on the
list
cautions
Return value should be checked for etror. If the correct
size is not supplied, the block may not be freed proDer}y.
3-8
Lattice 8086/8088 CCompiler Portable Lib'rary Functions
NAME
allmem, bldmem -- allocate level 2memory pool
SYNOPSIS
ret =allmem();
ret =bldmem(n);
int ret; return code
int n; maximum number of I kilobyte blocks
DESCRIPTION
The bldmem function uses the level 1function sbrk to
allocate up to nI kilobyte blocks of iíiemory. If nis 0,
then all availabTe memory is allocated.
The alhnem function merely calls bldmem with nset to CL
Subsequent getmem and getml calls will make allocations from
this memory pool. All of the memory allocated by getmem
calls following acall to getmem can be freed by acall to
the rstmem function described below.
RETURNS
ret =-I if first sbrk fails
=0if successful
CAUTIONS
Should be called only once during the lifetime of the
program.
3-9
Lattice 8086/8088 CCompiler portable Library Functions
NAME
sizmem -- get memory pool size
SYNOPSIS
bytes =sizmem();
long bytes; number of bytes
DESCRIPTION
Returns the number of unallocated bytes in the memory pool
used by getmern and getml. Note that getmem and getml
dynamically expand the pool by calling sbrk whenever a
request cannot be honored. Therefore, the value returned by
sizmem does not necessarily indicate how much memory is
actually available. If used after calling a.llmem, however,
the actual memory pool size will be returned.
RETURNS
bytes =(long) number of bytes in mermry pool
CAUTIONS
Note that this function returns along integer, and must be
declared long before it is used.
3-ID
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
rstmem -- reset memory pool
SYNOPSIS
rstmem();
DESCRIPTION
Resets the ,l,ey.e,l. ?memory pool to its initial state. All
memory allocated by calls to getmem and getml made after
allmem was called is released by rstmem; memory allocated
before allmem was called is not affected. This function
makes it possible to make acertain number of initial sbrk,
getmem, or getml calls, and then to initialize a memory pool
by calling allmem. Any allocations made after the call to
allmem are freed by rstmem, but the preceding sbrk or getmem
calls are not affected.
CAUTIONS
This function cannot be used if any files have been opened
after the immediately preceding allmem call for access using
any of the leve} 2I/O functions, because these functions
use getmem to allocate buffers. Files shÓuld be opened
before the allrnem call to avoid this problem.
3-ll
Lattice 8086/8088 CCompiler portable Library Functions
3.1.3 Level lMemory Allocation
The two functions defined at the lowest level of memory
allocation are primitives which perform the basic operations
needed to implement a more sophisticated facility; they are used
by the level 2functions for that purpose. sbrk treats the total
amount of memory available as a single block, from which portions
of aspecific size may be allocated at the low end, creating a
new block of smaller size. rbrk merely resets the block back to
its original size. The "break point" mentioned here shouZd not
be confused with the breakpoint concerjt used in debugging; this
-
term simply refers to the address of the low end of the block of
memory manipulated by sbrk.
3-12
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
sbrk, lsbrk -- set memory break point
SYNOPSIS
p=sbrk(nbytes);
p=lsbrk(lnbytes);
char *p; points to low allocated address
unsigned nbytes; number of bytes to be allocated
long In bytes; long number of bytes to be allocated
DESCRIPTION
Allocates ablock of memory of the requested size, if
possible. These functions form the basic UNIX memory
allocator. The first time one of them is called, it will
allocate the largest available block of high memory. Then
the requested number of bytes is subtracted from the low end
of the block for use by the caller.
returns
p=-l if request cannot be fulfilled (sbrk only)
p=0if request cannot be fulfilled (lsbrk only)
=pointer to low address of block if successful
CAUTIONS
For consistency with the UNIX function, sbrk returns -l if
it cannot satisfy the request, although the rest of the
memory allocators return NULL. Both functions should be
declared char * and acast used if defining apointer to
some other kind of object.
3-13
Lattice 8086/8088 CCompiler portable Library Functions
NAME
rbrk -- reset memory break point
SYNOPSIS
rbrk();
DESCRIPTION
Resets the memory break point to its original starting-
point. This effectively returns all memory to the free
space block.
CAUTIONS
Like rstmem above, this function cannot be used if any files
are open and being accessed using the .l.eye.l. E I/O functions.
3-14
Lattice 8086/8088 CCompiler Portable Library Functions
3.2 I/O and System Functions
The standard library provides 1,/0 functions at several different
levels, with single character 2ÉÉ and put functions and formatted
l/O at the highest levels, and direct byte stream T/Q functions
at the lowest levels. The major system dependency arises in
connection with text files, where some systems perform certain
translations to accommodate the particular text file
representation usc"d in the local environment. Although the
translation is generally transparent at the higher levels, I/O at
the lowest levels, particularly I/O involving binary data, must
be aware cjf the translation. Check the implementation section of
this manual for the details appropriate to aparticular sYstem.
Three general classes of I/O functions are provided. First, the
level 2functions define abuffered text file interface which
implements the single character I/O functions as macros rather
than function calls. Second, the level lfunctions define abyte
stream-oriented file interface, primarily useful for manipulation
of disk files, though most of the same functions are applicable
to devices (such as the user's console) as well. FinaZZy, since
one of the most common I/O interfaces is with the user's console,
aspecial set of functions allows single character T/O directly
to the user's terminal, as well as formatted and string I/O.
The system functions discussed in this section are concerned with
program exit. Additional system functions are described in the
implementation section of the manual.
3.2.1 Level 2I/O Functions and Macros
These functions provide abuffered interface using aspecial
structure, manipulated internally by the functions, to which a
pointer called the file pointer is defined. This structure is
defined in the standard I/O header file (called stdio.h on most
systems) which generally must be included (by means of a#include
statement) in the source file where .l.eye,l. 2 features are being
used. The file pointer is used to spécíÉy"the file upon which
operations are to be performed. Some functions require afile
pointer, such as
FILE "fp;
to be explicitly included in the calling sequence; others imply a
specific file pointer. In particular, the file pointers stdin
and stdout are implied by the use of several functions and
macros; these files are sci commonly used that on most gYgtems
they are opened automatically before the main function of a
program begins execution. Other file pointers must be declared
by the programmer and initialized by calls to the topen function.
The level ,2. functions are designed to work primarily with text
files. The usual Cconvention for line termination uses asingle
character, the newline (\n), to indicate the end of aline.
Unfortunately, many operating environments use a multiple
3-15
Lattice 8086/8088 CCompiler Portable Library Functions
character sequence -- usually carriage return/line feed, but
occdsionally even more exotic delimiters. In order to allow all
Cprograms to work with text files in the same way, the Lattice
functions support the standard newline convention but may --
depending on the system -- perform atext mode translation so
that end-of-line sequences will conform to local conventions.
This translation is usually beneficial and transparent but may
cause problems when working with binary files. Normally, all
files accessed through the level 2functions are opened in the
text, or translated mode, but the programmer may override this
mode by defining the external location
int _fmode =0X8000;
in one of im functions in the program (this statement must
appear outside the body of the function itself in order to be
considered an external definition). The value at fmode is
passed to the level 1function open or creat when the" file is
opened. If zero, the file is opened in the text mode; if (jx8000,
the file is opened in the binary, or untranslated mode. Note
that if fmodé is defined as above, the stdin, stdout, and stderr
files opened for the main function will áZsO be opened in the
binary mode. If this is undesirable, fmode can be initialized
with zero and then set to Gx8000 before"specific fopen calls are
made; in this way, different files may be opened in different
modes. Check the implementatior: section of this manual for more
information about the file access modes.
The actual I/O operations are petformed by the level 2functions
through calls to the level lL/O functions described in the next
section. The normal moU of buffering, designed to supDort
sequential operations, performs read and write functions in 512-
byte blocks.
Normally the ,l.ey.e_l. 2functions acquire buffers via the level 2
memory allocator unless the file is on a device other than 3
disk. Alternatively, the setbuf function allows aprivate buffer
to be attached. This function assumes that the buffer is the
standard size, which is defined via the BUFSIZ constant in
stdio.h. If for some reason operating the level 2I/O functions
in the buffered mode is not desirable, the setnbf function can be
called. This is done automatically for non-disk files or if
setbuf is called with aNULL buffer pointer.
In the descriptions below, some cjf the function calls are
actually implemented as macros; these are noted explicitly. The
reason the programmer should be aware cf the distinction is
because most macros involve the conditional operator and may,
under certain conditions, evaluate an argument expression more
than once. This can cause unexpected results if that expression
involves side effects, such as increment or decrement operators
or function calls.
3-16
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
fopen -- open abuffered file
SYNOPSIS
fp =fopen(name, mode);
FILE "fp; file pointer for specified file
char "name; file name
char "mode; access mode
DESCRIPTION
Opens afile for buffered access; the translated mode is the
default mode but may be overridden as described in the
introduction to this section. The NULL-terminated string
which specifies the filename must conform to local file
naming conventions. The access mode is also specified as a
string, and may be one of the following:
rto read afile
wto write afile
ato append to afile
r+ to update afile (read and write)
w+ to create afile for update
a+ to append to and update afile
The mode character must be specified in lower case. The a
option adds to the end of an existing file, or creates a new
one; the woption discards any data in the file, if it
already exists. On most systems, no more than 16 files
(including stdin, stdout, and stderr, if those are opened
for main) can be opened using fopen.
When afile is opened for update, both reading and writing
may be performed on the file pointer. In order to switch
modes, an fseek or rewind must be executed. Opening the
file to append forces all data to be written to the current
end of file, regardless of previous seeks.
RETURNS
"fp =NULL if error
=file pointer for specified file if successful
CAUTIONS
The return code must be checked for NULL; the error return
may be generated if an invalid mode was specified or if the
file was not found, could not be created, or too many files
were already open.
3-17
Lattice 8086/8088 CCompiler Portable í,ibrary Functions
NAME
freopen -- reopen abuffered file
SYNOPSIS
fpr *freopen(name, mode, fp);
FILE *fpr; file pointer after re-opening
char *name; file name
char *mode; access mode
FILE *fp; current file pointer
DESCRIPTION
Reopens abuffered file; that is, attaches a new file to a
previously used file pointer. This function is useful for
programs which must open several files, but only one at a
time; this avoids using up file pointers unnecessarily. The
previous file is automatically closed before the file
pointer is reused. The name and mode arguments are the same
as those for fopen.
RETURNS
fpr =NULL if error
=fp'if successful
CAUTIONS
TPie return code should be checked for NULL; the same errors
defined for fopen may occur.
3-18
t*
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
fclose -- close abuffered file
SYNOPSIS
ret =fclose(fp);
int ret; return code
FILE "fp; fike pointer for file to be closed
DESCRIPTION
Completes the processing of afile and releases all related
resources. If the file was being written, any data which
has accumulated in the buffer is written to the file, and
the level I close function is called for the associated file
descriptor. The buffer associated with the file block is
freed. fclose is automatically called for all open files
when aprogram calls the exit function (see Section 3.2.4)
or when the main program returns, but it is good programming
practice to close files explicitly. As the last buffer is
not written until fclose is called, data may be lost if an
output file is not properly closed.
RETURNS
ret =—I if error
=0if successful
3-19
Lattice 8986/8088 CCompiler Portable Library Functions
NAME
gete, getchar -- get character from file
SYNOPSIS
c=getc(fp);
c = getchar();
int c; next input character or EOF
FILE "fp; file pointer
DESCRIPTION
Gets the next character from the indicated file (stdin, in
the case of getchar). The value EOF (-I) is returned on
end—of-file or error.
RETURNS
c=character
=eoe if end-of-file or error
CAUTIONS
These are implemented as macros, so beware of side effects.
3-20
Lattice 8086/8088 CCompiler portable Library Functions
NAME
putc, putchar -- put- i'"hírí('"t("r to flit"'
SYNOPSIS
r=putc(c, fp);
r=putchar(c);
int r; same ass character SÉ'ñt, nr prr()r í""odé
char c; charaí"ter to Y)("? output
FILE "fp; file pointer
DESCRIPTION
E'u tsthecharacter to the indicated file (stdout, inrPip
case tjf putchar) .The va 1(1€" EOF (-I) is rett.irned on ond-nS-
file or error.
RETURNS
r=character sent if successful
=eof if error or end-of-file
CAUTIONS
These are implemented as macros, so beware of sick' rffec"ts.
3-21
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
fgetc, fputc -- get/put acharacter
SYNOPSIS
G
r=fgetc(fp);
r=fputc(c, fp);
int r; return character or code
char c; character to be sent (fputc)
FILE *fp; file pointer
DESCRIPTION
These fjmctions get (fgetc) or put (fputc) asingle
character to the indicated file. Since they are functions,
they are often recommended for use rather than the
corresponding macros (getc and putc) in two types of
situations: (I) if many calls are made and/or (2) if the
programmer is concerned about the amount of memory used in
the macr,o expansions. The tradeoff is the usual one: the
macro executes more quickly because it saves afunction
call; the function requires less memory since its code is
present in the program only once.
RETURNS
r=character if successful (c, for fputc)
=eof if error or end-of-file
3-22
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
ungetc -- push character back on input file
SYNOPSIS
r=ungetc(c, fp);
int r; return character or code
char c; character to be pushed back
FILE "fp; file pointer
DESCRIPTION
Pushes back acharacter to the specified input file. The
character supplied must be the character most recently
obtained by agetc (or getchar, in which case fp should be
supplied as stdin) invocation.
RETURNS
r=character if successful
=EOF if previous character does not match
3-23
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
fread, fwrite -- read/write blocks of data from/to afile
SYNOPSIS
naet =fread(p, s, n, fp);
nact =fwrite(p, s, n, fp);
int nact; actual number of blocks read or written
char *p; pointer to first block of data
int s; size of each block, in bytes
int n; number of blocks to be read or written
FILE *fp; file pointer
DESCRIPTION
These functions read (fread) or write (fwrite) blocks of
data írom or to the specified file. Each block is of size s
by t£?s; blocks statt at dand are stored contiguously f rom
A—
that location. nspecif les the number of blocks (of size s)
that are to be read or wrntten.
RETURNS
rjgo t=actual number of blocks (c)fsize S) read or written;
may be less than nif error or end-cf-tile occerte"í
CAUTIONS
Return va lúe mu s tbe checked to verify that thecorrect
number of blocks was processed. The ferror and feof macros
ca nbe used to determine the cause if the return value is
less than n.
3-24
Lattice 8086/8088 CCompiler Portable Library Functions
name
gets, fgets -- get astring
SYNOPSIS
p=gets(s);
p=fgets(s, n, fp);
char "p; returned string pointer
chat 's; buffer for input string
int n; number of bytes in baffler
FILE *fp; file pointer
DESCRIPTION
Gets an input string from afile. The specified file
(stdin, in the case of gets) is read until anewline is
encountered or n-l characters have been read (fgets only)-
Then, gets replaces the newline with aNULL byte, whi)e
fgets passes the newline through with aNULL byte appended.
RETURNS
p=NULL if end of file or error
= s if successful
CAUTIONS
For gets, there is no length parameter, so the input
buffer must be large enough to accommodate the string.
3-25
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
puts, fputs -- put astring
SYNOPSIS
r=puts(s);
r=fputs(s, fp);
int r; return code
char *s; output string pointer
FILE "fp; file pointer
DESCRIPTION
Puts an output string to afile. Characters from the"string
are written to the specified file (stdout, in the case of
puts) until aNULL byte is encountered. The NULL byte is
not written, but puts appends anewline.
RETURNS
r=EOF if end-of-file or error
3-26
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
scanf, fscanf, sscanf -- perform formatted input conversions
SYNOPSIS
n=scanf(cs, ...ptrs...);
n=fscanf(fp, cs, ...ptrs...);
n=sscanf(ss, cs, ...ptrs...);
int n; number of input items matched, or EOF
FILE *fp; file pointer (fscanf only)
char *ss; input string (sscanf only)
char "cs; format control string
---- ...ptrs...; pointers for return of input values
DESCRIPTION
These functions perform formatted input conversions on text
obtained from three types of files:
L) the stdin file (scanf);
2) the specified file (fmanf);
3) the specified string (sscanf).
The control string contains format specifiers and/or
characters to be matched from the input; the list of pointer
arguments specify where the results of the conversions are
to go. Format specifiers are of the form
B("]{rÍ](llX
where
I) the optional "means that the conversion is to be
performed, but the result value not returned;
2) the optional ,n. is adecimal number specifying amaximum
field width;
3) the optiona! I(e,l.) is used to indicate a,lgng int or
lorg float (í.e., double) result is desired; ""'
4) Xis one of the format type indicators from the
following list:
d-- decimal integer
o-- octal integer
x-- hexadecimal integer
h-- short integer
c-- single character
s-- character string
f-- floating point number
The format type must be specified in lower case. white
space characters in the control string are ignored;
characters other than format specifiers are expected to
match the next non-white space characters in the input. The
3-27
Lattice 8086/8088 CCompiler portable Library Functions
input is scanned through white space to loccíté the next
input item in all cases except the cspecifier, where the
next input character is returned without this initial scan.
See the Kernighan and Ritchie text for a more detailed
explanation of the formatted input functions.
RETURNS
n=number of input items successfully matched, i.e., for
which valid text data was found; this includes all
single character items in the control string
=E.O.F. if end-of-file or error is encountered during scan
CAUTIONS
All of the input values must be pointers to the result
locations. Make sure that the format specifiets match up
properly with the result locations. If the assignment
suppression feature (") is used, remember that apointer
must not be supplied for that specifier.
3-28
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
printf, fprintf, sprintf -- genetate formatted output
SYNOPSIS
printf(cs, ..-arqs...);
fprintf(fp, cs, ...args.-.);
n = sprintf(ds, cs, ...args...);
int n; number of characters (spíintf only)
FILE *fp; file pointer (fprintf)
char "ds; destination string pointer {sprintf)
char *cs; format control string
---- ...args...; list of arguments to be formatted
DESCRIPTION
Tbese functions perform formatted output conversions and
send the resulting text to:
I) the stdout file (printf);
2) the specified file (fprintf); or
3) the specified output string (sprintf).
The control string contains ordinary characters, which are
sent without modification to the appropriate output, and
format specifiers of the form
%[-][m][.p)[l]X
where
l) the optional -indicates the field is to be left
justified (right justified is the default);
2) the optional mfield is adecimal number specifying a
minimum field width;
3) the optional :£field is the character .followed by a
decimal number specifying the precision"of afloating
point image or the maximum number of characters to be
printed from astring;
4) the optional l (el) indicates that the item to be
formatted is io6g; and
5) Xis one of the format type indicators from the
Íollowing list:
d-- decimal signed integer
u-- decimal unsigned integer
x-- hexadecimal integer
o-- octal integer
s-- character string
c-- single character
f-- fixed decimal floating point
e-- exponential floating point
g-- use e or fformat, whichever is shorter
3-29
Lattice 8086/8088 CCompiler Portable Library Functions
The format type must be specified in lower case. Characters
in the control string which ate not part of aformat
specifier are sent to the appropriate output; a*may be
sent by using the sequence u. See the Kernighan and
Ritchie text for amote detailed explanation of the
formatted output functions.
RETURNS
n=number of characters placed in ds (sprintf only), not
including the NULL byte terminator
CAUTIONS
For sprintf, no check of the size of the output string area
is made, so it must be large enough to contain the resulting
image. In all cases, the format specifiers must match up
properly with the supplied values for formatting.
3-30
Lattice 8086/8088 CCompiler portable Library Functions
NAME
fseek --- seek to a new fiIp posit iíjn
SYNOPSIS
ret =fseek (fp, pos, mode) ;
int ret; return code
FILE "fp; file pointer
long pos; desired file position
int mode; of fset mode
DESCRIPTION
Seek sto a new position in the specified fi le. See the
lseek function description (Section 3.2.2) for the meaninq
of the of fset mode argument.
RETURNS
re t=0if successful
=-lif error
CAUTIONS
1fm,ode !is specified, the file position established f or
fiíe9" be ing accessed i nthe translated mode may be
incorrect.
4
3-31
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
ftell -- return current file position
SYNOPSIS
pos =fte"1l(fp);
long pos; current file position
FILE *fp; file pointer
DESCRIPTION
Returns the currient file position, that is, the number of
bytes from the beginning of the file to the byte at which
the next read or write operation will transfer data.
RETURNS
pos =current file position (long)
CAUTIONS
'I'híú f i Le p'j'íitio!1 returned takes account Mthe buffering
used ci"! the ti2c: ,-sr the file position retutmed is alogic"a]
f i it? positzot: rather than the actual position. Note tha l-
Le xtmode transZation may cause an incorrect fi le posit.ion
!:ube tetut"neci, since the nurnbeí of characters in the buf fer
isnot r)ec¿!ssari iy the number that will he actmally read or
written because of the translation.
3- 32
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
ferror, feof -- check if error/end of file
SYNOPSIS
ret =feof(fp);
ret =ferror(fp);
int ret; return code
FILE *fp; file pointer
DESCRIPTION
These macros generate anon-zero value if the indicated
condition is true for the specified file.
RETURNS
ret =non-zero if error (ferror) or end of file (feof)
=zero if not
3-33
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
clrerr -- 'clear error flag for file
SYNOPSIS
clrerr(fp);
FILE "fp; file pointer
DESCRIPTION
Clears the error flag for the specified file. Once set, the
flag will remain set, forcing EOE returns for functions on
the file, until this function is called.
3-34
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
fileno -- return file number for file pointer
SYNOPSIS
fn =fileno(fp);
int fn; file number associated with file pointer
FILE *fp; file pointer
DESCRIPTION
Returns the file number, used for the level lI/O calls, for
the specified file pointer.
RETURNS
fn =file number (file desc;riptor) for level ,1 calls
CAUTIONS
Implemented as a macro.
U+ 3 5
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
rewind -- rewind afile
SYNOPSIS
rewind(fp);
FILE "fp; file pointer
DESCRIPTION
Resets the file position of the specified file to the
beginning of the file.
CAUTIONS
Implemented as a macro.
3-36
Lattice 8086/80R9 CCompiler Portable Library Functions
NAME
fflush -- flush output buffer for file
SYNOPSIS
fflush(fp);
FILE *fp; file pointer
DESCRIPTION
Flushes the output buffer of the specified file, that is,
forces it to be written.
CAUTIONS
This macro must be used only on files which have been opened
for writing or appending.
3_37
Lattice 8086/8088 CCompiler portable Library Functions
NAME
setbuf -- change buffer for level 2file I/O
SYNOPSIS
setbuf(fd,buf);
FILE "fd;
char "buf;
DESCRIPTION
This function attaches aprivate buffer to the file whose
descriptor is fd. The length of the buffer is assumed to be
the same as bufsiz, which is defaulted to the constant
BUFSIZ in stdio.h..
If the buffer pointer is NULL, then this function is the
same as setnbf.
CAUTIONS
buf must be large enough to handle the data specified in
bufsiz.
3-38
Lattice 80'86/8088 CCompiler Portable Library Functions
NAME
setnbf -- set file unbuffered
SYNOPSIS
setnbf(fp);
FILE *fp; file pointer
DESCRIPTION
Changes the buffering mode for the specified file pointer
from the default SH-byte block mode to the unbuffered mode
used for devices (including the user's console). In this
mode, read and write oDerations are performed using single
characters.
CAUTIONS
Although the unbuffered mode may be used without difficulty
on files, the standard buffering mode is generally more
efficient, so this function should only be used for those
"files" which are definitely known to be devices.
3-39
Lattice 8086/8088 CCompiler Portable Library Functions
3.2.2 Level II/O Functions
These functions provide abasic, low-level I/O interface which
allows afile to be viewed as a stream of randomly addressable
bytes. Operations are performed on the file using the functions
described in this section; the file is specified by afile number
or file <iescriptor, such as
int fd;
which is returned by open or creat when the file is opened. Data
may be read or written in blocks of any size, from asingle byte
to as much as several kilobytes in asingle operation. The
concept of afile position is key: the file position is along
integer, such as
long fpos;
which specifies the position of abyte in the file as the number
of bytes from the beginning of the file to that particular byte.
Thus, the first byte in the file is at file position DL. Two
distinct file positions are maintained internally by the level I
functions. The current file position is the point at which data
transfers take place between the program and the file; it is set
to zero when the file is opened, and is advanced by the number of
bytes read or written using the read and write functions. The
end of file position is simply the total number of bytes
contained in the file; it is changed only by write operations
which increase the size of the file.
The current file position can be set to any value from zero up to
and including the end of file position using the lseek function.
Thus, to append data to afile, the current file position is set
to the end of the file using lseek before any write operations
are performed. When data is read from near the end of file, as
much of the reqoested count as can be satisfied is returned; zero
is returned for attempts to read when the file position is at the
end of file.
The level I functions operate in one of two mutually exclusive
modes: the text or translated mode, and the binar¥ or
untranslated mode. On some systems the two modes are iderjtIca1.
The desired mode is specified when the file is opened or created,
and remains in effect until the file is closed. The two modes
are provided so that any required translation of text file end-
of-line sequences can be performed automatically even by the
lowest level operations (read and write functions), while at the
same time aprogram may disable the translation, as needed, when
working with binary files. The problem is that not all systems
use the standard Cend-of-line delimiter, the newline (\n); the
translated mode converts the newline to whatever the local
delimiter may be. Since this may involve expansion or
contraction of the number of bytes read or written, the count
returned by read or write may not correctly reflect the actual
change in the file position. In the binary mode, this problem
3-40
Lattice 8086/8088 CCompiler Portable Library Functions
does not occur since no translation is performed.
apublic sj'mbol called iomode presets the translation mode.
Normally, iomode is 0 and translated mode is used unless 0RAW
is specified (see open function). If iomode is changed" to
0X8000, then the untranslated mode is used unless 0RAW is
specified. In other words, 0RAW toggles the meaning of "iomode.
Although the level Ifunctions are primarily useful for working
with files, they can be used to read and write data to devices
(including the user's terminal), as well. The exact nature of
the I/O performed is system-dependent, but it is generally
unbuffered and may have different effects, dependinq on whether
the translated or untranslated mode is in effect. The lseek
function has no effect on devices, and usually returns an error
status. Direct I/O to the user's terminal may also be performed
using the functions described in Section 3.2.3.
The actual I/O operations on disk files are buffered, but at a
level that is generally transparent to the programmer. The
buffering makes close operations anecessity for files that are
modified.
3-41
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
open -- open afile
SYNOPSIS
file =open(name, rwmode);
.int file; file number or error code
char *name; file name
int mode; indicates read/write mode and other
options (see below)
DESCRIPTION
Opens afile for access using the .l.e.v.e,l. I I/O functions.
The file name must conform to local naming conventions. The
mode word indicates the type of I/O which will be performed
on the file. The header file fnctl.h defines the codes for
the mode arguments:
0 RDONLY Read only access
0WRONLY Write only access
0RDWR Read/write access
Also, the following flags can be oRed into the above codes:
0CREAT Create the file if it doesn't exist
0 TRUNC Truncate (set to zero length) the file
if it does exist
0EXCL Forces create to fail if file exists
0APPEND Seek to end-of-file before each write
0RAW Use untranslated I/O (see introduction
to section 3.2.2)
The current file position is set to zero if the file is
successfully opened. On most systems, no more than 16 files
(including any which are being accessed through the level .2,
functions, such as stdin, stdout, etc.) can be open at the
same time. Closing the file releases the file number for
use with some other file.
RETURNS
file =file number to access file, if successful
=—l if error
CAUTIONS
Check the return value for error.
3-42
Lattice 8086/8088 ccompiler Portable Library Functions
NAME
creat -- create anew file
SYNOPSIS
file =creat(name, pmode);
int file; file number or error code
char "name; file name
int pmode; access privilege mode bits; bit Z5 has
same meaning as for open
DESCRIPTION
Creates anew file with the specified name and prepares it
for access via the level 1I/O functions. The file name
must conform to local naming conventions. Creating adevice
is equivalent to opening it. The access privilege mode bits
are system-dependent and on some systems may be largely
ignored; however, bit 15 is interpreted in the same way as
for open: if set, operations are performed on the file
without translation. If the file already exists, its
contents are discarded. The current file position and the
end-of-file are both zero (indicating an empty file) if the
function is successful.
RETURNS
file =file number to access file, if successful
=—I iferror
CAUTIONS
Check the return value for error. creat should be used only
on files which are being completely rewritten, since any
existing data is lost.
3-43
Lattice 8086/8088 CCompiler portable Library Functions
NAME
unlink -- remove file name from file system
SYNOPSIS
ret =unlink(name);
int ret; return code: 0if successful
char *name; name of file to be removed
DESCRIPTION
Removes the specified file from the file system. The file
name must conform to local naming conventions. The
specified file must not be currently open. All data in the
file is lost.
RETURNS
ret =0if successful
=-l if error
CAUTIONS
Should be used with care since the file, once removed, is
generally irretrievable.
3-44
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
read -- read data from file
SYNOPSIS
status =read(file, buffer, length);
int status; status code or actual length
int file; file number for file
char *buffer; input buffer
int length; number of bytes requested
DESCRIPTION
Reads the next set of bytes from afile. The return count
is always equal to the number of bytes placed in the buffer
and will never exceed the lenqth parameter, except in the
case of an error, where -l is returned. The file position
is advanced accordingly.
RETURNS
status =0if end-of-file
=-I if error occurred
=number of bytes actually read, otherwise
CAUTIONS
If fewer than the requested number of bytes remain between
the current file position and the end-of-file, only' that
number is transferred and returned. The number of bytµs by
which the file position was advanced may not equal the
number of bytes transferred if text mode translation
occurred.
3-45
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
write —- write data to file
SYNOPSIS
status =write(fi1e, buffer, length);
int status; status code or actual length
int file; file number
char "buffer; output buffer
int length; number of bytes in buffer
DESCRIPTION
Writes the next set of bytes to afile. The return count is
equal to the number of bytes written, unless an error
occurred. The file position is advanced accordingly.
RETURNS
status =-I if error
=number of bytes actually written
CAUTIONS
The number of bytes written may be less tban the supplied
count if aphysical end-of-file limitation was encountered.
3-46
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
lseek -- seek to specified file position
SYNOPSIS
pos =lseek(file, offset, mode);
long pos; returned file position or error code
int file; file number for file
long offset; desired position
int mode; offset mode:
0=relative to beginning "of file
I=relative to current file position
2=relative to end-of-file
DESCRIPTION
Changes the current file position to a new position in the
file. The. offset is specified as a long int and is added to
the current position (mode I) or to the logical end-of-file
(mode 2). Not all implementations support offset mode 2.
RETURNS
pos =-li if error occurred
=new file position if successful
CAUTIONS
The offset parameter must be along quantity; therefore a
long constant should be indicated when supplying azero. In
most cases, the return code should be checked for error,
which indicates that an invalid file position (beyond the
end-of-file) was specified. Note that the current file
position may be obtained by
long cpos, lseek();
0 0 0
cpos =lseek(file, DL, I);
which will never return an error code.
3-47
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
close -- close afile
SYNOPSIS
status =close(file);
int status; status code: 0if successful
int file; file number
DESCRIPTION
Closes afile and frees the file number for use in accessing
another file. Any buffers allocated when the file was
opened are released.
RETURNS
status =0if successful
=—l if error
CAUTIONS
This function must be called if the file was modified;
otherwise, the end-of-file and the actual data on disk may
not be updated properly.
3-48
Lattice 8086/8088 CCompiler Portable Library Functions
3.2.3 Direct Console I/O Functions
These functions provide adirect I/O interface to the user's
console. Because there is no buffering of characters, the
functions are particularly useful for applications which use
cursor positioning to define special screen formats or which
implement special single character responses to program prompts.
In order to distinguish these functions from the corresponding
level 2functions, different names are used for them. This
allows programs to make use of both kinds of I/O, if desired.
Programs which perform console I/O exclusively' can use the
#define mechanism to establish the following equivalencies for
some of the level 2functions:
4define getchar getch
#define putchar putch
tdefine gets cgets
#define puts cputs
tdefine 8canf cscanf
#define printf cprintf
Several system dependencies arise in connection with the direct
console functions. whether or not characters are echoed as they
are input is system-dependent but there is usually amechanism to
enable or disable the echo. On some systems the characters that
are typed when the program is not actually waiting for input are
saved, and then presented to the getch function when it requests
input. Often only one character is saved; however some sYstems
may save none while others retain several. The presence of type-
ahead, as this feature is usually called, rarely affects the
program itself, although its absence may be asource of
irritation to users who have to communicate with the program.
3—49
Lattice 8086/8088 CCompiler Portable Íjibrary Functions
NAME
geteh, putch -- get/put character directly from/to console
SYNOPSIS
c = getch();
putch(c);
int c; character received/sent to console
DESCRIPTION
These functions get (getch) or put (putcb) single characters
from or to the user's console.
RETURNS
c = character received (getch)
CAUTIONS
There is no notion of an end of file or error status, but
some implementions may use .E.O.F (-I) as an error return.
3-50
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
ungetch -- push character back tQ console
SYNOPSIS
r=ungetch(c);
int r; return code
char c; character to be pushed back
DESCRIPTION
pushes the indicated character back on the console. Only
one character of pushback is allowed. The effect is to
cause getch to return the pushed-back character next time it
is called.
RETURNS
r=EOF if acharacter has already been pushed back
=cif successful
3—51
Lattice 8086/8088 CCompiler Portable Ubrary' Functions
NAME
kbhit -- ch,eck for keyboard hit
SYNOPSIS
hit =kbhit();
int hit; 0if no hit
DESCRIPTION
Returns anon-zero value if akeyboard character is
available.
RETURNS
hit =0if no character available
"non-zero if character available
3-52
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
cgets -- get string directly from console
SYNOPSIS
p=cgets(s);
char "p; returned string pointer
char *s; input string buffer
DESCRIPTION
Gets astring directly from the user's console. Characters
are input until asystem-dependent terminator (usually CR,
0: x0D) is encountered. The carriage return is replaced by a
null byte.
RETURNS
p=pointer to string received, which does not include the
terminating carriage return
CAUTIONS
Cbeck the implementation section of this manual for details
of the operation of this function.
3-53
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
cputs -- put string directly to console
SYNOPSIS
cputs(s);
char *s; string to be output
DESCRIPTION
Puts aNULL terminated string directly to the user's
console. Does not automatically generate acarriage return
or linefeed.
3—54
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
cscanf, cprintf -- formatted I/O directly to console
SYNOPSIS
same as scanf and printf
DESCRIPTION
These functions perform the equivalent of scanf and
printf, but characters are sent directly to or received
directly from the console.
RETURNS
n=number of input items matched (cscanf)
CAUTIONS
cscanf performs its I/O directly using getch, so there are
none of the usual input conveniences such as back spacing or
line deletion. If an implementation's version of cgets
provides some of these conveniences, it may be better to
call cgets and then use sscanf to decode the resulting
string.
3-55
Lattice 8086/8088 CCompiler Portable Library Functions
3.2.4 Program Exit Functions
The program entry mechanism, that is, the means by which the
main function gains control, is sufficiently system-dependent
that it must be described in the implementation section of this
manual. program exit, however, is somewhat more general,
although not without its own implementation dependencies.
The simplest way to terminate execution of aCprogram is
for the main function to execute areturn statement, or -- even
simpler -- to "drop through" its terminating brace. In many
cases, however, amore flexible program exit capability is
needed; this is provided by the exit and exit functions
described in this section. They offer the advanfage of allowing
any function -- not just main -- to cause termination of the
program, and in some systems, they allow information to be passed
to other programs.
3—56
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
exit -- terminate execution of program and close files
3YNOPSIS
exit(errcode);
int errcode; exit error code
DESCRIPTION
Terminates execution of the current program, but first
closes all output files which are currently open through the
level .2, I/O functions. The error code is normally set to
zero to indicate no error, and to anon-zero value if some
kind of error exit was taken.
CAUTIONS
Note that exit only closes those files which are being
accessed using the level 2functions. Files accessed using
the .l.e.vel !, functions are not automatically closed.
g
3-57
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
_exit -- terminate execution immediately
SYNOPSIS
exit(errcode);
int errcode; exit error code
DESCRIPTION
Terminates execution of the current program immediately,
without checking for open files.
3-58
Lattice 8086/8088 CCompil{E'hr portable Library Functions
3.3Utility Functions and Macros
The' p{}rt.lt)lf" líbt.iry !)r{)L'!: it"s 'l v,3ri+'ty of' .?d(lit.inn,ll furic: tions
us,' t"uIfnt in...jñY of the cummcm cÍjt'.3 maniF)u|atI(jns y'r formt'd by c
pr'-"jr 'gms. 1'hrT!t? uril Jtie'Á pr'}Ui{.j(." fíxt mt"mnry tr.-3nsft'r: ;; aSat
4)fmrgÍ"l'OS .íllow'; q\ji(-"k tt'St in'; of ch,iracte'r typr's; and several
utiLíty {unc'tluns f3("Ilit-fít." ("h,lr3{"t.er string h-3nd1in('1.
3.3.IMemory Utilities
The throe utility funut ions "jescr íbed here í'l r e usually
implemented in machim·' l.'m'jaa'je fcjr m.íximum t.'f f iciency'. These
.j retht' cqulÜalt?nt Qt the nlmost \.)ni'/Arsa| Fj.[;[. and M_()V,F
subrout im's dt.'f'int"d in many othRr ianquaqt's.
3-59
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
setmem -- initialize memory to specified char value
SYNOPSIS
setmem(p, n, c);
char *p; bage of memory to be initialized
unsigned n; number of bytes to be initialized
char c; initialization value
DESCRIPTION
Sets the specified number of bytes of memory to the
specified byte value. On many sYstems ahardware block fill
instruction is used to perform the initialization. This
function is useful for the initialization of auto char
arrays.
CAUTIONS
Some systems may distinguish between char " pointers and
pointers of other types, so it is good practice to use a
cast operator when arrays or pointers of other types are
used for the pargument.
3-60
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
movmem -- move ablock of memory
WNOPSIS
m<jvíñem(s, d, n);
char "s; source memory block
char "d; destination memory block
unsigned n; number of bytes to be transferred
DESCRIPTION
Moves memory "-m one location to another. The function
checks the relative locations of source and destination
blocks, and performs the move in the order necessary to
preserve the data in the event of overlap. On many systems
ahardware .b.l.ock m.gy.e instruction is used to perform the
transfer.
CAUTIONS
Some systems may distinguish between char *pointers and
pointers of other types, sc) it is good practice to use a
cast operator when arrays or pointers of other types are
used for the sand d arguments.
3-61
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
repmem -- replicate values thrcugh memory
SYNOPSIS
repmem(s, v, lv, nv);
char "s; memory to be initialized
char "v; template of values to be replicated
int lv; number of bytes in template
int nv; number of templates to be replicated
DESCRIPTION
Replicates aset of values throughout ablock of memory.
This function is ageneralized version of setmem, and can be
used to initialize atrays of items other than char. Note
that the replication count indicates the number of copies of
vwhich are to be made, ñQt the total number of bytes to be
initialized.
CAUTIONS
Some sYstems may distinguish between char " pointers and
other types of pointers, 90 it is good practice to use a
cast operator when arrays or pointers of other types are
used for the sand varguments.
3-.62
Lattice 8086/8088 CCompiler Portable Library Functions
3.3.2 Character Type Macros
The character type header file, caLÉed ctype.h on most systems,
defines several macros which are useful in the analysis of text
dátcí. Most allow the programmer to determine quickly the type of
acharacter, i.e., whether it is alphabetic, numeric,
punctuation, etc. These macros refer to an external array called
ctype which is indexed by the character itself, so they are
generally much faster than functions which check the character
against arange or discrete list of values. Although ASCII is
defined as a7-bit code, the ctype array is defined to be 257
bytes long so that valid results are obtained for any character
value. This means that acharacter with the value 0xbl, for
instance, will be classified the same as acharacter with the
vaije 0x3l. Programs that need to distinguish between these
values must test for the 0x8(j bit before using one of these
macros. Note that ctype is actually indexed by the character
value Ejjj± one; ttñs allows the standard EOF value (-I) to be
tested in amacro without yielding anonsense result. EOF j'ields
azero result for any of the macros: it is not defined as any of
the character types.
Here are the macros defined in the character type header file
ctype.h. Note that many of these will evaluate argument
expressions more than once, so beware of using expressions with
side effects, such as function calls or increment or decrement
operators. Note that the file ctype.h must be included if any of
these macros are used; otherwise, the compiler will generate a
reference to afunction of the same name.
isalpha(c) non-zero if cis alphabetic, 0if not
isupper(c) non-zero if cis upper case, 0if not
islower(c) non-zero if cis lower case, 0if not
isdigit(c) non-zero if cis adigit 0-9, 0if not
isxdigit(c) non-zero if cis ahexadecimal digit, 0
if not (0-9, a-f, a-f)
isspace(c) non-zero if cis white space, 0if not
ispunct(c) non-zero if cis punctuation, 0if not
isalnum(c) non-zero if cis alphabetic or digit
isprint(c) non-zero if cis printable (including
blank)
isgraph(c) non-zero if cis graphic (excluding
blank)
iscntr1(c) non-zero if cis coÍjtroi character
isascii(c) non-zero if cis ASCII (0-127)
iscsym(c) non-zero if valid character for C
identifier, 0if not
iscsymf(c) non-zero if valid firgt character for C
identifier, 0if not
toupper(c) converts cto upper case, if lower case
tolower(c) converts cto lower case, if upper case
Note that the last two macros generate the value of cunchanged
if it does not qualify for the conversion.
3—63
Lattice 8086/8088 Ccompiler portable Library Functions
3.3.3 String Utility Functions
The portable library provides several functions to perform many
of the most common string manipulations. These functions all
work with sequences of characters terminated by aNULL (zero)
byte, which is the Cdefinition of acharacter string. Aspecial
naming convention is used, which works as follows: The first two
characters of astring function are always st, while the third
character indicates the type of the return value from the
function:
stc function returns an int count
stp function returns acharacter pointer
sts functioD returns an int status value
Thus, the name of the function shows at aglance the type of
value it returns.
For compatibility with other Cimplementations, four of the most
common functions are provided with stt names; these are the
functions mentioned in Kernighan and Ritchie: strlen, strcpy,
strcat, and strcmp.
3-64
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
sErien, stclen -- measure length of string
SYNOPSIS
length =strlen(s);
length =stclen(s);
int length; number of bytes in s(before NULL)
DESCRIPTION
Counts the number of bytes in sbefore the NULL terminator.
The terminator itself is not included in the count.
RETURNS
length =number of bytes in string before NULL, byte
3-65
Lattice 8086/8088 CCompiler portable Library Functions
NAME
strepy, stccpy -- copy one string to another
SYNOPSIS
strcpy(to, from);
actual =stccpy(to, from, length);
int actual; actual number of characters moved
(stccpy only)
char *to; destination string pointet
char *from; source string pointer
int length; sizeof(to) (stccpy only)
DESCRIPTION
Moves the NULL-terminateci source string to the destination
string. strcpy does not get alength parameter, so all of
the source string is copied unconditionally. For stccpy, if
the source is too long for the destination, its rightmost
characters are not moved. The destination string is always
NliLL-terminated.
RETURNS
actual "actual number of characters moved, including the
NULL terminator (stccpy only)
CAUTIONS
As noted above, strcpy does not get alength parameter, so
the destination st.ring must be latge enough. Use stccpy
it this causes problems.
3-66
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
strcat -- concatenate strings
SYNOPSIS
strcat(to, from);
char *to; string to be concatenated to
char *from; string to be added
DESCRIPTION
Concatenates from to the end of to. The result is always
NULL-terminated.
CAUTIONS
No Length parameter is present, so the destination string
must be large enough to receive the combined result.
3-67
Lattice 8086/8088 CCompiler portable Library Functions
NAME
strcmp, stscmp -- compare two strings
SYNOPSIS
status =strcmp(s, t);
status =stscmp(s, t);
int 8tatus; result of comparison
>0 if s>t, 0if s==t, <0 if s<t
char "S; first string to compare
char *t; second string to compare
DESCRIPTION
Compares two NULL-terminated strings, byte by byte, and
returns an int status indicating the result of the
comparison. If zero, the strings are identical, up to and
including the terminating byte. If non-zero, the status
indicates the result of the comparison of the first pait of
bytes which were not equal.
RETURNS
status =0if strings match
<0it first string less than second string
>0if first string greater than second string
CAUTIONS
The result of the comparison may depend on whether
characters are considered signed, if any of the characters
is greater than 127.
3-68
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
stcu d-- convert unsigned integer to decimal string *
SYNOPSIS
length =stcu d(out, in, outlen);
int length; output string length (excluding NULL)
char *out; output string
unsigned in; input value
int outlen; sizeof(out)
DESCRIPTION
Converts an unsigned integer into astring of decimal digits
terminated with aNULL byte. Leading zeros are not copied
to the output string, and if the input value is zero, only a
single 0character is produced.
RETURNS
length =number of characters placed in output string, not
including the NULL terminator
CAUTIONS
If the output string is too small for the result, only the
rightmost digits are returned.
3-69
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
gtci d-- convert Mgned integer to decimal string
SYNOPSIS
length =8tci d(out, in, outlen);
int length; output string length (excluding NULL)
char "out; output 8tring
int in; input value
int outlen; sizeof(out)
DESCRIPTION
Converts an integer into astring of decimal digits
terminated with aNULL byte. If the integer is negative,
the output string is preceded by a-. Leading zeros are not
copied to the output string.
RETURNS
length =number of characters placed in output string, not
including the NULL terminator
CAUTIONS
If the output string is too small for the result, the
returned length may be zero, or apartial string may be
returned.
3-70
Lattice 8086/8088 CCompiler Portable Library Functiom
NAME
stchi -- convert hexadecimal string to integer
SYNOPSIS
count =stchi(p, r);
int count; number of characters scanned
char "p; input string
int *r; result integer
DESCRIPTION
Converts ahexadecimal string into an integer. The procms
terminates only when anon-hex character is encountered.
Valid hex characters are D-9, A-F, and a-f.
RETURNS
count =0if input string dom not begin with ahex digit
"number of charactem scanned
CAUTIONS
No check for overflow is made during the processing.
3'//
Lattice 8086/8088 CCompiler portable Library Functions
MAME
stcdi -- convert decimal string to integer
SYNOPSIS
count =stcd i(p, r);
int count; number of characters scanned
char *p; input string
int "r; result integer
DESCRIPTION
Converts adecimal string into an integer. The process
terminates when anon-decimal character is found. Valid
decimal characters are 0-9. The first character may be +or -.
RETURNS
count "0if input string does not begin with adecimal
digit
"number of character8 scanned
CAUTIONS
No check for overflow is made during proceming.
T
3—72
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
stpblk -- skip blanks (white space)
SYNOPSIS
q = stpblk(p);
char *q; updated string pointer
char "p; initial string pointer
DESCRIPTION
Advances the string pointer past white space characters
(space, tab, or newline).
RETURNS
q=updated string pointer (advanced past white space)
CAUTIONS
Must be declared char *, as the stp prefix indicates.
3-73
Lattice 8086/8088 CCompiler Pcntable Library Functions
NAME
stpsym -- get asymbol from astring
SYNOPSIS
p=stpsym(s, sym, symlen);
char *p; points to next character in s
char "s; input string
char "sym; output string
int symlen; sizeof(sym)
DESCRIPTION
Breaks out the next symbol from the input string. The first
cbaracter of the symbol must be alphabetic (upper or lower
case), and the remaining characters must be alphanumeric.
Note that the pointer is not advanced past any initial white
space in the input string. The output string is the NULL-
terminated symbol.
RETURNS
p=pointer to next character (after symbol) in input string
CAUTIONS
Must be declared char ", as the stp prefix indicates. If no
valid symbol characters are found, pwill equal s, and sym
will contain an initial null byte.
3-74
Lattice 8086/8088 CCompiler Portable Library Functions
name
stpchr -- find specific character in string
synopsis
p=stpchr(s, C);
char *p; points to cin 8(or is NULL)
char *s; points to string being scanned
char c; character to be located
DESCRIPTION
Scans the specified string to find the first occurrence of
the specified character. If the NULL terminator byte is hit
first, aNULL pointer is returned.
RETURNS
p=NULL if cnot found in s
=pointer to first cfound in 8(from left)
CAUTIONS
Must be declared char % as the stp prefix indicates.
3—76
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
stpbrk -- find break character in string
SYNOPSIS
p=5tpbrk(8, b);
char "p; points to element of bin s
char "s; points to string being scanned
char "b; poinu to break character string
DESCRIPTION
Scans the specified 8tring to find the first occurrence of a
character from the break 8tring b. In other words, b18 a
NULL terminated list of characters being sought. If the
terminator byte for 8is hit first, aNULL pointer is
returne<L
RETURNS
p=null if no element of bis found in s
=pointer to first element of bin 8(from left)
CAUTIONS
Must be declared char h, as the stp prefix indicates.
3-77
Íjattice 8086/8088 CCompiler portable Library Functions
NAME
stcis, stcisn measure span of acharacter set
SYNOPSIS
length =stcis(s, b);
length =Mxñsn(s, b);
int length; span length in bytes
chaK *s; points to string being scanned
char "b; points to character set string
DESCRIPTION
These functions compute the number of characters at the
beginning (left) of sthat corrie from aspecified character
set.. For stcis, the character set consists of all
characters in b, while for stcisn, the character set
consists of all characters not in b.
RETURNS
length =number of characters from the specified set which
appear at the beginning (left) of s
i
3-78
Lattice 8086/8088 CCompiler Portable Library FunctÍoñ8
NAME
stcarg -- get an argument
SYNOPSIS
length =stcarg(sr b);
int length; number of bytes in argument
char "s; text string pointer
char "b; break string pointer
DESCRIPTION
Scans the text string until one of the break character8 is
found or until the text string ends (as indicated by aNULL
character). While scanning, the function skips over partial
strings enclosed in single or double quotes, and the
backslash is recognized as an escape character.
RETURNS
length =number of bytes (in S) in argument
=0if not found
3-79
Lattice 8086/8088 CCompiler portable Library Functions
NAME
stcpm -- pattern match (unanchored)
SYNOPSIS
length =8tcpm(8, p, q);
int length; length of matched string
char *s; string being scanned
char *p; pattern string
char **q; points to matched string if found
DESCRIPTION
Scans the specified string to find the firrt substring that
matches the specified pattern. The pattern is specified in
asimple form of regular expre3sion notation, where
?matches any character
8* matches zero or more occurrences of s
5+ matches one of more occurrences of s
The backslash is used as an escape character (to match one
of the special characters ?, ", or +). The scan is not
anchored; that is, if amatching string is not found at the
first position of g, the next position is tried, and so orj.
Apointer to the first matchinq ""bstring is returned'at *q.
RETURNS
length =0if no match
=length of matching substring, if succe8sful
CAUTIONS
Note that the third argument must be apointer to a
character pointer, since this function really returns two
values: apointer to, &ñcÍ the length of the first matching
mbstring.
3-80
.
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
.
stcpma -- pattern match (anchored)
SYNOPSIS
length =stcpma(s¶ p);
int length; length of matching string
char "s; string being scanned
char "p; pattern string
DESCRIPTION
Scans the specified string to determine if it begins with a
substring that matches the specified pattern. See the
description of stcpm for aspecification of the pattern
format.
RETURNS
length =0if no match
=length of matching substring if successful
3-Bl
Lattice 8086/8088 CCompiler Portable Library Functions
NAME
stspfp -- parse file pattern
SYNOPSIS
error =stspfp(p, n);
int error; return code: —I if error
char "p; file name string
int n[16]; node index array
DESCRIPTION
parses afile name pattern which consists of node names
separated by slashes. Each slash is replaced by aNULL
byte, and the beginning index of that node is placed in the
index array. For example, the pattern /abc/de/f has three
nodes, and their indexes are lfor abc, 5for de, and 8fcjr
f. Note that the leading slash, if present, is skipped.
Note also that aslash that is part of anode name (usually
unwise) must be preceded by abackslash. The last entry in
the node array nis set to -I (in the example above, this
causes n{3) to be -I).
RETURNS
error =0if successful
=-I if too many nodes or other error
3-82
Lattice 8086/8088 CCompiler Portable Library Functioñs
3.3.4 Utility Macros
The standard I/O header file stdio.h defines three general
utility macros which are useful in working with arithmetic
objects. They are:
max(a,b) returns the maximum of aand b
min(a,b) returns the minimum of aand b
at?s(a) returns the absolute value of a
Several important restrictions must be noted.
First, since these are macros which use che conditional operator,
arguments with side effects (such as function calls or increment
or decrement operators) cannot be used, and the address-of
operator cannot be applied to these "functions". Second, beware
of using the macro names in declarations such as
int min;
because the compiler will try to expand min as a macro, and an
error message complaining of invalid macro usage will be
generated. Third, only arithmetic data items should be used as
arguments to these macros; max and min should be supplied two
arguments of the same data type, although conversion will be
perEormed if necessary.
3-83
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
SECTION 4:
Compiler and Run-time Implementation
aversion of the Lattice Ccompiler for the 8086/8088 runs under
Microsoft's MS-DOS operating system. It accepts program8 written
in the Cprogramming language (the full language -- not asubset)
and produces relocatable machine code in Intel's 8086 object
module format, suitable for use by Microsoft's program linker.
The library defines acomprehensive set of I/O subroutines which
implement under MS-DOS most of the UNIX-compatible standard
functions described in the text by Kernighan and Ritchie.
The 8086 instruction set is well-suited to the implementation of
ahigh-level language like C, and the Lattice compiler generates
machine code which takes full advantage of its features.
Although the 8086 architecture supports up to I megabyte of
addressable memory, its segmented addressing approach works most
efficiently with 64K-byte program and data address spaces. In
order to provide the most flexibility, the compiler supports four
different memory addressing environments, or models, from which
the programmer can select the combination of efficiency and
addressability required for aparticular application. These
models are discussed in more detail in Section 4.4; initially,
onlv the simplest and most efficient model will be presented in
examples: the so-called Smodel in which aprogram may have a
maximum of 64K bytes of program section (functions), pl-us a
maximum of 64K bytes of data section (including static data, auto
or stack data, and dynamically allocatable memory). Despite
these limitations, programs of considerable complexity and power
(including the compiler itself) can be developed.
4.1 Operating Instructions
See Appendix dfor the most current list of the files supplied
with the compiler package. The executable files LCI.EXE and
LC2.EXE make up the actual compiler. Each performs aportion of
the compilation process and must be invoked by' separate commands;
LCl does not automatically load LC2 when it completes its
processing. Normally, LC2 should be executed immediately after
LCl if there are no errors in the source file. Abatch procedure
file can be used to execute LCL and LC2 in succession, using the
same file name (the normal sequence). The compilation process
can be diagtamed as follows:
file.C -> LCl -> file.Q
file.Q -> LC2 -> file.OBj
LCl reads aCsource file, which must have a.C extension, and
(provided there are no fatal errors) produces an intermediate
file of the same name with a.Q extension. LC2 reads an
intermediate file created by LCl and produces an object file of
the same name with an .OBJ extension. The .Q file is deleted by
LC2 when it completes its processing. Each phase normally
creates its output file on the same drive and directory as the
4-l
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
input file. Note that if asource file defines more than one
function, so does its resulting object file. Individual
functions cannot be broken out from the object file when a
program is linked; see Section 4.3.2 for more information.
The .OBJ file must be supplied as input to the linker in order to
produce an executable program file- Two special files must also
be involved in the linking process, in addition to any .OBJ files
created by the user. The linking process can be diagrammed as
follows:
(Note that the actual filenames used depends upon the memory
model selected; see Section 4.4 for more information. In this
discussion and in the example below, the Smodel will be used to
illustrate the linking process.)
CS.OBJ +user.OBj +... +LCS.LIB -> LINK -> user.ExE
The special files required are CS.OBJ and LCS.LIB. First, the
file CS.OBJ must be specified as the first module on the LINK
execution command; this module defines the execution entry and
exit points for any program generated using the Lattice C
compiler. Second, the file LCS.LIB must be specified as the
library; this file defines all of the run-time and I/O library
functions incladed as part of the Lattice Cpackage. The user
must also specify at link time the names of any .OBJ files which
are to be included, as well as the name of the .EXE file which
will be created by the linker.
To illustrate the program generation sequence, the following
commands necessary to compile, link, and execute the Fahrenheit-
to-Celsius sample program (FTOC.C). This example assumes that
all of the .EXE files (LCl, LC2, and LINK) reside on the same
disk and directory. The commands will be shown in upper case,
although lower case commands will work as well. (Note: the
linker prompts described here are for version I.I0 of the
Microsoft linker; for LINK.EXE versions other than l.l, and for
use with linkers other than the Microsoft linker, appropriate
documentation should be consulted. Generally, the default
responses are correct.)
STEP I: Execute the first phase of the compiler by typing
LCl FTOC<ENTER>
Note that the .C extension is not supplied (although
the command will work properly even if it is).
STEP 2: When the MS-DOS prompt is issued after LCI has
completed its processing, execute the second phase of
the compiler with
LC2 FTOC<ENTER>
Again, no extension is specified; LC2 supplies the .Q
4-2
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
extension.
STEP 3: When the prompt is issued after LC2 has completed its
processing, the linker is invoked by typing
LINK CS+FTOC,FTOC,NUL,LCS
Note that CS (meaning CS.OBJ) is specified as the first
object module on the LINK command; this is required for
the linking of any Cprogram. Then FTOC (meaning
FTQC.OBJ, which was just produced by LC2) is specified
as an additional object module. The second FTOC causes
the run file to be named FTQC.EXE, NUL 8kips the
generation of alink map, and LCS cause8 LINK to search
LCS.LIB for external references.
STEP 4: Execute the .EXE file by typing
FTOC<ENTER>
The program writes alist of Fahrenheit temperature
values and their Celsius equivalents to the user's
console.
Detailed instructions for compiling, linking, and executing
programs are presented in the following sections. See Section
4.3 for adetailed discussion of the processing performed by the
compiler pbases.
In presenting the various command line formats, the term field
will be used to describe asequence of non-white space characters
in the command line. Optional fields will be shown enclosed in
square brackets II: the brackets are not to be included when the
actual command is typed. Examples are provided at the end of
each section.
Versions of Lattice Cdesigned to take advantage of MS-DOS
version 2.0 recognize the full Version 2pathnames for all
filenames. The name can be specified on the command line, as in:
LCl b:\lowleve1\file
(which specifies b:\lowlevel\file.c for compilation), or it can
be specified in tinclude statements, as in
#include "b: \headers\stdio.h"
See option -id below for further uses of command line pathnames.
4.1.1 Phase I
The first phase of the compiler reads aCsource file and
produces an intermediate file of logical records 'called
quadruples, or quads. See Section 4.3.1 for amore detailed
discussion of the processing performed. The format of the
4—3
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
command to invoke the first phase of the compiler is:
LCl {=stack] [>listfile] filename [options]<ENTER>
The various command line specifiers are shown in the order they
must appear in the command. Required specifier are shown in
emphasized type. Optional specifiers are shown enclosed in
brackets. The first two options are part of the general command
line options for all Cprograms (see Section 4.1.4). This allows
the use of if expressions in batch files, such as:
Lcl íl
if errorlevel lgoto errs
=stack The first option is used to override the number of
bytes reserved for the stack (see Section 4.5 for a
complete description of the structure of Cprograms).
The default is 2048 (decimal) bytes, which is
sufficient for most programs. If present, the stack
size override field must be the first field after the
name of the first phase (LCl). It is specified as an
equals sign followed by adecimal number (for example,
=4096 specifies avalue of 4096 decimal bytes). Since
the compiler uses recursion to process Cstatements,
heavily-nested statements cause the compiler to use
more stack space than straightforward, linear
sequences. If asource program with many embedded
statements (ifs within ifs within ifs, etc.) causes the
first phase to terminate execution with aSTACK
OVERFLOW error message, the program should compile
successfully if LCl is re-execmted using an increased
stack size, such as 4096. Some experimentation may be
required to determine the necessary stack size. On
systems which are cramped for memory, the stack size
may be trimmed down in an attempt to eliminate aNot
enough memory error; there is no guarantee, however,
that the compilation will be successful, particularly
if the stack size is reduced below 1024 bytes.
>listfile The second option is used to direct the first phase
messages to aspecified file. These messages include
the compiler sign-on message and any error or warning
messages which may be generated. The full filename
must be specified, including extension, if any. If the
file already exists, it is truncated and reused. This
option is useful for reviewing long lists of error
messages.
filename This is tbe only command line field which must be
present; it specifies the name of the Csour=fi1e
which is to be compiled. The filename should be
specified without the .C extension; the first phase
supplies the extension automatically. Note that only
files with a.C extension can be compiled; if some
other extension is specified, the compiler ignores it
4~4
Lattice 8086j8088 CCompiler Cowpíler/Run-time Implementation
and tries to find name.C. (tinclude files, on the
other harA, must be fully specified with extensions.)
The default drive and directory (hereafter
drive/directory) are used unless apathname preceding
the filename specifies another drive/directory; the
quad file is created °Eke sanie drive and directory as
the source Eá~mnless the -o option is ased (see
below). Alphabetic characters may be either upper or
lower case in filenames.
options Compile time options are specified as a hyphen followed
by asingle letter. The letter must be typed in lower
case; the corresponding upper case option will have no
effect. Each option must be specified separately, with
aseparate hyphen and letter (that is, they cannot be
combined as they can for certain UNIX programs).
Current options include:
-a Causes the compiler to assume worst-case aliasing, that
is, to abandon any optimizations based on favorable
assumptions about pointers. Normally, the compiler
assumes that objects referenced through pointers are
not the same as objects being referenced directly in
the same section of the program; this option cancels
that assumption. The -a option additionally forces all
assignment statements to be performed (i.e., the actual
store to memory) before execution of the next
statement. Normally, the code generated for assignment
causes avalue to be loaded to aregister, but it may
not be stored immediately; the -a flag now forces the
store operation. This is important only in (I) unions,
where avalue is stored and then immediately inspected
or passed to afunction via another member; (2) real-
time processing where shared data values are used as
"lock" words, and immediate execution of an assignment
statement is critical to subsequent actions; and (3)
memory-mapped I/O assignments, where values must be
stored repeatedly in the same "memory" location.
-b Forces byte alignment for all offset calculations. The
first phase normally aligns all objects which are not
pointers, structures, or unions on a wc>rd boundary.
-c Causes comments to be processed without nesting. The
Lattice compiler normally assumes that comments may be
nested; this allows large sections of code to be
commented out very easily. This option allows the user
to force the compiler to the standard, non-nesting mode
of operation.
-d Causes debugging information to be included in the quad
file. Specifically, line separator quads are inter-
spersed with the normal quads. This allows the second
phase to collect information relating input line num-
bers to program section offsets. If this option is
4—5
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
used, the object file produced will contain line num-
ber/offset records, and can be processed by the object
Module Disassembler to produce an intermixed source
code and machine code listing (see Section 4.1.6
below). Note that the -d option does not affect the
size of the function itself, only the object file.
-iprefix Specifies that #include files are to be searched for by
prepending the filename with the string prefix, unless
the filename in the #include statement is already
prefixed by adrive or directory identifier. Up to 4
different -i strings may be specified. Note that when
an unprefixed tinclude filename is encountered, the
cutrent drive/directory is searched; then
drive/directories are searched using prefixes specified
in -i options, in the same left-to-right order as they
were supplied orí the command line. The drive/directory
specification should follow DOS 2.0 naming conventions
(see example below). No intervening blanks are
permitted in the string following the i.
—mM Causes the compiler to generate code for the specified
memory model. The model can be specified as asingle
letter, either upper- or lower-case, naming the model;
or anumeric indicator from (J to 3may be used (S=0,
P=l, 0=2, L=3). The model specifier must be adja¿ent
to the m(no intervening blanks). (See Section 4.4.2).
-n Causes the compiler to retain up to 39 characters for
all identifier symbols, including #define symbols. The
default symbol retention length is 8characters.
-oprefix Specifies that the output file (the .Q or quad file) is
to be formed by prependíng the input filename (the .C
file which is being compiled} with prefix. The drive
is specified by asingle alphabetic character, either
upper or lower case, followed by acolon. Thus -ob:
causes prepending with b:.Any drive or directory
prefixes attached to the input filename are discarded
before the prepending is performed. No intervening
blanks are permitted in the string following the o.
-8 Changes the way code is generated for four-byte
pointers in the Dand Lmodels; see Section 4.4.5.
-x Changes the default storage class for external
declarations (made outside the body of afunction) from
external definition to external reference. The usual
meaning of an exteroal declaration for which an
explicit storage class is not present is to define
storage for the object and make it visible in other
files: i.e., external definition. The -x option
causes such declarations to be treated as if they were
preceded by the extern keyword, that is, the object
4-6
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
being declared is present in some other file. This
option is provided for use on programs written for the
BDS C compiler; see Appendix Cfor more information.
EXAMPLES
LCl xyzfile -b: \headers\
This command executes the first phase of the compiler
using file XYZFILE.C as input, creating file XYZFILE.Q
in the current directoryr Any binclude files not found
in the current drive/directoty will be searched for in
the directory B: \HEADERS. Note the trailing backslash
on the prefix attached to the -i flag; it is not
automatically assumed by the compiler.
LCl XYZ -ob: -X
This command executes the first phase of the compiler
using file XYZ.C as input, creating file XYZ.Q on B:;
it sets all external declarations without astorage
class to be interpreted as extern declarations.
LCl =4096 >tns.err tris
This command executes the first phase of the compiler
using file TNS.C as input, creating file TNS.Q on the
currently logged-in disk; it causes the stack size to
4096 decimal bytes, and create afile TNS.ERR to
contain all of the messages generated by the compiler.
4.1.2 phase 2
The second phase of the compiler reads aquad file created by the
first phase and creates an object file in the standard MS-DOS
format. See Section 4.3.2 for a more detailed discussion of the
processing performed. The format of the command to invoke the
second phase of the compiler is:
LC2 filename (options]<ENTER>
The command format is very similar to that for the first phase.
The stack size override and listfile options can a}so be used,
but they are generally less useful and úill not be described here
in any detail. Note that neither phase of the compiler does any
processing of the standard input, so the <option has no effect
on either phase (see Section 4.1.4 for the general Cprogram
execution options).
filename This field must be present; it specifies the name of
the intermediate file for which code is to be
generated. This intermediate file is aquad file with
a.Q extension, created by the first phase of the
compiler. The fije name should be specified without
the .Q extension; the second phase supplies the
4-7
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
extension automatically. Alphabetic characters may be
supplied in either upper or lower case. The default
directory is used unless another drive/directory name
is specified, and the object file is created in the
same drive as the quad file unless the -o option is
used (see below).
options Compile time options are specified as a hyphen
followed by asingle letter. The letter must be typed
in lower case; the corresponding upper case option will
have no effect, Each option must be specified
separately, with aseparate hyphen and letter (that is,
they cannot be combined as they can for certain UNIX
programs). Current options include:
-ggroup Assigns a name of the user's choice to be used for the
code group in the .OBJ module. group may be 15 or
fewer characters in length, and must be adjacent to the
-g {no intervening blanks).
-oprefix Specifies that the output file (the .OBJ file) is to be
formed by prepending the input filename (the .Q file
which is being compiled) with prefix. The drive is
specified by asingle alphabetic character, either
upper or lower case, followed by acolon. Thus -ob:
causes prepending with b:.Any drive or directory
prefixes attached to the input filename are discarded
before the prepending is performed. No intervening
blanks are permitted in the string following the o.
-ssegment Assigns a name of the user's choice to be used for the
code segment in the .OBJ module. segment must be 15 or
fewer characters in length, and must be adjacent to the
-S (no intervening blankg).
-v Causes the code generator to omit the code at the entry
tD each function which checks for stack overflow (See
Section 4.5.5).
The -g and -s options for LC2 are provided to override the
default code group arA segment names. Only users who need to
interface to very specialized applications (other languages,
etc.) will need to make use of these options.
EXAMPLE
LC2 u790 -OC:
This command executes the second phase of the compiler
using file U790.Q as input, causing the file U790.OBJ
to be created on drive C: .
4-8
Lattice 8086/8088 CCompiler Ccmpiler/Run-thne Implementation
4.1.3 Program Linking
d
After all of the component source modules for aprogram have been
compiled, they must be linked together to form an executable
program file. This step is necessary for several reasons.
First, the object file produced by the second phase of the
compiler is not in astate suitable for execution. Second, most
programs make use of functions not defined in the current module;
before such programs can execute, they must be "connected" with
those other modules. These external functions may be defined by
the user, in which case they must be compiled and be available as
.OBJ files, cir they may be defined in the library supplied with
the compiler. (The portable functions are described in Section
3; others defined only under MS-DOS are described in Section
5.5.) Third, although Cnormally defines the function called
main to be the execution point of aCprogram, there is usually a
considerable amount of system-dependent processing which must be
performed before main is actually called; the module to perform
this processing is integrated into the program when it is linked.
Although the usual concept of linking involves external function
calls, Calso permits functions to access data locations defined
in other modules. This kind of reference is possible because the
external linkage mechanism supported by the object code
associates an external symbol with amemory location; this symbol
is the identifier used to declare the object in acprogram. The
programmer must be careful to declare an object with the same
attributes in both the module which defines it and the module
which refers to it, because the linker cannot verify the type of
reference made -- it simply connects memory references using
external symbols» The Lise of include files f,o,k common external
declarations will usually prevent this'"kiñd Ó7"error.,
The linking process in ageneral sense requires that all of the
components of aprogram be specified, either directly or
indirectly, as input to the linker. Three types of input are
required.
]. Astart-up file CS.OBJ (or CP.OBJ, CD.OBJ, or CL.OBJ)
must be specified as the first module included by the
linker. This file defines the MS-DOS entry point for
all Cprograms compiled using the Lattice Ccompiler.
2. Functions generated by the user must be specified as
additional modules to be included. These modules
include the main module, as well as any additional
functions defined in other source modules.
3. AZibraty file LCS.LIB (or LCP.LIB, LCD.LIB, or LCL.LIB)
must be specified as the library to be searched during
linking.
In the case of the Microsoft linker supplied with MS-DOS, these
inputs are specified by:
4-9
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
l. Making CS (or CP, CD, or CL) the first module on the
LINK command.
2. Including the names (without the .OBJ extension) of the
user's object files on the LINK command, after the CS
(or CP, CD, or CL) specification.
3. Typing LCS (or LCP, LCD or LCL) in response to the
Libraries prompt from the linker.
Note that for step (2)", one of the files included on the LINK
command must be the main module.
If the linker cannot find one of the .OBJ files mentioned on the
LINK command, it will stop processing without creating a.EXE
file. Another error condition can arise if the linker cannot
find all of the external items referred to in the .OBJ files
specified. In this case, the message Unresolved Externals will be
generated by the linker, followed by alist of the external names
which were not defined. SÉj. attempt ,t.o. execute a. program with
unresolved externals should be made unless it is certain that the
missing functions will never b.e. called.
See Section 4.2.2 for adiscussion of external names. See
Section 4.4 for adiscussion of the startup and library files
used in the four memory models. See Section 4.5 for atechnical
description of the object code features used in this
implementation. If the linker being used allows generation of a
public symbol map, a .MAP file may be created, allowing the
examination of the components in the resulting load module.
EXAMPLE
LINK CS XYX QRS<BNTER>
Run File [cs.ExEj: XYE<ENTER>
List File [NUL.MAP]: <ENTER>
Ubraries (.LIB]: LCS<ENTER>
This command executes the linker, prodacing XYZ.EXE as
an executable program, and causes the files XYZ.OBJ and
QRS.OBJ to be included in the program. AnswerS to the
prompts from the linker used for this compilation are
also shown.
Álternatively, these Linket instructions can appear on
asingle command line:
LINK CS+XYZ+QRS,XYZ,NUL.,LCS<ENTER>
4.1.4 Program Execution
When aCprogram is executed, the function main is called to
begin execution. Two important services are performed for main
before it receives control.
4-ID
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
I. The command which executed the program is analyzed, and
information from the command line is supplied as
parameters to main. The analysis performed and the
nature of the parameters supplied will be discussed in
detail below. This feature is designed to make it
easier to process command line inputs to the program.
2. The buffered text files stdin (standard input), stdout
(standard output), and stderr (standard error) are
opened and thus available for use by the program.
Normally, all three units are assigned to the user's
console, but stdin and stdout may be assigned elsewhere
by command line options described below. This feature
allows flexibility in the use of programs which work
with text file I/O using the standard getchar and
putchar macros.
The simplest way to execute aCprogram 18 to type the name of
the .EXE file (without the .EXE extension), followed by areturn
(<enter>). Since the command line provides aconvenient way to
supply input to aprogram, aprogram execution request will often
contain other information. The general format of the command
line to execute aCprogram is:
["stack] [<infile) [>outfile) [args)<ENTER>
Everything after pgmname is optional, as the brackets indicate.
The various additional items ("stack, <infile and >outfile), if
present, must appear before all other command line arguments
following the program name. Note that these three items do not
contribute to the argument count.
pgmname This field names the pEogram to be executed; it is the
name of the .EXE file created when the program was
linked. It must be specified without the .EXE
extension.
=8tack The first optional field is used to specify adecimal
number of bytes to be reserved for the stack when the
program executes. The default value used if this field
is not present is 2048 bytes. The stack size is
specified as a decimal number immediately preceded by
an equals sign. All objects declared auto are
allocated from the stack, but the memory used for these
allocations is freed when the function in which they
are declared returns to its caller. The dynamic nature
of this allocation makes it generally difficult to
predict how much stack space is actually needed for a
particular program. The stack size option on the
command line allows the user to adjust the amount of
memory reserved for the stack without having to
recompile the program. The memory reserved for the
stack affects the amount of memory available for
dynamic allocation by the various library functions
4-ll
mttice 8086/8088 CCOmpiler Compiler/Run-time Implementation
described in Section 3.1. See Section 4.5 for more
information about the structure of Cprograms.
<infile The second optional field names afile or device to
which the standard input (stdin) is to be assigned.
This option is useful only if the program being
executed actually uses the standard input (that is, it
processes text input using getchar or scanf or makes
explicit getc or fscanf calls using stdin). The file
or device name must be immediately preceded by a<
character; if afile, the full name including
extension, if any, and pathname, if any, must be
specified. See section 5.2 for alist of valid device
names. The file must exist, or the program will be
aborted with the error message Can't open stdin file.
>outfile The third optional field names afile or device to
which the standard output (stdout) is to be assigned.
This option is useful only if the program being
executed actually uses the standard output (that is, it
generates text output using putcbar or printf or makes
explicit putc or fprintf calls using stdout). The file
or device name must be immediately preceded by a>
character; if afile, the full name including
extension, if any, must be specified. See Section 5.2
for alist of valid device names. The file is opened
as a new file, which discards its previous contents if
they already existed and creates an empty file. If the
filename specified is invalid or not enough directory
space is available to create the new file, the ptogram
is aborted with the error message Can't creat2 stdout
file.
If two >characters are used instead of one, the file
is opened flor appending, and any output is added on to
the end of the file. This option is useful for
accumulating logging information. The file is created
if it does not exist.
arg8 Any additional fields beyond the program name and the
three optional fields are extracted and passed to the
function main as two arguments:
main(argc, argv)
int argc; rnumber of arguments */
char *argv{]; /" array of ptrs to arg strings "/
Each arg string is terminated by anull byte. On most
systems which support C, argv[0] is the name by which
the program was invoked. Unfortunately, under MS-DOS
the program name is not readily available, although all
of the other information from the command line is. A
dummy argv[0j is therefore supplied (all programs are
named caccording to argv[0]) but subsequent elemeots
of argv are defined properly. Arguments appear in argv
4-12
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
in the same order in which they were found on the
command line. Note that the optional stack and file
specifiers are not included in the argv list of
strings.
Although all of the above features are intended as conveniences
for writing utility programs under MS-DOS, many of the library
I./O functions are forced to be apart of the program because of
this processing (specifically, the opening Df the buffered input
and output fiLes). For programs which were going to use the
buffered I/O functions anyway, this does not present aproblem,
even though these functions add asubstantial number of bytes of
code to the size of the linked program. Users who must be
concerned about program size and who are not using these
functions can avoid including the extra modules by supplying a
special version of main, the library function which calls main.
See Section 5.4 for"details.
EXAMPLES
CPROG =8000 <INPUT.R PQP 12
This command executes CPROG.EXE, sets the stack size to
8000 decimal bytes, and connects stdin to the file
INPUT.R. The main function will be supplied an argc
value of 3, with strings c, PQP, and 12 in the argv
array.
errlog >>errors.log data
This command executes ERRLOG.EXE with stdout connected
to ERRORS.LOG for appending (adding to the end of
file). The main function will be supplied with an argc
value of 2, with strings cand data in the argv array.
4.1.5 Function Extract Utility
Because the compiler generates asingle, indivisible object
module for ali of the functions defined in asource file, the
Function Extract Utility (FXU) is provided so that groups of
small functions may be kept together in asingle source file and
object modules produced for them individually. The utility
operates by extracting the source text for asingle, specified
function, thus creating asource module which can then be
compiled to produce an object module defining only that specific
function.
Those who are somewhat puzzled by the need for this utility may
find the following example helpful. Suppose that one user has a
module called STRING.C, which defines several string handling
functions, and that aprogram calls one of those functions (say,
strcnt). If STRING.C is compiled as a single source module, the
resUítiDg object module defines strcnt along with several other
functions. When the program is linked, then, the machine code
for strcnt is included (as part of the object module produced
4—13
mttice 8086/8088 CCompiler Compiler/Run-time Implementation
when STRING.C was compiled), but the code for all of the other
functions is included as well, even though the program does not
make use of them. Only by compiling 8trcnt as the only function
defined in its source module will the compiler produce an object
module which defines only that function. FXU can be used -to
produce such asource file.
The format of the ccmmand to invoke the Function Extract Utility
is
FXU [<header-file] [>output-fi1e) filename function<enter>
The various command line specifiers are shown in the order they
must appear in the command; optional specifiers are shown
enclosed in brackets. The first two options are part of the
general command line options for all Cprograms (see Section
40 IP4)e
<header-file The first option specifies afile which will be
copied to the output file when the specified
function is found. The entire file is copied
before any text from the function is written. If
only the function itself is to be written to the
output file, the <NUL option should be used. If
this option is omitted, text will be read from the
user's console and copied to the output file
until acontrol-Z is typed.
>output-file The second option specifies the output file which
will contain the text of the extracted function
(preceded by the header file text, if any). If
this option is omitted, text is written to the
user's console.
filename Specifies the name of the file containing the
function to be extracted.
function Specifieg the name of the function to be extracted
from the 3pecified file. The function name must
be specified exactly as it appears in its
definition, except that alphabetic characters may
be specified in either upper or lower case.
The Function Extract Utility counts braces defined in the'body of
the functions in order to determine when it has reached the end
of afunction. Although it recognizes comments and will not make
the mistake of counting any braces which might be enclosed in
them, it assumeg that comments can be nested, which is the same
assumption normally made by the compiler. The compiler, however,
can be requmted Mc command line option to process comments as if
they did not nest; FXU has no such option.
The text extracted consists of all the characters between the
closing brace of the preceding function, up to and including the
closing brace of the extracted function. If the specified
4-14
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
function is the first one defined in the source file, then all
characters from the beginning of the file to the function's
closing brace are included. Note that functions which refer to
external data items defined in the source module cannot be easily
processed with the function extract utility. As the example
below illustrates, however, the header file option can be used to
avoid this limitation.
If the specified function is not encountered in the specified
source file, the output file will receive the single error
message Named function not found. Note that FXU works on only a
single function, not alist of functions. Asource module
defining more than one extracted function can be generated,
however, by executing E'XU repeatedly and then combining the
extracted texts using the CAT program, which is supplied as an
example source file.
The supplied version of FXU uses an internal buffer to store
characters between functions, while it scans for the next. The
buffer size can be expanded, if necessary, by asimple
modification to the source text, which is supplied as FXU.C.
EXAMPLES
FXU <NUL STRING.C strcnt
This command extracts the function called strcnt from the
text file STRING.C and causes the extracted text to be
written to the user's console.
FXU <IOS.H >INPUT.C XOFUNC.C input
This command extracts the function called input from the
text file IOFUNC.C, prepends the output with the text from
the file IOS.H and writes the resulting text to INPUT.C.
If each function in IOFUNC.C can refer to the external
locations flagl and flag2, for example, and ne,eds the
information from the standard I/O header file, then IOS.H
should include the text
tinclude <stdio.h>
extern int flagl, flag2;
Asimilar technique can be used for functions which need more
extensive external references.
4.1-.6 object Module Disassembler
For programmers who wish to debug Cmodules at the machine code
level, the object Module Disassembler (OMD) provides alisting of
the machine language instructions generated for aparticular C
source module. If the module is compiled with the -d option so
that line number/offset information is included in the object
file, the disassembler utility can produce alisting with
interspersed source code lines. This listing can then be used in
4-15
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
association with the link map for the program to perform
interactive debugging using Microsoft's DEBUG.
The format of the command to invoke the object module
disassembler is
OMD [>1istfile] [options) objfile [textfile]
The various command line specifiers are shown in the order they
must appear in the command. Optional specifiers are shown
enclosed in brackets.
>listfile The first option is used to direct the listing produced
by OMD to aspecified file or device. If this option
is omitted, the listing output is written to the user's
console.
options Four override options can be specified; each consists
of ahyphen followed by asingle letter which indicates
the value to be overridden, and astring of decimal.
digits specifying the override value. There must be no
embedded blanks in any single option, but each must be
specified as aseparate field. The valid options are:
-Pnnn Overrides the default size provided for the program
section of the object module being processed. nnn
specifies adecimal number of bytes of storage to be
allocated for the program section. The default value
is 1024 bytes.
-Dnnn Overrides the default size provided for the data
section of the object module being processed. nnn
specifies adecimal number of bytes of storage to 75é
allocated for the data section. The default value is
1024 bytes.
—Xnnn Overrides the default maximum number of external items
which can be processed by OMD; this number applies
separately to both external definitions and external
references. nnn specifies adecimal number of external
items which can be processed. The default value i':
200.
-Lnnn Overrides the default size for the line number and
offset information tables. These tables are used only
if the object file was produced with the -d 'option;
line number/offset information from the file is placed
in these tables. The default size (which defines the
maximum number of line number/offset pairs which can be
processed) is 100.
objfile Specifies the name of the object file, produced by tbe
compiler, which is to be processed by OMD. The full
name including the .OBJ extension must be specified.
4-16
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
textfile Specifies the name of aCsource code file which is to
be listed along with the disassembled instructions. If
this option is present, the object file must have been
compiled using the -d option for the LCl command. The
full name including the .C extension must be specified.
OMD processes only asingle object module. The entire module is
read and loaded into memory before the listing is generated. The
various override options are useful for processing very large
object modules, or for reducing the amount of memory needed by
OMD on systems which are cramped for memory.
If the textfile option is used, only the source text from the
specified file is listed; if it refers to any tinclude files,
they will not be listed. Some limitations of the textfile option
should be noted. First, the code generated for the ttiírd portion
of for statements is placed at the bottom of the loop; that code
will appear in front of the next statement after the end of the
loop. Second, the compiler tends to defer storing registers
until the last pQssible moment, so that the code shown for
assignment statements often consists merely of loading values
into registers; the registers will be stored later. Finally, the
code generated for entry to afunction will often be displayed in
front of the source lines defining that function. Thus,
inspection of the surrounding code may be necessary to determine
the actual code generated for asource file construct.
EXAMPLES
OPID -P2048 -D8000 QRS.OBJ
This co=aDd disassembles the object module QRS.OBJ and
writes the listing to the user's console; it causes
2048 decimal bytes of storage to be allocated for the
program section defined in the object module, and 8000
decimal bytes for the data section.
OMD >TEMP.LST -X400 XYZ.OBJ XYZ.C
This command disassembles the object module XYZ.OBJ and
writes the listing to the file TEMP.LST; it causes the
source code lines from XYZ.C to be placed in the
listing, provided that line number and offset
information is present in the object file. It also
provides for amaximum number of 400 external items
(same limit for both external definitions and external
references).
ERROR MESSAGES
avariety of error conditions are detected by the object Module
Disassembler; all cause early termination of the output file and
result in the writing of an appropriate error message to stderr.
These messages are self-explanatory for the most part. If one of
the run-time-specifiable options is not sufficiently large, the
4—17
D
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
etror message will indicate the specific option which was not
large enough; for example, if the module defines too many words
of program section, the message
Program section overflow
will be produced. Note that OMD was designed specifically for
use with modules generated by the Ccompiler; attempts to use it
with other object modules will probably cause an error message to
be generated.
4.2 Machine Dependencies
The Clanguage definition does not completely specify all aspects
of the language; anumber of important features are described as
machine-dependent. This flexibility in some of the finer details
permits the language to be implemented on avariety of machine
architectures without forcing code generation sequences that are
elegant on one machine and awkward on another. This section
describes the machine-dependent features of the language as
implemented on the 8086/8088. See Section 2of the manual for a
description of the machine-independent features of the Lattice
implementation of the language.
4.2.1 Data Elements
The standard Cdata types are implemented according to the
following descripticms. The only data elements which free
alignment to aword offset are pointers, structures, and unions;
as noted in Section 4.1.2, this alignment can be disabled by a
compile time option. In all cases, regardless of the length of
the data element, the low order (least significant) byte is
stored first, followed by successively higher order bytes. This
scheme is consistent with the general byte ordering used on the
8086, and with the memory formats expected by the 8087 numeric
data processor. The following table. summarizes the character,-
istics of the data types:
Type Length in Bits Range
char 8 0 to 255 (ASCII character set)
int 16 -32768 to 32767
8)ijort 16 -32768 to 32767
unsigned 16 0to 65535
long 32 -2E9 to 2E9
float 32 +/- I0E37 to +/- I0E38
double 64 +/- I0E-307 to +/- WW08
char defines an B-bit unsigned integer. Text
characters are generated with bit 7reset,
according to the standard ASCII format.
int defines al6-bit signed integer; short and short
int are synonyms.
4~18
Lattice 8086/8088 CCompiler Compiler/Run-time Ímplementation
unsigned or
unsigned int defines aí6-bit unsigned integer. Note that in
this implementation, unsigned is not amodifier
but aseparate data type.
long or
long int defines a32-bit signed integer.
float defines a32-bit signed floating point number,
with an B-bit biased binary exponent, and a24-
bit fractional part which is stored in normalized
form without the high-order bit being explicitly
represented. The exponent bias is 127. This
representation is equivalent to approximately 6
or 7decimal digits of precision.
double or
long float defines a64-bit signed floating point number,
with an ll-bit biased binary exponent, and a53-
bit fractional part which is stored in normalized
form without the high-order bit being explicitly
represented. The exponent bias is 1023. This
representation is equivalent to approximately 15
Dr 16 decimal digits of precision.
pointers to the various data types are either two bytes or four
bytes in length, depending on the memory addressing model used.
See Section 4.4 for more information.
4.2.2 External Names
External identifiers in the MS-DOS implementation differ from
ordinary identifiers in one important respect: the MS-DOS linker
treats upper and lower case letters as if they were the same.
This means that, although the compiler will consider main and
MAIN to be two different functions, the linker will not.
External names may be up to 8characters in length, and the
underscore is avalid character. Since the compiler always
assumes that external names have the same characteristics as
ordinary identifiers, programmers must be careful not to define
external names which the compiler believes are different but
which the linker will interpret as the same name. Asafe rule is
to use lower case letters only for all externally visible items,
including functions and data items which are to be defined for
reference from functions in other source files.
Auser may define external objects with any name that does not
conflict with the following classes of identifiers:
******* Certain library functions and data elements (defined in
modules written in C) are defined with an initial
underscore.
CX***h Run-time support functions (written in assembly
language) which implement Clanguage features such as
4-19
Lattice 8086/8088 CCompiler Compiler/Run-time Ímplementation
long integer multiply and divide, floating point
arithmetic, and the like are defined with CX as the
first two characters.
XC"*** Low-level operating system interface functions (written
in assembly language) are defined with XC as the first
two characters.
The likelihood of collision with library definitions is remote,
but users should be aware of these conventions and avoid applying
these types of identifiers to external, user-defined functions
and data.
4.2.3 Include File Processing
Include files may be specified as:
tinclude "filename.ext"
or tinclude <filename.ext>
The two forms have exactly the same effect. The name between the
delimiters is taken at face value; the extension must be
specified if one is defined for the file. The usual convention
is to use .H for all header files, as was done with the header
files included with the compiler package. Alphabetic characters
in afilename may be specified in either upper or lower case.
The file must be present in the default drive/directory unless a
drive specifier or pathname is included in the filename (not
recommended). The -i option (see Section 4.1.1) is the
recoñmenáed method for specifying adifferent drive and,/or
directory path. The filename is retained internally by the
compiler for error reporting (see Section 4.3.3).
4.2.4 Arithmetic Operation8 and Conversions
Arithmetic operations for the integral types (floating type
operations are discussed in the next section) are generally
performed by' in-line code. Integer overflows are ignored in all
cases, although 16-bit signed comparisons correctly include
overflow in determining the relative size of operands. Division
bjj zero generates an interrupt which is processed by MS-DOS; on
the operating system used to develop the compiler, the message
Integer overflow is generated and execution of the offending
program aborted. Division of negative integers causes truncation
toward zero, just as it does for positive integers, and the
remainder has the same sign as the dividend. Right shifts are
arithmetic, that is, the sign bit is copied into vacated bit
positions, unless the operand being shifted is unsigned; in that
case, alogical (zero-fill) right shift is performed.
Function calls to library routines are generated only for long
integer multiplication, division, and comparison. Product
overflow is ignored. Division by zero yields aresult of zero.
The sign of the remainder is the same as the sign of the
4-20
Lattice 8086/8088 CCowpiler Compiler/Run-time Iwplewentatiot3
dividend. Comparison is signed but does not take account of
overflow.
Conversions are generated according to the "usual arithmetic
conversions" described in Kerntghan and Ritchie, and are
generally trouble free. The following four points should be
noted:
I. char objects are unsigned in thi8 implementation. Sign
extension is n.o.t. performed during expansion to int;
instead, the high byte 18 simply set to zero. Code
sequences such as
char i;
0D O
for (i"8; i>" D; i--)
will not work (in this case, the loop never terminates).
2. Conversion of int or 8hort to long causes sign
exteosion. The inverse operation is atruncation; the
result is und<Eined if its absolute value is too large
to be represented.
3. Conversions from integral to floating types are fairly
straightforward. The inverse conversions cause any
fractional part to be dropped.
4. Conversion from float to double is well-defined, but the
inverse operation may cause an underflow or overflow
condition since double has amuch larger exponent range.
Considerable precision is also lost, though the fraction
is rounded to its nearest float equivalent.
4.2.5 Floating point Operatiom
In accordance with the language definition, all floating point
arithmetic operations are performed using double precision
operands, and all function arguments of type float are converted
to type double before the function is called. The formats used
are identical to the short real and long real formats expected by
the 8087 numeric data processor (the formats are described in
Section 4.2.1). Legal floating point operations include simple
assignment, conversion to other aritlmetic types, unary minus
(change sign), addition, subtraction, multiplication, division,
and comparison for equality or relative size. Note that,' in
contrast to the signed integer representations, negative floating
point values are not represented in two's complement notation;
positive and negative numbers differ only in the sign bit. 'This
means that two kinds of zero are possible: positive and
negative. All floating point operations treat either value as
true zero and generally produce positive zero, whenever possible.
Note that code which checks float or double objects for zero by
type punning (that is, examining the objects as if they were int
or some other integral type) may assume (falsely) neqative ,z.e.r.o,
4-21
Lattice 8086/8088 CCompiler Compiler/Run-time Ímplementation
to be not zero.
Floating point arithmetic and comparison operations are performed
by generating calls to library functions. These functions do not
make use of the 8087, although the floating-point formats are
compatible with the 8087. Note that these functions were
designed for accuracy, not speed, using straightforward,
unsophisticated algorithms.
Floating point exceptions are processed by alibrary function
called CXFERR that is called according to the following
coovention:
CXFERR(errno);
int errno;
where errno can be
I=underflow
2=overflow
3=divide by zero
The standard version of CXFERR supplied in the library file
LCS.LIB (and LCP.LIB, LCD.LIB, and LCL.LIB) simply ignores all
error conditions. You may write adifferent version (in either C
or assembly language) to print out an error message and terminate
processing, or take any other action. If CXFERR returns to the
library function which called it, each exception is processed as
follows:
Underflow Sets the result equal to zero.
Overflow sets the result to plus or minus infinity.
zerodivide Sets the result equal to zero.
Consult the 8087 description for more information about the
floating-point formats.
4.2.6 Bit Fields
Bit fields are fetched on a word basis, that is, the entire word
containing the desired bit field is loaded (or stored) even if
the field is 8bits or less in size. Bit fields are assigned
from left to right within amachine word; the maximum field size
is 15 bits. Bit fields are considered unsigned in this
implementation; sign extension is not performed when the value of
afield is expanded in an arithmIetic expression. If astructure
is declared
struct {
unsigned x:5;
unsigned y:4;
unsigned z:3;
}a;
then aoccupies asingle 16-bit word, a.x resides in bits 15
4-22
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
through li, a.y in bits ID through 7, and a.z in bits 6through
4. Because of the way bytes are ordered on the 8086, this
results in a.y being split between the low and high bytes.
4.2.7 Register Variables
This version of the compiler does not implement register
variables because of the comparatively limited number of
registers available on 8086/8088 microprocessor. However,
declarations using register are accepted if properly' made.
Storage is reserved fW these objects as if they had been
declared auto.
4.3 Compiler Processing
The Lattice Ccompiler under MS-DOS is implemented as two
separately executable programs, each performing part of the
compilation task. This section discusses the structure of the
compiler in general terms, and describes the processing performed
by both phases. Special sections are devoted to adiscussion of
the topics of error processing and code generation.
4.3.1 Phase I
The first phase of the compiler performs all pre-processor
functions concurrently with lexical and syntactical analysis of
the input file. It generates the symbol tables, which contain
information about the various identifiers in the program, and
produces an intermediate file of logical records called
quadruples, which represent the elementary actions specified by
the program. The intermediate file (also called the quad file)
is reviewed as it is written, and locally common sub-expressions
are detected and replaced by equivalent results. When the entire
source program has been processed (assuming there are no fatal
errors), selected symbol table information is written to the quad
file, for use by the second phase. The first phase is thus very
active as far as disk I/O is concerned. Generally, if the disk
activity stops for more than afew seconds, it is reasonable to
assume that the compiler has failed. See Appendix Bfor the
cqmpiler error reporting prpcedure if this happens.
When the first phase begins execution, it writes asign-on
message to the standard output, unless (I) the specified sjource
file could not be found, or (2) aquad file with a.Q extension
could not be created (owing to lack of directory space). The
sign-on message identifies the version of the compiler which is
being executed. The MS-DOS 2.0 implementation returns an exit
code of zero if no errors were detected, and acode of I
otherwise. This allows the use of if expressions in batch files,
such as:
LCl u
if errorlevel l goto errs
See Section 4.3.3 for more information about error processing.
4-23
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Note that the quad file is deleted if any fatal errors are
detected.
4.3.2 Phase 2
The second phase of the compiler scans the quad file produced by
the first phase, and produces an object file in the Intel 8086
format. This object code supports all of the necessary relocation
and external linkage conventions needed for Cprograms (see
Section 4.5.2 for details). Alogical segment of code specifying
the 8086 machine language instructions which make up the
executable portion of the program is generated first, followed by
asegment of data-defining code for all static items. Unlike the
first phase, the code generator is not always actively performing
disk I/O. Each function is constructed in memory before its
object code is generated, so there may be fairly sizable pauses
during which no appatent activity is taking place. In general,
these delays should not last more than several seconds. Anything
longer than a30-second delay can safely be assumed to ·be a
crash; see Appendix Bfor information about reporting compiler
problems.
When the second phase begins execution, it writes asign-on
message to the standard output, unless (I) the specified quad
file could not be found, or (2) an object file with a.OBJ
extension could not be created (owing to lack of directory
space). When code generation is complete, the second phase
writes amessage of the form
Module size p=pppp D=dddd
to the standard output (usually the user's console). pppp
indicates the size in bytes of the program or executable portion
of the module generated, and dddd indicates the size in bytes of
the data portion; both values are given in hexadecimal. These
sizes include the requirements for all of the functions included
in the original source file. Note that the sizes define the
amount of memory required for the module once it is loaded (as
part of aprogram) into memory; the .OBJ file requires mote space
because it contains additional relocation information.
As noted in the introduction to Section 4.1, the code generator
produces asingle .OBJ module for agiven source module,
regardless of how many functions were defined in that module.
These functions (if more than one is defined) cannot be separated
at link time; if any one of the functions is needed, all of them
will be included. Functions must be separated into individual
source files and compiled to produce separate object modules if
it is necessary to avoid this collective inclusion. As
previously mentioned, aFunction Extract Utility (FXU.EXE) is
provided sso that multiple functions may be stored in asingle .C
file and extracted individually for compilation; see Section
4.1.5.
4~ 2 4
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
4.3.3 Error Processing
All error conditions (with the exception of internal compiler
errors) are detected by the first phase. As soon as the first
fatal error is encountered, the compiler stops generating quads
and deletes the quad file just before it terminates execution.
This prevents the second phase from attempting to generate code
from an erroneous quad file. As mentioned in Section 4.3.1, under
DOS 2.0 the compiler returns azero if no errors are detected,
and alotherwise. When the compiler detects an error in an input
file, it generates an error message of the form:
filename .l,i.n,e, Error nn: descriptive .t.e.x.t.
where filename is the name of the current input file (which may
not be the original source file if Sinclude files are used); line
is the line number, in decimal, of the current line in that file;
LYj. is an error number identifying the error; and descriptive text
is abrief description of the error condition. (Appendix A
provides expanded explanations for all error and warning messages
produced by the compiler.) All error messages are written to the
standard output, which is normally the user's console but can be
directed to afile if desired (see Section 4.1.1). Amessage
similar to the one above but with the text Warning instead of
Error is generated for non-fatal errors; in this case, generation
of the quad file continues normally. In some cases, an error
message will be followed by the additional message:
Execution terminated
which indicates that the compiler was too confused by the error
to be able to continue processing. The compiler uses avery
simple-minded error recovery technique which may cause asingle
error to induce asuccession of subsequent errors in a"cascade"
effect. In general, the programmer should attempt to correct the
obvious errors first and not be overly concerned about error
messages for apparently valid source lines (although all lines
for which errors are reported should be checked).
Error messages which begin with the text CXERR are internal
compiler errors which indicate aproblem in the compiler itself.
See Appendix Bfor the compiler error reporting procedure. The
compiler generates afew other error messages that are not
numbered; theY are usually self-explanatory. The most common of
these is the Not enough memory message, which means that the
compiler ran out of working memory.
4.3.4 Code Generation
The code generation phase reads the quad file and builds an image
of the instructions for each function in working memory, before
writing the instructions to the object file. This implies that
at least as much working memory must be present as is required by
the largest function in the source file; actually, considerably
more memory (as much as several times that size) is required
4—25
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
because of the additional overhead used by tbe compiler. Since
the compiler uses the Smemory model which has a64K byte data
space limitation, there is adefinite limit to the size of a
functicn which can be compiled even when the maximum amount of
memory is available. Nonetheless, all of the compiler's own
source modules -- some of which contain very large functions --
can be compiled without difficulty. In any case, Cis alanguage
which encourages modularity; most programs consist of! numetous
functions, most of them small. It is therefore doubtful that the
function size limitation will prove to be aproblem.
One reason for the extra overhead in buffering the function in
memory is that branch instructions are not explicitly represented
in the function image. Instead, they are represented by special
structures denoting the type and target of each branch. when the
function has been completely defined, the branch instructions are
analyzed and several important optimizations are performed:
l. Any branch instruction that passes control directly to
another branch instruction is re-routed to branch
directly to the target location.
2. Aconditional branch instruction that branches over a
single unconditional branch is replaced by asingle
conditional branch instruction of the opposite sense.
3, Sections of code into which control does not flow are
detected and discarded.
4. Each branch instruction is coded in the smallest
possible machine' language sequence required to reach the
target location.
Most of these optimizations are applied iteratively until no
further improvement is obtained.
The code generator also makes aspecial effort to generate
efficient code for the switch statement. Three different code
sequences may be produced, depending on the number and range of
the case vqlues.
I. If the number of cases is three or fewer, control is
routed to the case entries by aseries of test and
branch instructions.
2, If the case values are all positive and the difference
between the maximum and minimum case values is less than
twice the number of cases, the compiler generates a
branch table which is directly indexed by the switch
value. The value is adjusted, if necessary, by the
minimum case value and compared against the size of the
table before indexing. This construction requires
minimal execution time and atable no longer than that
required for the type cjf sequence described in No. 3.
4-26
Lattice 8086/8088 Ccompiler Compiler/Run-time Implementation
3. Otherwise, the compiler generates atable of {cas,e.
value, branch address) pairs, which is linearly searched
for the sYitcíj value.
All of the above sequences are generated in-line without Eunction
calls because the number of instruction bytes 18 small enough
that little benefit would be gained by implementing them as
library functions.
Áside from these special control flow analyses, the compiler does
not perform any global data flow analysis or any loop
optimizations. Thus, values in registers are not preserved
across regions into which control may be directed. The compiler
does, however, retain information about register conteñt8 after
conditional branches which cause control to leave aregion of
code. Throughout each section of code into which control cannot
branch (although it may exit via conditional branche8), values
which are loaded into registers are retained as long as possible
so as to avoid redundant load and store operations. The
allocation of registers is guided by next-use information,
obtained by analysis of the local block of code, which indicates
which operands will be used again in subsequent operationm This
information also assists the compiler, in analyzing binary
operations, in its decision whether to load both opetands into
registers or to load one operand and use amemory reference to
the other. Generally, the result of such an operation will be
computed in aregister, but sequences like
i+= j;
will load the value of jinto aregister and compute the result
directly into the memory location for i(but only if iis not
used later in the same local block of code).
The hardware registers AX, BX, CX, and DX are used as general
purpose accumulators, while SI and DI (along with BX) are used
for access to indirect operands. BP 18 u8ed to address the
current stack frame; see Section 4.5.3 for more information. In
the dand Lmemory addressing models, the ES segment regigter is
used for indirect pointer references, see Section. 4.4.
In order to generate the most efficient code for the largest
number of source language constructiom, the compiler u8uaIly
makes afavorable assumption about pointer variables.
specifically, it assumes that the actual objects accessed using
pointer variables are not the same as other objects which can be
accessed directly. This allows the compiler to avoid discarding
register contents (thus forcing them to be reloaded, perhaps
unnecessarily, at alater time) whenever aremüt is assigned
using apointer. Consider the following example:
int i, j, k, "pi;
C 0 e
i=j+2;
"pi "j;
4-27
tmttice 8086/8088 CCompiler Compiler/Run-time Implementation
k=1"4;
In the general case, it is quite possible that pi might actually
point to i, which would change the value assigned to kin the
next statement. In the vast majority of Cprograms, however, i
will be alocal variable to which it is not possible for pi to
point. The compiler normally makes this assumption, that is,
that *pi cannot be equivalent to i, and therefore can retain the
value computed in the first statement for i in aregister, which
saves having to reload it to perform the multiply operation in
the third statement.
On the other hand, there are rare cases where this assumption is
not valid. Cprogrammers almost never code sequences such as:
pi =U;
*pi =12;
but more subtle cases of pointer overlap can occur, particularly
when both the pointer and its target are externa1iy defined. For
these cases, the -a compile-time option is provided (Section
4.1.1);, this forces the compiler to assume worst-case aliasing
(which is compiler jargon for pointer overlap) when generating
code. The compiler is so designed because instances of pointer
overlap are more the exception than the rule. Thus, rather than
default to worst-case assumptions that produce correct code in
all cases and unnecessary inefficiencies in most cases, the
compiler normally makes afavorable assumption that produces
efficient code which works correctly in nearly ali cases.
Afinal note on this subject: even when the -a option is used,
the compiler assumes that only objects of the pointed-to type can
be changed in pointer assignments. Thus, if an int pointer is
used in an indirect assignment, only registers containing int
values will be discarded.
4.4 Memory Addressing Models
The segmented architecture of the 8086 and 8088 processors
presents special problems for the implementation of high level
languages. In order to provide programmers with the ability to
select the combination of efficiency and addressability needed
for aparticulat application, the compiler supports four
different sets of memory addressing assumptions, called memotY
models. Each is identified by asingle capital letter, and
reflects adifferent view of the addressing of functions and data
within aCprogram. These views can be expressed by the
limitation on the size of the respective space for program text
(the functions) and data objects (all the declared or
allocated data structures), as follows:
4-28
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Model Program Address Space Data Address Space
S64K 64K
Pup to Im 64K
D64K up to IM
Lup to IFI up to Im
The D and Lmodels use four-byte pointers, and the Pand Lmodels
generate FAR calls and returns. The S and Pmodels produce
compact, efficient code limited to addressing a64K data area,
while the Dand Lmodels allow access to all of the I megabyte of
available memory.
4.4.1 Choosing the Memory Model
The compiler is most efficient (both in terms of code size and
execution speed) for the Smodel. All of the examples in
previous sections have shown commands for compiling with the S
model, and this memory model is particularly recommended for
beginning Cprogrammers.
All of the functions in asingle program must be compiled and
linked with one and only one of the available memorjj models. In
other words, functions compiled for different models may not be
combined. It becomes important, 'therefore, to choose the right
memory model for the particular application. The tradeoff is
between efficiency and memory addressability. There are two
choices that must be made.
l. will the combined size of the functions in the program
be greater than 64K bytes? If not, one of the models
that uses NEAR calls (the sor Dmodels) should be
selected, as these are faster and require less code.
Otherwise, amodel that supports .F.A.R calls (the por L
models) should be selected. """ " "
2. Does the application require more than 64K bytes of data
storage? If not, one of the models that uses 2-byte
data pointers (the Sor Pmodels) should be selected,
because pointer operations are performed much more
efficiently in these models. If the program simply
needs access to specific memory locations beyond the
program's 64K address space, the library functions peek
and poke can be used, allowing the program to retain the
efficient 2-byte pointers. Otherwise, if data storage
in excess of 64K bytes is amust, amodel that uses the
4-byte data pointers (the dor ,[; models) must be
selected, even though this wÍll produce somewhat less
efficient code.
4.4.2 Compiling for the Memory Models
Generation of code for the various models is controlled by a
compile-time option specified on the first phase ([.Cl) of the
4-29
Lattice 8086/8088 CCompiler CompÉLer/Run-time Implementation
compiler. The -m option must be followed immediately (no spaces)
by aletter (either lower or upper case) specifying the desired
memory model. The model may also be specified as asingle
numeric digit from 0to 3. If no -m option is present, code is
generated for the Smodel.
Smodel: LCl filename (no flags)
Lcl filename -mS
Pmodel: LCl filename -mp
LCl filename -ml
Dmodel: LCl filename -mD
LCl filename -m2
Lmodel: LCl filename -ml)
LCl filename -m3
4.4.3 Linking programs
When using the various memory models, care must be taken to link
with the appropriate library (LCS.LIB, LCP.LIB, LCD.LIB, or
LCL.LIB). The compiler generates code segments with different
names for each model, which allows examination of the LINK map to
determine if code for different models has been erroneously
mixed. Only one of the following segment names should appear on
the link map.
Smodel: PROG (code group PGROUP)
Pmodel: CODE
Dmodel: Code (code group CGROUP)
Lmodel: PROG
Note that for the Pand Lmodels, several segments with the name
_CODE (or PROG) will be included (one for each separately, com-
piled module containing functions).
4.4.4 Code Generation for Pointer Operatiom
In the Sand Pmodels, pointers to the various data types consist
of the ÍÍ6—bit"offset of the low order (least significant) byte of
the data element. Since the ccmbined size of the data elements
in these models cannot exceed 64K bytes, the address of an item
is fully specified in 16 bits. Indirect data references are made
by loading the pointer into one of the indexing registers SI, DI,
or BX.
Function pointers differ in each of the memory models. In the S
and dmodels, pointers to functions consist of the 16-bit offset
of 'Éhe first byte of the code defining the function. In the .S.
model, this pointer is stored in two bytes, while in the D. model,
it is stored as the first two of four bytes (the last 'Ewo are
zero since they are not used, but are merely required to conform
to the four-byte size of other pointers in the .D model). In the .P
model, atwo-byte pointer (required because of the two-byte size
4-30
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
of data pointers) is used to store the offset of afour-byte
function address contained in the data section. This function
pointer has the same format as function pointers in the .L. model,
where the first two bytes contain al6-bit offset and the next
two contain the l6-bit segment base for the function.
The code generated by the Dand Lmodels uses four-byte pointers
and can therefore address any location in memory. These pointers
are stored as an offset portion in the low two bytes, followed by
abase portion in the high two bytes (the format expected by the
machine language instructions LDS and LES). objects are ad-
dressed from these pointers by Loading the base portion into the
extra segment register ES, the offset portion into an index
register, and using the segment override prefix for ES to force
the indexed operation to refer to the correct memory location.
Since there is only one ES register, such common operations as
copying from one pointer to another require ES to be reloaded for
each step in the copying process. Pointer references are there-
fore less efficient than in the 2-byte memory models.
The four-byte pointers used in the Dand Lmodels are manipulated
according to the following rules:
l. Pointer arithmetic is performed by adding or subtracting
a32-bit offset to the pointer, using acall to a
library routine. Thus, dynamically allocated arrays
(addressed by subscripting apointer variable) may be
larger than 64K, and address manipulations work properly
for all offset values. Note that, since the compiler
requires statically declared arrays (extern, static, or
auto) to be less than 64K bytes in size, only a16-bit
offset is used in accessing elements of these arrays,
resulting in more efficient code.
2. When two 4-byte pointers are subtracted, alibrary
routine is called which returns along result.
3. Conversions between long integers and 4-byte pointers
are automatically performed, again by calling library
routines.
4. Comparison of pointers for equality or relative rank is
performed by calling alibrary routine which converts
the pointers to normalized (canonical) form before
comparing. Thus, two pointers which have different base
and offset portions, but which actually point to the
same location will be recognized as equal.
5. Any function which returns apointer as its return value
calls alibrary routine which converts that pointer to
normalized (i.e., offset in the range 0to 15) form.
4-31
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
4.4.5 The -s Option for Four-byte É'ointers
While the above rules generally describe use of four-byte
pointers, the additional overhead of Library routine calls can be
inefficient if asignificant amount of pointer manipulation is
being performed. Aspecial compile-time option (specified on
LCl) is provided for knowledgeable users who are willing to work
within certain restrictions. Adding the -S flag to LCl causes
the following changes in the above rules:
l. Pointer arithmetic is performed by adding or subtracting
al6-bit offset tD the pointer. Thus, no single object
may be greater than 64K bytes in size.
2. Pointer arithmetic affects only the offset portion of the
pointer (not the base). When pointers are compared for
equality, an exact match of both base and offset portions
is required. When compared for relative rank, only the
offset portions are compared, so the comparison is
meaningful only if they are pointers to the same array.
3. when two pointers are subtracted, only the offset
portions patticipate in the operation, and the result is
ashort.
4. Pointers and long integers are not converted when one is
amigned to the other; instead, asimple copy operation
is performed.
5. The return value from afunction which returns apointer
is not normalized.
Most functions can be safely compiled with the -s option,
resulting in improved code generation quality. In fact, all of
the library functions written in Csupplied in the libraries are
compiled with the -s option, except,for the memory allocation
functionm Note that the'-3 flag has no effect on the sand' E
models. "
A8 noted above, the biggest potential problem when converting
code to use the four-byte pointers of the p. and L models is that
pointers and integers are no longer the same sizé. while it may
appear that aprogram's source code does Dot depend in any way on
this fact, programmers must be alert for subtle problems that
might relate to this. Here are three important cautions:
l. when supplying pointer arguments to Cfunctions,' it is
common practice to supply anull pointer (i.e., one that
does not point to anything) as the #define constant NULL,
which is defined as 0 by stdio.h. When compiling code
for the Dor Lmodels, NULL must be changed to DL so that
the null"poinfer value supplied to functions is the same
size as the pointer argument. Failure to do this will
cause the called function to incorrectly address its
parameters, resulting in serious problems.
4-32
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
2. The sbrk memory allocator is supposed to return avalue
of -l when no more memory is available (for compatibility
with other implementations). Under the ,D and .L. models,
the result of casting -l into acharacter pointer depends
on whether the -S option was used (see Sections 4.4.4).
Since the library function was compiled without the -s
option, the -l gets converted to the four-byte pointer
format. The result is that afunction compiled with the
-s option cannot properly test for the -l value! All of
these problems can be avoided by using the library
function lsbrk, which accepts along integer number of
bytes and returns zero if no morcz space is available (see
Section 3.1).
3. The four-byte pointers implemented under the ,D, and ,L,
models allow direct access to all of the memory on the
machine. This can be extremely useful, but it can also
be extremely dangerous. Memory on the 8086 and 8088
processors is not protected, and storing values via an
uninitialized pointer can crash the system -- or worse.
MS-DOS stores anumber of very important system elements
in lower memory, so that use of an uninitialized pointer
to store data can have disastrous consequences (such as
destroying the File Allocation Table (FAT) for ahard
,disk!). Programmers should exercise extreme caution when
using these memory models. Beginnin9 programmers ,a.t.e
advised to use the So,r. Pmodels, where uninitialized
pointers are much less likely .tg. access critical
locations.
4.4.6 Creating an Array Greater than 64K Bytes
Since static data in all of the memory models is limited to a
maximum of 64K bytes, the only way to create an object of greater
size is through the memory allocation functions.
t
Suppose that an array of 10,000 double precision values must be
allocated; 80,000 bytes of storage will be required for such an
array. First, apointer must be declared which will contain the
array's address after allocation:
double "d;
Note tbat asimple double pointer is all that is needed, despite
the fact that it will actually point to an array. Next, the
memory allocation function
char "getml();
must be declared.
Also note that the memory allocation function must be declared to
return apointer; otherwise, the compiler will assume it returns
4-33
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
an int and the cast operation shown below will not work
correctly. The array is then allocated by the expression:
d=(double *) getml(80000L);
Note the L(el) specifier on the constant. The size could also
be specified as (I0000L *sizeof(double)). (Note: if the size
argument for getml is computed using amultiplication expression,
be sure that one of the operands is along constant or is cast to
along before the multiplication; otherwise, the compiler will
perform the multiplication in short arithmetic and obtain an
incorrect result. If the example above is written as
((long)(10000 *sizeof(double)), the size argument is incorrectly
computed as 14464!
The returned pointer, of course, must be checked for null (zero)
before use; NULL is returned if there is not enough memory
available for the requested allocation. The variable dcan now
be subscripted as if it were an array, i.e., d[12] will address
the thirteenth (13th) element of d, etc. In this example, the
number of elements in the array is less thañ 64K, so ordinary int
variables can be used as subscripts; it achar array had been
allocated, long integers would be needed to subscript an array of
this size. Also note that since an object with asize greater
than 64K is being addressed, the -S option cannot be used.
4.5 Run—time Program Structure
This section describes the structure of Cprograms under the
8086/8088 MS-DOS implementation of the Lattice Ccompiler. Some
knowledge of the architecture of the 8086 processor and of the
8086 object code and linkage concepts is required in order to
understand much of the information presented. Readers who are
not interested in the precise technical details of the hardware
implementation may safely skim through or skip over this section;
it is primarily intended for programmers who must provÍde an
interface between Cand assembly language.
postponing discussion of the specific object code details used to
create it (see Section 4.5.1 below), the general structure of aC
program is illustrated by the diagrams on the next page.
4-34
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Sand P Models
High Address <- SP
stack
(auto data)
dynamic memory
static data
<- DS, ES, SS
f6aoctóom
Low Addre88 <- CS
Dand L models
High Addrem -
dynamic
memory
<- SP
8tack
(auto data) <- SS
static data
"——_"" <~ DS
functions
Low Addre8s ------- <- CS
The C programming language provides for three basic kinds of
memory allocation: the instructions which make up the executable
functions, the static data items which persist independently of
any of the functions which refer to them, and the automatic data
items which exist only while afunction is invoked. Most
implementations (including this one) support, through library
functions, an additional dynamic memory allocation facility which
returns pointers to objects not explicitly declared. The
diagrams above show the way these allocations are made; as one
might expect, the auto data items are allocated on the 8086
hardware stack.
4-35
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Two different memory layouts are used, depending on the size of
pointers. In either case, the functions are grouped together in
the lowest portion of the address space defined by the program,
and the static data items are grouped together immediately above
the functions. In the S and P models, the segment registers DS,
ES, and SS all. contain the same value, which is the base segment
address for all of the static data items in the program. The
stack pointer SP is initialized to point to the highest available
offset relative to this segment; this value is X'FFF0' if
sufficient memory is available, and is adjusted acc: ordingly if
less than 64K bytes of memory remain above the data segment base.
Acertain number of bytes is reserved for the stack, which grows
downward. The remainder of memory between the end of the static
data items and the lowest address allotted to the stack is
available fot dynamic memory allocation using library functions.
The stack overflow detection mechanism described in Section 4.5.'5
can be used to prevent stack allocations from exceeding the
allotted space and colliding with the dynamic memory pool or the
static data items. The stack size override feature described in
Section 4.1.4 allows the number of bytes to be reserved for the
stack to be specified when aprogram is executed.
In the Dand Lmodels, the stack resides immediately above the
static áata arz·a, and the free memory pool (allocated by the
functions described in Section 3.1) is above the stack, which can
be as large as G4K bytes. Segment register DS points to the base
of the static data area, SS points to the base of the stack, and
ES is undefined. The stack pointer SP is initialized to contain
the number of bg"tes allocated for the stack (defined in _stack;
see Section 4.5.S). As noted above, the stack overflow detection
mechanism prevents collision with the static data elements.
4.5.1 object Code conventiom
The object file created by the second phase is in the standard
ms-dos object code format, which is compatible with the Intel
8086 object module format. The object file defines the
instructions and data necessary to .implement the module specified
by the Csource file, and also contains relocation and linkage
information necessary to guarantee that the components will be
addressed properly when the module is executed or referenced as
part of alinked program. In order to force the parts of the
module into,the proper locations after linking, the object file
defines two logical segments which are marked for concatenation
with other segments of the same name.
The program segment is the segment which includes the
instructions which perform the actions specified by any functions
defined in the source file. As noted in Section 4.4.3, the
segment name used for the program segment depends on the memory
model.
DATA is the segment which includes all static data items which
are defined in the source file. This includes not only those
data items explicitly' declared static but also items declared
4-36
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
outside the body of afunction without an explicit storage class
speCifier, string constants, and double precision constants.
(Auto data items are simply allocated on the stack at run time
and are not explicitly defined in the object file.)
The DATA segment is defined to be combinable with other segments
of the same name. In the Sand Dmodels, the program segment is
also made combinable. Program segments combine with byte-
alignment, that is, as closely as possible; data segments combine
with word-alignment. Thus, no space is wasted when functions are
combined during linking, and the word alignment of elements
within aparticular DATA segment is preserved after combination.
This alignment of data items is important for efficient data
fetches on the 8086, where word fetches from an odd byte address
require an additional four clock periods. Note that although a
compile-time option (described in Section 4.1.1) allows the
alignment requirement for data items within aparticular module
to be relaxed, the word alignment of DATA segments during linking
is not affected.
The net effect of these segment definitions is to force, at link
time, all functions to be collected together and all static data
items to be similarly combined. Thjs achieves the most important
part of the program structure diagrammed above. The segment
directives needed to combine assembly language modules with C
modules are shown in Section 4.5.4.
4.5.2 Linkage Conventions
The 8086 qroup concept is used to guarantee that the data portion
of the final linked program does not exceed 64K bytes; in the ,S.
and Dmodels, it is similarly used to force the combined program
section to fit into 64K. The groups which may be defined are:
PGROUP "BASE segment +PROG segment (S model)
CGROUP XBASE segment +·CODE 8egment (D model)
DGROUP XDATA segment +STACK segment (all modeIM
The PROGRAM and DATA segments are obtained from the Cmodules in
the program, as previously discussed. The other two segments are
defined in the startup module (CS.OBJ, CP.OBJ, CD.OBJ, or
CL.OBJ), which must be the first module encountered during
linking. The BASE segment serves two purposes: (I) it forces
PGROUP (or CGROUP) lower in memory because it is the first
segment within the startup module, and (2) it contains abyte
which identifies the memory model used. The latter feature allows
programs to be examined with aprogram debugger to determine the
memory module used when the program was linked. The STACK segment
has adual role as well: (I) it defines the base of the stack
and dynamic memory portion of the data section of the program,
and (2) it satisfies the linker's need for asegment of type
STACK (if one is not encountered, the linker generates awarning
message).
4-37
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
The startup module (CS.OBJ, CP.OBJ, CD.OBJ, or CL.OBJ) also
defines its own program and DATA segments. The PROGRAM segment
defines the initial execution address of the linked program. The
segment registers are initialized, and the amount of memory
remaining above the STACK segment is determined. The stack
pointer is adjusted to its initial value, as noted in the
discussion in Section 4.5. In the DATA segment of the star"tup
module, the address of the stack base and top are saved for use
by the memory allocation functions. At the top of the stack, the
address of the program segment prefix is saved so that an orderly
return to MS-DOS can be made when the program terminates. The
characters from the command line which executed the program are
transferred from the program segment prefix to the stack. A
pointer to this copy of the command line is then passed to the
function main, which begins execution of the program (see
Section 5Á).
As noted in Section 4.2.2, extetnal names differ from ordinary
identifiers in Cin that upper and lower case letters are
equivalent. All external names are defined as an unspecified
type, that is, there is no set of attributes associated with the
name; it is simply an offset within one or the other of the two
defined groups. It is therefote an error to define two items
with the same external name in the same progtam. It is the
programmer's responsibility to prevent this occurrence and also
to make sure that programs refer to external names in a
consistent way (i.e., afunction should not refer to xyz as long
when it is actually defined as int in some other module).
External definition and reference from assembly language modules
are discussed in Section 4.5.4.
See the appropriate linker documentation for information on how
to obtain apublic symbol map for alinked program. As a
convenience, the DGROUP segments are defined with class name
DATA, the PGROUP segments with class name PROG, and the CGROUP
segments with the class name CODE.
4.5.3 Function Call Conventions
When aCfunction makes acall to another function, it first
pushes the values of any arguments onto the stack and then makes
acall to that function. a NEAR call (which changes IP but not
CS) is used in the Sand .D. models; aFAR call (which changes both
IP and CS) is used in the pand Lmodels. The argument values are
pushed in reverse (right-to-left) order because the stack grows
downward on the 8086; this allows the called function to address
the arguments in the natural left-to-right (low-address-to-high-
addre3s) order. The first actions taken by the called function
are:
I. The BP register is pushed onto the stack; this saves the
value of BP used by the caller.
2. The stack pointer SP is reduced (i.e., av.alue is
subtracted from it) by the number of bytes of stack
4-38
ittice 8086/8088 CCompiler Couipiler/Run-time Ímplementation
space required by the called function. This value is
rounded to the nearest word sq that the stack pointer is
always word-aligned. The stack space includes all auto
data elements declared in the function, and also may
include additional space for the temporary storage
locations which are often required during expression
evaluation. If no auto items or temporaries are needed,
this step is skipped; SP is unchanged.
3. If the function was compiled with stack overflow
detection, it then checks the stack pointer for alegal
value, as described in Section 4.5.5. If stack overflow
is detected, control is routed to tbe entry point XCOVF
(defined in the startup module) by means of ajump
instruction.
4. The stack pointer SP is moved into BP to allow
addressing of the elements on the stack: function
arguments, auto storage, and temporaries.
he offsets of the varÜjUB componenü are indicated by the
ollowing diagram. Note that of the registers used by the
ailing program, only BP is saved.
High -<- Caller's BP
argumenU
00e
return addreB8
(2 or 4byte8)
callerW 8aved BP
auto data items
temporarie8
Low <- BP, SP
uring execution of aCfunction, BP and SP normally contain the
ame value. The temporaries are allocated closest to BP,
ollowed by the auto elements declared, in the order of their
eclaration. This addressing scheme has the disadvantage that
he arguments supplied to the function are at an offset
etermined in part by the amount of auto storage declared. If
he function declares more than approximately 124 bytes of auto
torage, the arguments require an additional offset byte in the
nstructions which refer to them.
he compensating advantage to this mechanism appears when a
unction calls another function and supplies it with argument
alues. Because aCfunction may in special cases have a
ariable number of arguments (printf is the classic example), the
ailed function cannot deallocate the stack space used in pushing
4-39
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
the argument values; the calling function must do so. By
retaining the normal SP value in BP, Lattice Cfunctions can
restore the stack pointer after afunction call with the two-byte
instruction:
MOV SP,BP
If BP is not set up in this way, avalue must be explicitly added
to SP, which requires athree- or four-byte instruction.
Asecond advantage to this technique is that it is easy to
implement assembly language functions (to be called from C) with
avariabte oumber of arguments. Since the caller's BP contains
the value in SP before argument values were pushed (as the
diagram shows), it defines the upper limit for the address of any
arguments. In other words, only the space between the saved
return address arjá the address in the caller's BP register can
contain arguments.
When afunction returns to its caller, it first loads the
function return value, if any, into predefined registers. The
size of the value returned determines the register(s) used:
16 bits AX register
32 bits (AX,BX) register pair
64 bits (AX,BX,CX,DX) register quadruplet
In the multiple register returns, AX contains the high order bits
of the value. Note that in the dand Lmodels, this means that
the segment portion of apQinter return value is contained in BX
and the base portion in AX.
After the return value is loaded, the function adds to sp the
sanie value that was subtracted on entry. Then BP is popped,
restoring the caller's base pointer, and anear return is
executed. The calling function now regains control, and must
restore SP if any argument values were pushed.
4.5.4 Assembly Language Interface
Programmers may write assembly language modules for
inclusion in Cprograms, provided that these modules adhere to
the object code, linkage, and function call conventions described
in the preceding sections. In order to facilitate assembly
language programming for the various memory models, four macro
libraries have been provided as part of the compiler package.
These libraries define values for symbols which can be tested for
conditional assembly purposes, including:
LPROG Ifor por Lmodel, 0otherwise
DATA lfor 6or ímodel, 0othew*S8e
8086 lfor Smo&íi, 0otherwise
8086 lfor Fmodel, 0otherwise
8086 lfor 6model, 0otherwise
8086 lfor kmodel, 0otherwise
4-40
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Also defined are four special macros, used to delimit the
beginning and end of the program and data segments:
PSEG defines start of program segment
ENDPS define8 end of program segment
DSEG defines start of data segment
ENDDS defines end of data segment
In order to use these symbols and macros, an INCLUDE statement
must be used at the beginning of the assembly language module.
For example:
INCLUDE DM8086.MAC
makes available the symbol and macro definitions for the Dmemory
model. By using the generic include file named DOS.KAC, an
assembly language module can be assembled under any of the
models, as long as the appropriate header file is copied to
DOS.MAC before the module is assembled.
An assembly language module which defines one or more functions
to be called from Cmust define the start of the program segment:
PSEG
followed by PUBLIC declarations of the functions:
PUBLIC AFUNC, ...
followed by' the functions themselves:
AFUNC PROC NEAR/FAR
WO0
ENDP
Note that the PROC statement must define the function NEAR in the
Sand Dmodels, and FAR in the Pand Lmodels. The function must
conform to the conventions detailed in Section 4.5.3. If avalue
is to be retutned by the function, it must be placed in the
appropriate register(s).
To call afunction from assembly language, an EXTRN declaration
most be included for that function, and the caller must supply
any expected arguments in the proper order (see Section 4.5.3).
Note that the position of the EXTRN statements for functions is
critical: lor the Pand Lmodels, they mast appear before the
program segment definitions:
EXTRN XYZ: PAR,
PSBG
AFUNC PROC FAR
For the S and D models, they must appear after the definition of
the program segment:
4-41
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
PSEG
EXTRN XYZ: NEAR, ...
AFUNC PROC NEAR
An assembly language module may also define data locations to be
accessed (using "extern" declarations) from Cprograms:
DSEG
PUBLIC DXI,DX2,DX3
Dxl DW 4000H
DX2 DW 8000H
DX3 DB 'Text string',0
ENDDS
Note that if the address of an item is to be defined, the name
must be prefixed with the group name if it is used as the operand
of the OFFSET operator or of the DW or DD statements. If DX4 is
used to define the address of DXl in the example above, it must
be coded:
DX4 DW DGROUP: DXI
Otherwise, asegment-relative offset is generated, which will not
be the actual address of the item as it is defined within the
context of aCprogram. (NQte: the prefix is not required for
the LEA instruction, which refers to the current ASSUME
directive.)
Similarly, to refer to data elements defined in aCmodule,
include appropriate EXTRN statements:
EXTRN XDI:WORD,XD2:BYTE
W
V
0
MOV AX,XDI
Note that any EXTRN statements for data elements must be defined
within aDATA segment declaration like the one shown previously.
The BYTE attribute rñu8t be used for external char items. If an
element is larger than aword, aSTRUC can be used to define it,
or its off8et can be loaded into an index and used to fetch its
component parts. The same caution about addresses requiring a
group prefix applies to an external reference. For example:
DW DGROUP: XDI
must be used to define the address of XDl. Otherwise, asegment-
relative offset is generated, which will not be the actual
address of the item as it is defined within the context of aC
program. Note that the prefix is not required for the LEA
instruction, which refers to the current ASSUME directive.
4_42
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Upper and lowet case letters for external names (and for all
symbols within assembly language modules) are equivalent, so an
assembly language function XYZ can be called from Cas either XYZ
or xyz.
Assembly language functions need to preserve BP only, as the
compiler does not make any assumptions regarding register
contents following afunction call (except for return values).
As noted above, DS always points to the base of static storage
for any of the memory models, so assembly language functions must
be careful not to change DS. In the Sand .P, models, ES must also
be preserved (but not in the Dand LÑodelsj.
Note the differences between the use of pointers in the Sand .P.
models from their usage in the !2 and .L. models, as in the
following example:
S/P model: MOV BX,[BP].ARG1 ;get apointer arg
MOV AX,[BX] ;use it
D/L model: LES BX,[BP].ARGI ;get offset and base
MOV AX,ES: [BX] ;use it
The following example (supplied with the compiler package as the
file IO.ASM) illustrates many of the above requirements, and also
demonstrates the use of DOS.MAC and conditional assembly fer the
different memory models.
TITLE PORT I/O FUNCTIONS
SUBTTL Copyright 1982 by Lattice, Inc.
NAME PORTIO
INCLUDE DOS.MAC
IF LPROG
X EQU 6;OFFSET OF ARGUMENTS
ELSE
XEQU 4;OFFSET OF ARGUMENTS
ENDIF
PSEG
-kik
ir
O
V
;name inp -- input byte from port
W
W
;synopsis c = inp(port);
;int c; returned byte
;int port; port address
e
V
;de8cription This function inputs abyte from the specified por
;addre88 and returns it as the function value.
O
r
·**
GPUBLIC INP
IF LPROG
4-43
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
INP PROC FAR
ELSE
INP PROC NEAR
ENDIF
PUSH BP ;SAVE BP
MOV BP,SP
MOV DX,[BP+X] ;GET PORT ADDRESS
IN AL,DX ;'3ET INPUT BYTE
XOR AH,AH ;CLEAR HIGH BYTE
POP BP
RET
INP ENDP
PAGE
·**
P
0
V
;name outp -- output byte to port
0
r
;synopsis outp(port,c);
;int port; port address
;int c; byte to send
0
B
;description TFÜs function sends t-he specified character to
;tbe specified port.
H
V
·**
IPUBLIC 'JUTF
IF LE'ROG
OUTP PROC FAE'
ELSE
OUTP PROC NEAR
ENDIF
PUSH BP ;SAVE BP
MOV BP,SP
MOV DX,[BP+X) ;GET PORT ADDRESS
MDV AX,[BP+X+2} ;GET OUTPUT BYTE
OUT DX,AL
POP BP
RET
OUTP ENDP
ENDPS
END
4.5.5 stack Overflow Detection
The compiler, by default, generates code at the beginning of each
function to check for stack overflow. The cost in code size for
each function is 9bytes for tbe Sand D models, and li bytes for
the Pand Lmodels. The benefit is elimination of avery nasty
class of etrors which can be very difficult to find. When stack
overflow is detected, the error message:
*"* STACK OVERFLOW ***
is written to the console, and the program terminates immedi-
ately.
4-44
Lattice 8086/8088 CCompiler Compiler/Run-time Implementation
Stack overflow occurs when the program fails to supply sufficient
storage for the run-time stack. The number of bytes of storage
for which the stack is set up is defined in the external location
stack, and can be changed when the program is executed by the
Jnnn Option on the command line. The size of the stack can thus
be set in any of three ways:
l. If no definition for stack is found in the user's
object modules during linking, the Lattice Clibrary
provides adefinition of _stack containing 2048 (2K).
Thus, the default stack size is 2048 bytes.
2. If one of the user's object modules includes a
definition for stack, that value will be used. All
that is required is that astatement such as
int stack =4096;
appear outside the body of afunction. That value then
becomes the default stack size.
3. Either one of the above methods can be overridden at
execution time (after linking) by executing the program
with acommand such as
PROGNAME =8000
The decimal value after the equals sign becomes the
stack size during execution of the program.
Unfortunately, there is no hard and fast rule for determining how
much stack space aprogram will need. At least as much storage
as the largest amount of auto storage declared in any of the
functions included in the program will be needed (i.e., if a
function has an auto array of 4000 bytes, at least that much
stack space is needed, because auto data items are allocated on
the stack). Since Cfunctions typically call other functions,
the storage needed by the called function must be added to that
needed by the caller, and so on. The intention in supplying the
various setting mechanisms described above is to make the stack
size easily adjustable.
The code for stack overflow detection can be eliminated by com-
piling your source file with the -v option on LC2 (SecÉion
4.1.2). Library functions are supplied with stack overflow
detection included.
4-45
Lattice 8086/8088 CCompiler System Library Implementation
SECTION 5:
System Library Implementation
Although the portable library functions described in Section 3of
this manual define ageneral purpose interface to the typical
environment provided for Cprograms, there are inevitably many
details and variations which are system-dependent. In this
section, some of the details of the MS-DOS library implementatior
are presented in order to clarify the peculiarities of this
particular environment.
Fortunately, MS-DOS supports anumber of powerful features which
allow afull implementation of the standard file I/O functions,
although the representation of text files presents aminor
problem; Section 5.1 discusses file I/O. Several standard device
names are also supported by MS-DOS, and the Lattice CI/C
interface processes these in special ways, as explained ir
Section 5.2. The structure of Lattice Cprograms (see Sectior
4.5) allows the full set of memory allocation functions, althougF
care must be taken to provide sufficient space for the stack, aj
Section 5.3 warns. The basic program entry and exit functiom
are described in Section 5.4, and some special functions unique
to the MS-DOS implementation are presented in Section 5.5. As
additional functions wilt probably be provided as the compiler
evolves, the programmer should check the addendum for the current
version of the compiler.
5.1 File I/O
Filenames are specified according to the following format:
d:\pathname\filename.ext
where d,: . is an optional drive specifier, pathname is an optional
directory specifier, filename is the name of the file, and ,±u!
is the file extension. If the drive specifier is omitted, the
currently logged-in disk is used; if the pathname is omitted, the
current directory is used. The filename is specified without
trailing blanks if less than 8characters; the extensior
(including the ".") must be omitted if one is not defined for ttiÉ
file. Alphabetic characters may be supplied in either upper or
lower case; actual filenames use upper case letters only. Only
those characters which are legal for filenames under MS-DOS are
acceptable; consult the MS-DOS documentation for details.
Certain names are recognized as devices rather than files; seE
Section 5.2.
The level II/O functions perform disk I/O by making direct calls
to MS-DOS, so that all buffering is performed by the operatinc
system. Programs using the level 2I/O functions cannot use the
rbrk function, because fopen allocates abuffer using getmem.
In the MS-DOS implementation, both the level 2(fopen, putc,
getc, fclose) and the level l(open, creat, read, write, close)
5-I
Lattice 8086/8088 CCompiler System Library Implementation
I/O functions are limited to 20 open files, including devices,
and including the three (stdin, stdout, stderr) which are
automatically opened for the main program. Note that the number
of files available under MS-DOS version 2is also affected by the
CONFIG.SYS file, since an MS-DOS file handle is used for every
open file (see MS-DOS documentation).
The portable library provides asystem-dependent option when a
file is opened or created; the programmer may select one of two
modes of I/O operation while afile is open. On some systems the
modes are in fact the same, but in the MS-DOS implementation they
differ in some important details.
Translated or text mode is the default condition. In this mode,
the line terminator normally used by Cprograms (a single newline
character, \n or 0x0A) is translated to the MS-DOS line
terminator, which consists of the two characters, carriage return
and linefeed (0X0D fcñlowed by 0X0A). This translation is
performed when the file is written using calls to the write
library function; the inverse translation is performed when the
file is read using the read library function. programs which use
the higher level I/O functions (putchar, getchar, printf, etc.)
ate usually not affected, but programs which call read and write
directly must beware of these translations. On read calls, the
count returned may be less than the actual number of bytes by
which the file position was advanced (because of CR deletions).
Note that all carriage returns are discarded when reading from a
file in the translated mode; similarly, all linefeeds are
expanded to CR/LF when writing to the file.
Untranslated or binary mode is an option which can be selected
when the file is opened or created. By adding 0x8000 to the mode
for the open call or to the access privilege mode word for the
creat call, the programmer indicates that read/write operations
on the file are to be performed without translation. In this
mode, bytes are transferred between the caller's area and the
file without modification. This option must be used for files
containing binary data; otherwise data bytes which happen to take
on CR and LF values will be translated incorrectly.
In addition to the file I/O modes discussed above, two other
functions should be clarified under the heading of file I/O. The
creat function gets asystem-dependent argument, the access
privilege mode bits; these are ignored under the Ms-nos
implementation, except for bit 15 (the 0x8000 bit) which, if set,
causes the file to be accessed in untranslated or binary mode.
The lseek function has an offset mode, not always implemented,
which specified an offset relative to the end of file. Because
MS-DOS retains the exact file size in its directory, this mode
can be and is implemented in this version.
5.2 Device I/O
Several special file names are checked for by the Lattice I/O
interface under MS-DOS, and processed using single character
S-2
Lattice 8086/8088 CCompiler System Library Implementation
reads and writes. These device names may be specified in either
upper or lower case, but will be recognized by the level lopen
and creat functions only if the trailing colon is suppliéá. If
the colon is omitted, the name is passed to the operating system
and may be processed specially by it; however, the level l
functions will deal with adevice reference sans colon as if if
were areference to adisk file. The device names recognized are
as follows:
Console CON:
printer PRN: ,LST: ,LPT: ,LPTI
Aux port AUX: ,COM: ,RDR: ,PUN:
Null NUL: ,NULL:
I/O is performed to these devices, one character at atime, using
the appropriate BDOS function calls. One exception occurs for
the console device: if atranslated mode ,r.e.a.d. operation requests
more than lbyte, the BOOS buffered console input function is
used to read the data (a maximum of 128 bytes per read). Any
special editing features supported by the operating system
(backspace processing, etc.) will therefore be enabled.
The following table lists the devices and the corre6ponding BDOS
functions used for read and write operations in translated and
untranslated modes.
Device Translated Mode Untranslated Mode
Name Read FN Write FN Read FN Write FN
CON l2 7 6
AUX 343 4
corn 3 4 3 4
PRN 55
LPTI 55
NUL --- -
A-for the function number indicates that the correspondiDg
operation is not supported for that device. The read function
returns end of file (count =D) if read is not supported. If
writing is not supported, the write function returns anormal
count indicating success, but does not actually send the data.
An additional special device name, specified by aNULL string
("", which consists of just a'\0'), is recognized and processed
as if CON: had been specified.
In translated mode, anewline (0x0A) is converted to acarriage
return/linefeed sequence. Acarriage return on input is
converted to anewline, and terminates the read operation even if
the byte count is not satisfied. In untranslated mode,
characters are sent without modification, and read operations do
not terminate until the requested number of characters has been
received. Note that aread operation to the console in
untranslated mode does not echo the characters received.
Programmers may also perform direct single character I/O
5-3
Lattice 8086/8088 CCompiler System Library Implementation
operations using the bdos function, and several additional
functions support direct I/O to the console. See Section 5.5 for
details.
If one of these devices is opened for access using fopen, input
and output are performed in unbuffered mode, which means that
single characters are received and sent immediately. The only
exception to this rule occurs for stdin, which main opens in
buffered mode so that the buffered console input function can be
used. If desired, stdin can be changed to the unbuffered mode
using setnbf; see Section 3.2.2 for more information.
+
5.3 Memory Allocation
The full set of memory allocation functions described in Section
3.1 is provided under MS-DOS. The following cautions apply:
l. The reset functions rstmern and rbrk cannot be used if
any of the level 2I/O functions are also being used on
currently open files. Note that only disk files
allocate afile access block using getmem; the reset
functions may be used if the only open files are
actually connected to devices. Afile may be closed,
then re-opened after the reset function is called;
however, any file pointers must be updated if this is
done, because there is no guarantee that the same value
will be returned when the file is opened again.
2. The dynamic memory used by the memory allocation
functions is the same memory used for the run-time
stack. Programmers must be careful to provide enough
space for the stack to prevent its collision with the
dynamic memory pool, either by getting an override value
from the command line (see Section 4.1.4) or by defini'ng
an external int location called _stack and initializing
it with adesired value. See Section 4.5.5 for a
complete discussion of the stack size.
3. Programmers who wish to implement their own memory
allocation functions can refer to the data locations in
the startup module which define the total stack space
available:
extern umigned _base;
contaim the offset (from DS) of the lowest portion of
the stack, which is the same as the highest offset of
the static data items in the program (see diagram at
Section 4.5).
extern unsigned _top;
contains, in the Sand Pmodels, the offset of the top
of the stack, either X'FFF0' or whatever was determined
to be the highest usable offset; in the 9and Lmodels,
5-4
Lattice 8086/8088 CCompiler System Library Implementation
it contains the number of bytes allocated for the stack
(same as stack). As noted above, the external location
stack contains the default or specified stack size
aesired; user-written memory allocators may wish to make
use of that value, as aconvenience.
5.4 Program Entry/Exit
The startup module CS.OBJ (or CP.OBJ, CD.OBJ, or CL.OBJ) calls
main to begin execution of aCprogram, and passes to it acopy
Of the command line which executed the program. Actually,
because MS-DOS does not save the program name portion of the
command, the command line passed to main consists of the
characters "c " (lower case 'c' followed by ablank) immediately
followed by all of the characters typed after the program name.
The standard version of main supplied in the libraries analyzes
the command line for all of the elements described in Section
4.1.4, and then passes the command-line arguments to main. If
the stack override and file specifier features are not needed,
the version supplied as TINYMAIN.C can be used instead. Please
note the following important cautions if this is done.
I. The library function printf sends its output to the pre-
defined file pointer stdout, which is normally opened by
main. If the code that performs this function is
Femovecí, printf calls will produce no visible output
(the I/O library functions ignore attempts to read or
write unopened files). asimilar caveat applies to the
use of 8canf, which reads from stdin.
2. If the goal is to avoid including the level 2I/Q
functions in the linked program, the library function
exit should not be called, since it closes all buffered
output file before terminating execution and
automatically causes level 2functions to be included.
Call _exit instead.
The program exit functions exit and exit are aescFibed irt
Section 3.2.4. The error code argumenf is passed back to thq
operating system, where it can be tested in abatch file using d
command such as:
if error level Igoto error
5.5 Special Functiom
The functions discussed in this section provide low-level access
to various system resources. They tend to be machine-dependent
and are therefore not portable.
5+5
Lattice 8086/8088 CCompiler System Library Implementation
NAME
bdos -- call BDOS function
SYNOPSIS
ret =bdos(fn,dx);
int ret; returns code
int fn; BDOS function number
int dx; value to be placed in DX
DESCRIPTION
Performs aBDOS call by placing fn in the AH register, dx in
the DX register, and operating an INT 21H. The value
returned by BDOS in the AX register is passed back as ret.
CAUTIONS
In the Dand Lmodels, it is better to use the intdosx
function aescri6ed next, since some BDOS function calls need
apointer defined relative to DS, which may not contain the
correct segment base in these models.
5-6
Lattice 8086/8088 CCompiler System Íjibrary Implementation
NAME
intdos, intdosx -- generate DOS function call
SYNOPSIS
ret =intdos(inregs, outregs);
ret =intdosx(inregs, outregs, segregs);
int ret; operating system return code
union REGS '"inregs; input registers
union REGS *outregs; output registers
struct SREG "segregs; segment registers (intdosx only)
DESCRIPTION
Generates aDOS function request to the operating system.
The operating system specifications should be checked to
determine the DOS functions and calling sequences supported;
the values in the registers are used as inputs. In
particular, the exact function request is specified by
placing avalue in one of the registers (under MS-DOS, the
function number is specified in AH; under CP/M-86, in CL).
inregs must contain the values which will be loaded into the
working registers before the function call is made; outregs
will receive the values in the registers after control
returns from the function request. with intdosx, the values
which will be placed in the segment registers before the
interrupt may be specified; although the SREGS structure
defines all of the segment registers, only DS and ES will
actually be loaded. The REGS and SREGS structures are
defined in the DOS.H header file.
CAUTIONS
Defining the segment register values for intdo8x is best
acco%lished by calling segread to obtain current values
(see below for details on this function).
Note that inregs, outregs, and segregs are shown as pointers
above; the usual technique is to declare them directly, and
then use the address-of operator to pass apointer to them.
S-7
Lattice 8086/8088 CCompiler System Library Ímplementation
NAME
int86, int86x -- generate 8086 software interrupt
SYNOPSIS
int86(intno, inregs, outregs);
int86x(intno, inregs, outregs, segregs);
int intno; interrupt number
union REGS "inregs; input registers
union REGS *outregs; output registers
struct SREGS "segregs; segment registers (int86x only)
DESCRIPTION
Performs an 8086 software interrupt of the specified number.
The operating system should be checked to determine the
interrupts and calling sequences supported; generally,
values in the registers are used as inputs. inregs must
contain the register values which will be loaded into the
working registers before the interrupt is performed; outregs
yill receive the register values after control returns from
the interrupt. with int86x, the values which will be placed
in the segment registers before the interrupt can be
specified; although the SREGS structure defines all of the
segment registers, only DSand ES will actually be loaded.
The REGS and SREGS structures are defined in the DOS.H
header file.
CAUTIONS
The software interrupts on the 8086 are used to implement
multi-level system processing, and invalid input data can
cause unpredictable (and occasionally disastrous) results.
Defining the segment register values for int86x is best
accomplished by calling segread to obtain current values
(see below for details on this function).
Note that inregs, outregs, and segregs are shown as pointers
above; the usual technique is to declare them directly, and
then use the address-of operator to pass apointer to them.
5-8
Lattice 8086/8088 CCompiler system Library Ímplementation
NAME
segread -- return current segment register values
SYNOPSIS
segread(segregs);
struct SREGS "segregs; structure for return of values
DESCRIPTION
Places the current 8086 segment register values into the
SREGS structure whose pointer is supplied. Its main purpose
is to obtain current values in order to make asubsequent
call to int86x or intdosx. The definition for the SREGS
structure is found in the DOS.H header file.
5-9
Lattice 8086/8088 CCompiler System Library Implementation
NAME
movedata -- move data bytes from/to segment/offset address
SYNOPSIS
movedata(sseg, soff, dseg, doff, nbytes);
irjt sseg; segment portion of source address
int soff; offset portion of source address
int dseg; segment portion of destination address
int doff; offset portion of destination address
unsigned nbyte3; number of bytes to move
DESCRIPTION
Moves the specified number of data bytes from the source to
the destination address. The addresses must be specified as
(segment: offset) in accordance with the standard 8086 nota-
tion. This function is primarily intended for use in pro-
grams compiled using the Sand Pmodels; in the Dand L
models, the standard library function movmem can be used.
The segread function can be used to obtain segment register
values.
CAUTIONS
Memory is not protected on the 8086, so supplying invalid
parametem to this function can have disastrous results.
5~ I0
Lattice 8086/8088 CCompiler System Library Implementation
NAME
peek, poke -- examine/modify arbitrary memory locations
SYNOPSIS
peek(segment, offset, buffer, nbytes);
poke(segment, offset, buffer, nbytes);
int segment; segment portion of memory address
int offset; offset portion of memory address
char *buffer; local memory buffer
unsigned nbytes; number of bytes to transfer
DESCRIPTION
These functions copy data values between an arbitrary memory
location and alocal memory buffer: peek moves data to the
local buffer from aspecified memory address, while poke
moves data from the local buffer to the arbitrary memory
address. These functions are primarily intended for use in
programs compiled using the .S. and Emodels; in the ,D, and .L.
models, the standard library function movmem can be used.
CAUTIONS
Memory is not protected on the 8086, so supplying invalid
parameters to the poke function can have disastrous results.
5~ l I
Lattice 8086/8088 CCompiler System Library Implementation
NAME
inp, outp -- direct port I/O functions
SYNOPSIS
v = inp(p);
outp(p,v);
int v; I/O value
int p; I/O port number
DESCRIPTION
The inp function reads I/O port pand returns whatever data
is there. The outp function writes value vto port p.
CAUTIONS
Direct port operations can cause all sorts of problems,
including physical damage to some systemm Extreme care
should be exercised.
5~12
Lattice 8086/8088 CCompiler Error Messages
APPENDIX A:
Error Messages
This appendix describes the various messages produced by the
first and second phases of the compiler. Error messages which
begin with the text CXERR are compiler errors which are described
in Appendix B.
A.l Unnumbered Messages
These messages describe error conditions in the environment,
rather than errors in the source file due to improper
language specifications.
Can't create object file
The second phase of the compiler was unable to create the
.OBJ file. This error usually results from afull directory
on the output disk.
Can't create quad file
The first phase of the compiler was unable to create the .Q
file. This error usually results from afull directory on
the output disk.
Can't open quad file
The second phase of the compiler was unable to open the .Q
file specified on the LC2 command, usually because it did
not exist on the specified (or currently logged-in)
drive/directory.
Can't open source file
The first phase of the compiler was unable to open the .C
file specified on the Lcl command, usually because it did
not exist on the specified (or currently logged-in)
drive/directory.
File name missing
Afile name was not specified on the LCl or LC2 command.
Intermediate file error
The first phase of the compiler encountered an error when
writing to the .Q file. This error usually results from an
out-of-space condition on the output disk.
Invalid command line option
An invalid command line option (beginning with a-) was
specified on either the LCl or the LC2 command. See
A-I
Lattice 8086/8088 CCompiler Error Messages
Sections 4.1.1 and 4.1.2 for valid command line options.
The option is ignored, but the compilation is not otherwise
affected. In other words, this error is not fatal.
No functions or data defined
Asource file which did not define any functions or data
elements was processed by the computer. This error always
terminates execution of the compiler. It can be generated
by forgetting to terminate acomment, which then causes the
compiler to treat the entire file as a comment.
Not enough memory
This message is generated when either phase of the compiler
uses up all the available working memory. The onLy cure for
this error is either to increase the available memory on the
system, or (if the maximum is already available) reduce the
size and complexity of tbe source file. Particularly large
functions will generate this error regardless of how much
memory is available; break the task into smaller functions
if this occurs.
object file error
The second phase of the compiler encountered an error when
writing to the .OBJ file. This error usually results from
an out-of-space condition on the output disk.
A.2 Numbered Error Memages
These error messages describe syntax or specification errors in
the source file; they ate generated by the first phase of the
compiler. afew are warning messages that simply remark on
marginally acceptable constructions but do not prevent the
creation of the quad file. See Section 4.3.3 for more
information about error processing.
IThis error is generated by avariety of conditions in
connection with pre-processor commands, including specifying
an unrecognized command, failure to include white space
between command elements, or uge of an illegal pre-proce3sor
symbol.
2 The end of an input file was encountered when the compiler
expected more data. This may occur on an tinclude file or
the original source file. In many cases, correction of a
previous error will eliminate this one.
3 The file name specified on an Unclude command was not
found.
4An unrecognized element was encountered in the input file
that could not be classified as any' of the valid lexical
constructs (such as an identifier or one of the valid
A-2
Lattice 8086/8088 CCompiler Error Messages
expression operators). This may occur if control characters
or other illegal (i.e., high bit set) characters are
detected in the source file. This may also occur if a pre—
píocessor command is specified with the t not in the first
position of an input line.
5Apre-processor tdefine macro was used with the wrong number
of arguments.
6Expansion of a#define macro caused the compiler's line
buffer to overflow. This may occur if more than one lengthy
macro appears on a single input line.
7The maximum extent of iinclude file nesting was exceeded;
the compiler supports tinclude nesting to amaximum depth of
4.
8An invalid arithmetic or pointer conversion was specified.
This usually results when an attempt is made to convert
something into an array, astructure, or afunction.
9The named identifier was undefined in the context in which
it appeared, that is, it had not been previously declared.
This message is only generated once; subsequent encounters
with the identifier assume that it is of type int (which may
cause other errors).
10 An error was detected in the expression following the [
character (presumably asubscript expression). This may
occur if the expression in brackets is NULL (not present).
II The length of astring constant exceeded the maximum allowed
by the compiler (256 bytes). This will occur if the closing
"(quotes) are omitted in specifying the string.
12 The expression preceding the .(period) or -> structure
reference operator was not recognizable by the compiler as a
structure or pointer to astructure. This may occur even
for constructions which are accepted by other compilers; see
Section 2.1.
13 An identifier indicating the desired aggregate member was
not found following the .(period) or -> operator.
14 The indicated identifier was not amember of the structure
or union to which the .(period) or -> referred. This may
occur for constructions which are accepted by other
compilers; see Section 2.1.
15 The identifier preceding the (function call operator was
not implicitly or explicitly declared as afunction.
16 Afunction argument expression specified following the (
function call operator was invalid. This may occur if an
argument expression was omitted.
A-3
Lattice 8086/8088 CCompiler Error Messages
17 During expression evaluation, the end of an expression was
encountered but more than one operand was still awaiting
evaluation. This may occur if an expression contained an
incorrectly specified operation.
18 During expression evaluation, the end of an expression was
encountered but an operator was still pending evaluation.
This may occur if an operand was omitted for abinary
operation.
L
19 The number of opening and closing parentheses in an
expression was not equal. This error message may also
occur if amacro was poorly specified or improperly used.
20 An expression which did not evaluate to aconstant was
encountered in acontext which tequired aconstant result.
This may occur if one of the operators not valid for
constant expressions was present (see Kernighan and Ritchie,
Appendix A, p. 211).
21 An identifier declared as a structure, union, or function
was encountered in an expression without being properly
qualified (by astructure reference or function call
operator).
22 This non-fatal warning occurs when an identifier declared as
astructure or union appeared as a function argument without
the preceding &operator. Expression evaluation continues
with the &ássumed (i.e., apointer to the aggregate is
generated).
23 The conditional operator was used erroneously. This may
occur if the ?operator is present but the :was not found
when expected.
?4 The context of the expression required an operand to be a
pointer. This may occur if the expression following * did
not evaluate to apointer.
25 The context of the expression required an operand to be an
lvalue. This may occur if the expression following &was
not an lvalue, or if the left side of an assignment
expression was not an lvalue.
26 The context of the expression required an operand to be
arithmetic (not apointer, function, or aggregate).
27 The context of the expression required an operand to be
either arithmetic or apointer. This may occur for the
logical OR and logical AND operators.
28 During expression evaluation, the end of an expression was
encountered but not enough operands were available for
A-4
Lattice 8086/8088 CCompiler Error Messages
evaluation. This may occur if abinary operation is
improperly specified.
29 An operation was specified which was invalid for pointer
operands (such as one of the arithmetic operations other
than addition).
30 This non-fatal warning occurs when in an assignment
statement defining avalue for apointer variable, the
expression on the right side of the =operator did not
evaluate to apointer of the exact same type as the pointer
variable being assigned, i.e., it did not point to the same
type of object. See Section 2.1 for an explanation of the
philosophy behind this warning. Note that the same message
becomes afatal error if genera€e<i for an initializer
expression.
31 The context of an expression required an operand to be
integral, i.e., one of the integer types (char, int, short,
unsigned, or long).
32 The expression specifying the type name for acast
(conversion) operation or asizeof expression was invalid.
See Kernighan and Ritchie, Appendix A, pp. 199-200 for the
valid syntax.
33 An attempt was made to attach an initializer expression to a
structure, union, or array that was declared auto. Such
initializations are expressly disallowed by the language.
34 The expression used to initialize an object was invalid.
This may occur for avariety of reasons, including failure
to separate elements in an initializer list with commas or
specification of an expression which did not evaluate to a
constant. This may require sorne experimentation to
determine the exact cause of the error.
35 During processing of an initializer list, astructure, or
union member declaration list, the compiler expected a
closing right brace, but did not find it. This may also
occur if too many elements are specified in an initializer
expression list or if astructure member was improperly
declared.
36 This implementation does not allow initializer expressions
to be used for unions.
37 The specified statement label was encountered more than once
during processing of the current function.
38 In abody of compound statements, the number of opening left
braces {and closing right braces )was not equal. This may
also occur if the compiler got "out of phase" due to a
previous error.
A-5
Lattice 8086/8088 CCompiler Error Messages
39 one .of the Clanguage reserved words appeared in an invalid
context (e.g., as avariable name). See Kernighan and
Ritchie for alist of the reserved words (p. 180). Note
that entry is reserved although it is not implemented in the
compíler.
40 Abreak statement was detected that was not within the scope
of awhile, do, for, or switch statement. This may occur
due Lo an error in apreceding statement.
41 Acase prefix was encountered outside the scope of aswitch
statement. This may occur due to an error in apreceding
statement*
42 The expression defining acase value did not evaluate to an
int constant.
43 Acase prefix was encountered which defined aconstant value
already used in aprevious case prefix within the same
switch statement.
44 acontinue statement was detected that was not within the
scope of awhile, do, or for loop. This may occur due to an
error in apreceding statement.
45 adefault prefix was encountered outside the scope of a
switch statement. This may occur due to an error in a
preceding statement.
46 Adefault prefix was encountered within the scope of a
switch statement in which apreceding default prefix had
already been encountered.
47 Following the body of ado statement, the while claw'e was
expected but not found. This may occur due to an error
within the body of the do statement.
48 The expression defining the looping condition in awhile or
do loop was NULL (not present). Indefinite loops must
supply the congtant I, if that is what is intended.
49 An el8e keyword was detected that was not within the scope
of apreceding if statement. This may occur due to an error
in apreceding statement.
50 Astatement label following the goto keyword was expected
but not found.
51 The indicated identifier, which appeared in agoto statement
as a statement label, was already defined as a variable
within the scope of the current function.
52 The expression following the if keyword was NULL (not
present).
A-6
Lattice 8086/8088 CCompiler Error Messages
53 The expression following the return keyword could not be
legally converted to the type of the value returned by the
function. This may be generated if the expression specifies
astructure, union, or function.
54 The expression defining the value for aswitch statement did
not define an int value or avalue that could be legally
converted to int.
55 The statement defining the body of aswitch statement did
not contain at least one case prefix.
56 The compiler expected but did not find acolon (:). This
error message also may be generated if acase expression was
improperly specified, or if the colon was simply omitted
following alabel or prefix to astatement.
57 The compiler expected but did not find asemi-colon (;)·
TFÜs error generally means that the compiler completed the
processing of an expression but did not find the statement
terminator (;). This may also occur if too many closing
parentheses are included or if an expression is otherwise
incorrectly formed.
58 Aparenthesis required by the syntax of the current
statement was expected but was not found (as in awhile or
for loop). This may also occur if the enclosed expression
is incorrectly specified, causing the compiler to end the
expression early.
59 In processing external data or function definitions, a
storage class invalid for that declaration context (such as
auto or register) was encountered. This may also occur if,
due to preceding errors, the compiler begins processing
portions of the body of afunction as if they were external
definitions.
60 astorage class other than register appeared on the
declaration of aformal parameter.
61 The indicated structure or union tag was not previously
defined; that is, the members of the aggregate were unknown.
62 Astructure or union tag has been detected in the opposite
usage from which it was originally declared (i.e., atag
originally applied to astruct has appeared on an aggregate
with the union specifier). The Lattice compiler defines
only one class of identifiers for both structure and union
tags.
63 The indicated identifier has been declared more than once
within the same scope. This error may be generated due to a
preceding error, but is generally the result of improper
declarations.
Á-7
Lattice 8086/8088 CCompiler Error Messages
64 adeelaration of the members of astructure or union did not
contain at least one member name.
65 An attempt was made to define afunction body when the
compiler was riot processing external definitions. This may
occur if apreceding error caused the compiler to "get out
of pbase" with respect to declarations in the source file.
66 The expression defining the size of asubscript in an array
declaration did not evaluate to apositive int constant.
This may also occur if azero length was specified for an
inner (i.e., not the leftmost) subscript.
67 Adeclaration specified an illegal object as defined by this
version of C. Illegal objects include functions which
return aggregates (arrays, structures, or unions) and arrays
of functions.
68 Astructure or union declaration included an object declared
as afunction. This is illegal, although an aggregate may
contain apointer to afunction.
'69 The structure or union whose declaration was just processed
contains an instance of itself, which is illegal. This may
be generated if the " is forgotten on a structure pointer
declaration, or if (due to some intertwining of structure
definitions) the structure actually contains an instance of
itself.
70 Afunction's formal parameter was declared illegally; that
is, it was declared as a structure, union, or function. The
compiler does not automatically convert such references to
pointers.
71 Avariable was declared before the opening brace of a
function, but it did not appear in the list of formal names
enclosed in parentheses following the function íjame.
72 An external item has been declared with attributes which
conflict with aprevious declaration. This may occur if a
function was used earlier, as an implicit int function, and
was then declared as returning some other kind of value.
Functions which return avalue other than int must be
declared before they are used so that the compiler is aware
of the type of the function value.
73 In processing the declaration of objects, the compiler
expected to find another line of declarations but did not,
in fact, find one. This error may also be generated if a
preceding error caused the compiler to "get out of phase"
with respect to declarations.
74 During processing of external declarations, an attempt was
made to define afunction, but it was not the first
identifier declared on the input line.
A~8
Lattice 8086/8088 CCompiler Error Messages
75 An attempt was made to define the same function more than
once within the same source module.
76 The compiler expected, but did not find, an opening left
brace in the current context. This may occur if the opening
brace was omitted on a list of initializer expressions for
an aggregate.
77 In processing adeclaration, the compiler expected to find
an identifier which was to be declared. This may occur if
the prefixes to an identifier in adeclaration (parentheses
and asterisks) are improperly specified, or if asequence of
declarations is listed incorrectly.
78 The indicated statement label was referred to in the
previous function in agoto statement, but no definition of
the label was found in that function.
79 In processing alist of declared items, the compiler
expected aseparator (comma or semi-colon) but did not find
one. This usually results from an improperly specified list
of names being declared, or from an attempt to initialize an
object for which initialization is not permitted (such as an
extern object).
80 The number of bits specified for abit field was invalid.
Note that the compiler doe8 not accept bit fields which are
exactly the length of amachine word (such as 16 on a 16-bit
machine); these must be declared as ordinary int or umigned
variables.
81 The current input line contained areference to apre-
processor symbol which was defined with acircular
definition, or loop. See Section 2.2.1 for an example.
82 The size of an object exceeds the maximum legal size (which
is the largest positive int); or, the last object declared
caused the total size of declared objects for that storage
class to exceed that maximum. This may also occur if the
size of formal parameters exceeds 256 bytes.
83 This non-fatal warning complains of an indirect reference
(usually asubscripted expression) which accesses memory
beyond the size of the gbject used as abase for the address
calculation. It generally occurs when an element beyond the
end of an array is referred to.
A-9
Lattice 8086/8088 CCompiler Compiler Errors
APPENDIX B:
Compiler errors
This' appendix describes the procedure to be used for reporting
compiler errors. These are errors that result not from the
user's incorrect specifications but from the compiler itself
failing to operate properly. There are five general kinds of
errors which can occur:
I. The compiler generates an error message for asource
module which is actually correct.
2. The compiler fails to generate an error message for an
incorrect source module.
3. The compiler detects an internal error condition and
generates an error message of the form
CXERR: nn
where na is an internal error number.
4. The compiler dies mysteriously (crashes) while compiling
asource module.
5. The compiler generates incorrect code for acorrect
source module.
The last type of error is, of course, the most difficult to
determine and the most vexing for the programmer, who has no
indication that anything is wrong until something inexplicably
doesn't work; who OñÍY concludes that the compiler is at fault
after along and painstaking study of his or her own code.
Lattice, Inc. is anxious to know about and repair any compiler
errors as quickly as possible, so please report any problems
promptly. The difficulties encountered may be spared the next
programmer if this is done. In order to maintain a more precise
record of the bugs that are discovered, all problems should be
reported in writing to:
Lattice, Inc.
P.O. Box 3072
Glen Ellyn, Illinoi8
60138
In all cases, include the following items of information:
I. Alisting of the source module for which the error
occurred. Don't forget to include listings of any
tinclude files used (and watch out for tinclude file
nesting; don't forget the inner files as well).
Supplying the source on IBM PC-compatible disk format
will save time.
B-l
Lattice 8086/8088 CCompiler Compiler Errors
2. The revision number of the compiler, when it was
purchased and the serial number.
3. Your name and address and, if possible, atelephone
number with information about the best time to call.
4. Adescription of the problem, along with any other
information which may be helpful such as the results of
your investigation into the problem. Obviously, errors
of type 3(see above) don't need anything more than a
terse "Causes CXERR 23."
Our current policy in cc)operation with our publisher,
Lifeboat Associates in New York, calls for afree update
to the first finder of abona fide bug!
Meanwhile, attempt to code around the problem; if that
doesn't work, mutter afew curses directed at "lousy
compiler writers" and work on something else. Remember,
Lattice is in the business of supplying portable C
compilers and uses them for its own development work;
the motivation to fix the bugs immediately is definitely
there.
B-2
Lattice 8086/8088 CCompiler ConverUon of CP/M program
APPENDIX C:
Conversion of CP/M-80 Programs
Because of its similarity to CP/M-80, it is reasonable to expect
that Cprograms written for that operating system will be
transported to MS-DOS without agreat deal of difficulty. This
appendix attempts to point out some of the pitfalls likely to be
encountered when moving source from CP/M to MS-DOS or vice-versa
for compilation with the Lattice Ccompiler.
The least amount of trouble lies in store for those who have
written programs for the BDS C compiler. At the source code
level, every effort has been made to be compatible. while the
Lattice compiler is alittle stricter in some things, gene,rally
the correction is accepted by the BDS compiler as well, which
Facilitates keeping one set of source code for both sYstems. For
example, asequence like
char "cp;
V e 0
cp =cfunct(i);
0 0 O
char *cfunct(n)
int n;
{
0 V 0
will cause the Lattice ccmpiler to complain about amismatch of
external attributes, because cfunct is used implicitly as int
before it is defined as char *. Inserting
char "cfunct();
prior to the first use of cfunct eliminates the error, and is
acceptable to the BDS compiler as well. As for other coding
constructions, the warning generated for structures supplied as
function arguments without apreceding &was included
specifically for BDS C programs. The problem of external data
definitions posed bj' the bds implementation's lack of storage
class specifiers is mlved by the -x compile-time option. Here
are the rules for using it on BDS C programs:
I. When compiling the main module, do not specify the -x
option. The various external declarations are
interpreted as definitions of the objects, and storage
is actually allocated for them.
2. When compiling any of the other modules, gpecify the -x
option on the LCl command. The various external
declarations are then interpreted as references to
objects defined elsewhere (presumably in the main
module).
Be careful not to compile more than one of the modules in the
C-l
Lattice 8086/8088 CCompiler Conversion of CP/M Programs
program without using the -x option; otherwise, the linker will
inform you that multiple definitions of the external items were
encountered.
At the library level, there are other, more serious difficult·ies.
Although the BDS library does agood job of supplying most of the
standard functions described in the Kernighan and RÍtchie text,
the details of their operation are different from the Lattice
functions in anumber of small ways. In particular, putchar and
getchar are direct console I/O functions under BDS C, whereas
they are implemented as macros in Lattice C. This problem can be
avoided by using the console I/O functions described in Section
3.2.3. In general, it is best to review all of the functions
supplied in both libraries with aview toward locating potential
trouble spots. Many of the more specialized CP/M functions have
not yet been provided in the Lattice library, but check the
latest compiler addendum; others will probably be added as newer
versions of the compiler are released.
O*e
Users of the Whitesmiths Ccompiler are not likely to encounter
any problems with source language compatibility, but the library
is for the most part completely different. Hint: judicious use
of tdefines may eliminate some problems.
C-2
Lattice 8086/8088 CCompiler LÁ8t of Film
APPENDIX D:
LIST OF FILES
The following files are supplied as part of the compiler package:
Executable Film
LCI.EXE Ccompiler (phase l)
LC2.EXE Ccompiler (pha8e 2)
F'XU.EXE Function Extract Utility
okd.exe object Module Disassembler
Run-time and Library File8
CS.OBJ C program entry/exit module (S model)
CP.OBJ C program entry/exit module (F model)
CD.OBJ Cprogram entry/exit module (6 model)
CL.OBJ Cprogram entry/exit module ([ model)
LCS.LIB Run-time and I/O library (S mÓdel)
LCP.LIB Run-time and I/O library (F model)
LCD.LIB Run-time and I/O library (ÍJ model)
LCL.LIB Run-time and I/O library (i model)
CSource Files
MAIN.C Standard library version of main
TINYMAIN.C Abbreviated version of main"
FTOC.C Fahrenheit-to-Celsius sample program
CA,T.C File concatenation 8ample program
FXU.C Source for function extract utility
CONIO.C Easic console I/O functions
CHeader File8
STDIO.H Standard I/O header file
CTYPE.H Character type macro8 header file
ERROR.H Header file defining UNIX error numbers
FCNTL.H Header file defining level II/O codes
IOSI.H Header file defining level II/O 8tructure8
DOS.H Environment information header file
MSDOS.H Defines MS-DOS version
SP'!8086.H Memory model header file for Smodel
PM8086.H Memory model header file for Fmodel
DM8086.H Memory model header file for iS model
LM8086.H Memory model header file for ímodel
(Note: in order to use the DOS.H header file, you must copy one
of the last four files into M8086.H.)
Amembíy Language Source Film
CeASM Source for C.OBJ (all versions)
IO.ASM Sample assembler language function
D-l
Lattice 8086/8088 CCompiler Íjist of Files
Assembly Language Macro Files
SM8086.MAC Macro includ" file used with Smodel
PM8086.MAC Macro include file used with pmodel
DP!8086.MAC Macro include file used with Dmodel
LM8086.MAC Macro include file used with Lmodel
(Note: in order to assemble the sample source modules, you must
copy one of the last four files into DOS.MAC.)
D-2
Lattié@ 0086/8088 CCompiler Index
INDEX
&address operator 2-2, 2-9, 2-ll
8087 numeric data processor 4-18, 4-21, 4-22
8088 processor 4-18, 4-33, 4-34
-a option 4-5, 4-28
address operator 2-2, 2-9, 2-ll
aliasing 4-5, 4-28
alignment requirements 2-6
aliment function 3-9, 3-10, 3-ll
arguments 4-39
arithmetic conversions 4-20
arithmetic objects 2-5
arithmetic operations 4-20
array name 2-2, 2—13
ASCII 3-63, 4-18
assembly language interface 4-40
auto storage class 2-7, 4-39
-b option 4-5
bdos function 5-6
BDOS function entries 5-3
binary mode 3-16, 3-40, 5-2
bit Fields 4-22
branch instructions 4—26
buffering 3-16, 3-41
byte alignment 4—5
byte ordering 4-18
-c option 4-5
calloc function 3-4, 3-5
CAT proqram 4-15
CD.OBJ 4-9, 4-37
cgets function 3-53
character constants 2-2, 2—12
character type 3-63
char 4-18, 4-21
CL.OBJ 4-9, 4-37
close function 3-48
clrerr function 3-34
code generation 4-24, 4-25
comments 2-l, 2-12, 4-5, 4-14
common subexpressions 2-ID
compile-time option 4-5, 4-8, 4-17, 4-28
compiler errors 4-25
compiler processing 4-23
conditional compilation 2-14
console I/O functions 3-49
constant operands 2-9, 2-ID
control flow analysis 2-11, 4-26, 4-27
conversions 4-20
CP.OBJ 4-9, 4-37
cprintf function 3-49, 3-55
I-l
Lattice 8086/8088 CCompiler Index
cputs function 3-49, 3-54
creat function 3-43, 5-l
cs.obj 4-2, 4-9, 4-37
cscanf function 3-49, 3-55
ctype.h 3-63
ctype array 3-63
Cxerr error message 4-25
CXFERR library function 4-22
i
-d option 4-5
Dmemory model 4-29
data elements 4-18
data formats 4-18
DATA segment 4-36
debugging 4-5, 4-lS
tdefine 2-4, 3-49
derived objects 2-6
device I/O 5-2
device names 5-3
DGROUP group 4-n, 4-38
differences from standard language 2-l
division by zero 4-20
dollar sign 2-2
double precision 4-21
echo 3-49
equality operators 2-13
error processing 4-25
escape character 2-12, 3-79, 3-80
exit function 3-13, 3-57
exit function 3-58
expression evaluation 2-9
external data definitions 2-14
external declarations 4-6
external function definitions 2-14
external names 4-19, 4-38
external reference 4-6
external storage class 2-7
fclose function 3-19
feof macro 3-33
ferror macro 3-33
fgetc function 3-22
fgets function 3-25
file access mode 3-17
file descriptor 3-40, 3-42
file I/O 5-l
file names 5-l
fileno macro 3-35
file number 3-40, 3-42
file pointer 3-15, 3-17
file position 3-31, 3-32, 3-40, 3-45,
3-46, 3-47
floating point 4-19, 4-21, 4-22
fmode location 3-16
2
Lattice 8086/8088 CCompiler Index
fopen function 3-17, 5-l
formatted input 3-27, 3-55
formatted output 3-29, 3-55
formal storage class 2-6
fprintf function 3-29
fputc function 3-22
fputs function 3-26
fread function 3-24
freopen function 3-18
free function 3-5
fscanf function 3-27
fseek function 3-17, 3-31
ftell function 3-32
function arguments 4-38
function call conventions 4-38
Function Extract Utility 4-13
function return value 4-40
fwrite function 3-24
FXU.EXE 4-13
-g option 4-8
getchar macro 3-20, 3-23, 3-49
getch function 3-50, 3-55
getmem function 3-7, 5-l
getml function 3—7
getc macro 3-20, 3-23
gets function 3-25, 3-49
groups 4-37
hardware characteri8tics 4-18
hardware regi8ters 4-27
-i option 4-6
óíf 2-2, 2-4, 2-14
Hnclude 3-15, 4-6, 4-17, C-20, 4-25
include files 4-6, 4-20
initialization 2-8
initializers 2-8
int86x function 5-8
int86 function 5-8
intdo8x function 5-7
intdos function S-7
integer overflow 4-20
inp function '1-43, 5-12
iomode location 3-41
Tminum macro 3-63
imlpha macro 3-63
i8a8cii macro 3-63
i8cntKl macro 3-63
imcáymf macro 3-63
i8c8y1m macro 3-63
iMigit macro 3-63
i8graph macro 3-63
i8lower macro 3-63
isprint macro 3-63
I-3
rjattice 8086/8088 CCompiler Index
ispunct macro 3-63
isspace macro 3-63
isupper macro 3-63
i8xdigit macro 3-63
kbhit function 3-52
Lmemory model 4-29
language definition 2-]
LCI.EXE 4-l
LC2.EXE 4-l
LCD.LIB 4-9, 4-30
LCL.LIB 4-9, 4-30
LCP.LIB 4-9, 4-30
LCS.LIB 4-2, 4-3, 4-9, 4-30
library functions 3-l
linkage conventions 4-37
linking 4-9
#line 2-14
line control 2-14
local declarations 2-7
logical end-of-file 3-40, 3-47
lsbrk function 3-13
lseek function 3-47
lvalue 2-13
-m option 4-6, 4-29
machine dependencies 4-LB
macros 3-16
main function 4-S, 4-12
main function 5-5
malloc function 3-3
maximum Size cjf declared object 2-3
maximum subscript length 2-4
member names 2-2, 2-12, 2-13, 2-15
memory allocation 3-l, 4-34, 5-4
memory models 4-6, 4-28
movedata function 5-ID
movmem function 3-61
MS-DOS 4-l, S-l
-n option 4-6
-o option 4-6, 4-8
object code conventions 4-36
object Module Disassembler 4-15
operating instructions 4-l
operating system 4-l
operators 2-9
open function 3-41, 5-2
optimization 4-26
order of evaluation 2-9
outp function 4-44, 5-12
overflow 4-22
I-4
Lattice 8086/8088 CCompiler Index
Pmemory model 4-28
peek function 5-ll
PGROUP group 4-37
phase lcommand line options 4-4, 4-5, 4-6
phase lprocessing 4-23
phase 2 command line options 4-8
phase 2processing 4-24
pointers 2-6, 2-9, 4-18, 4-30, 4-32
pointer conversion warning 2-2, 2-3
pointer overlap 4-28
pointer variables 4-27
poke function 5-ll
portable library functions 3-l
pre-processor features 2-l, 2-4
primary expressions 2-12
printf function 3-29, 3-49
program entry/exit 5-5
program execution 4-ID
program exit 3-54
program generation 4-2
progrqm linking 4-9
prográm segment 4-36
program structure 4-34
putch function 3-50
putchar macro 3-21
putc nacro 3—21
puts function 3-26, 3-49
quadruples 4-23
quad file 4-3, 4-23, 4-25
rbrk function 3-12, 3-14, 5-l, 5-4
read function 3-40, 3-45, 5-2
registers 4-27, 4-38, 4-39
register storage class 2-7
register variables 4-23
relational operators 2-13
repmern function 3-62
rewind macro 3-17, 3-36
rl8menj function 3—8
rlsml function 3-8
r8tmem function 3-11, 5-4
run-time program structure 4-34
-8 option 4-6, 4-8
Smemory model 4-29
ebrk function 3-13, 4-33
scanf function 3-27, 3-49
scope -of identifiers 2-8
segmerit definitions 4-36
segment registers 4-35
8egread function 5-9
setbuf function 3-16, 3-38
setmem function 3-60
8etnbf function 3-39
I-5
Lattice 8086/8088 CCompiler Index
shift operations 4-20
sign extension 4-20, 4-21
sizeof operator 2-2, 2-4, 2-14
sizmem function 3-6, 3-10
sprintf function 3-29
sscanf function 3-27
stack 3-l, 4-38, 4-44, 5-4
stack location 4-44, 4-45, 5-4
stack overflow 4-.36, 4-38, 4-44
stack pointer SP 4-36, 4-38
stack size 4-4, 4-11, 4-45
standard error 4-ll
standard input 4-11, 4-12
standard output 4-11, 4-12
static storage class 2-7
stcarg functicm 3-79
stccpy function 3-66
stcd ifunction 3-72
stch"i function 3-71
stcisn function 3-78
stci dfunction 3-70
stcis function 3-78
stclen function 3-65
stcpma function 3-Bl
stcpm function 3-80
stcu dfunction 3-69
stderr 3-16, 4-11, 4-17, 5-2
stdio.h 3-1: 5, 3-38, 3-83, 4-32
stdin 3-16, 3-20, 4-11, 5-2
stdout 3-16, 3-21, 4-11, 5-2
storage classes 2-6
storage class specifiers 2-13
stpblk function 3-73
stpbrk function 3-77
stpchr function 3-76
stpsy: mmfunction 3-74
stptok function 3-75
strcat function 3-67
strcmp function 3-68
strcpy function 3-66
string constants 2-2, 2-4, 2-12
string utility functions 3-64
strlen function 3-65
structures and unions 2-2, 2-14, 4-18
structure and union declarations 2-13
structuee member references 2-2, 2-12
stscmp function 3-68
stspfp function 3-82
subexpressions 2-ID
switch statement 4-26
tags 2-13
temporaries 2-10, 4-39
text mode '3-16, 3-40, 5-2
tolower macro 3-63
I-6
Lattice 8086/8088 CCompiler Index
toupper macro 3-63
translated mode 3-16, 3-40, 5-2
type-ahead 3-49
type names 2-14
type punning 2-ID
unary operators 2-13
tundef 2—5
underflow 4-22
ungetch function 3-51
ungetc function 3-23
uninitialized pointer 4-33
unions 2-9, 2-14, 4-5, 4-18
unlink function 3-44
unresolved externals 4-ID
untranslated mode 3-16, 3-40, 5-3
utility functions and macros 3-59
-v option 4-8
warning message 2-3
write function 3-46, 5-2
-x option 4-6
zerodivide 4-22
I-7
Lattice 8086/8088 CCompiler Suppltmmt for version 2.10
Lattice 8086/8088 CCanpiler
manual sUppLmRtr fcr veaskn 2.10
1.0 SIFMARY CE
The fo1lowim list sumar izes the tnost important differences
tetween Version 2.10 and Version 2.00. Please no te that UÜ3
docunent is intended as a supplenent to the Version 2.(J0 manual .
If you do not yet have that manual ,you must contact the
publ isher from wbcm jpu purchased the compiler and make arrange-
mmts to obtain it.
l. 1Ctmpiler Dtif fermces
'Ihe compiler bas been been upgraded in afew minor ways, as the
following list indicates:
Extem/static objects as large as 64K now permitted
New -d fliig to tdefine symbols frcxn ccmnand line
pre-defined synbols for manory model ,operating system
New -w fleg forces mrd aligrnent as in Version 1.04
Wrger inµit lines/macro def initions supprted
Additional warnings issued for questionable constructs
1.2 Library Differes
xjst of the differmces betRen Version 2.1 aíü version 2.0 are
in the library, as stmnarized in the Eollowim list:
Automatic sensiW of MS-DOG Ivs. MS-DOS 2
Autcmatic ms: tnj and use of 8087 math chip
UNIX-cmpatible math fmctions
FauvExEc ccmbination fimctions
ASCII/BINARY rmde specifiers on FOPEN
Mcess to errvirornent strings
Miscellmeow library add itions
W? have attanpted to keep all of the 2.1 chatyjes upward
canpatible with Version 2.0, arü so you should not have to change
my existim pr¢jgrans. lbwever, the Mdi tion of MS-DCS version
I
Lattice 8086/8088 CCompiler SuFpl%mt for Version 2.10
sensing and 8087 sensing has caused the library to grow abit.
Therefore ,prcgrans that were close to a manory limit might be
affected. Also, the FCRK/EXEC caµíbility forced us to chanje our
approach to memory allocation, which may affect prograns that
bypass our staMard m~ry managanent functions. This change in
the manory lajput for the Sand Pimdels forced achange in the
code generated to detect stack overflow, which means that
prograns using these models must be entirely reccmpiled before
they can use the new library. See section 6for more details.
Version 2.1 also includes bug fixes in both the ccmpiler and the
library. These sMuld all Le transparmt, since none of the
doctíaented interfaces were changed .
Finally, m've improved the operating procedures by aiding an LC
canínarü that invokes both canpiler passes and by aiding several
batch f lies that copy the release disks to our rec«mended
directory structure on systans with hard disks.
The following sections describe these di fferences in detail.
table Of camtns
2.0 NEW CCMPI= FExñRE3 3
3.0 -MS-COS VERSION SENSING 6
4.0 AUKMATIC SEN3ING AND USE (JÉ 8087 MATH CHIP 7
5.0 UNIX-CCMPATIBLE MATH FLNcTr= 8
6.0 FCRK/EXEC CCMBINATION FUNCTICN3 20
7. 0ASCII/BINARY MOLE SPECIFIERS CN FDPEN 24
8.0 access mmIRcNqENT strings 25
9.0 MISCELLANEOUS LIBRARY AñDITIcNs AND CORRECTIONS 27
10. 0CCNVENIENCE FEAMES 34
11.0 LIST (JE FILES 36
2
Lattice 8086/8088 CCcmpiler Supplm«it for Version 2.10
2.0 NEW CCMPILER FEATURES
In addition to the wual buj fixes, this version of the compiler
has been enhanced in several ways. These enhancements make it
easier to Ejerforln conditional ccxnpilations, and allow alarger
class of prcgrans to be accepted by the compiler. At the sane
tiíne ,several helpful warnings have been added which can often
point to coding errors.
2.1 New Storage Class Size Lhnitatíom
In the previous version of the ccxnpiler, no object could exceM
32767 bytes in size; moreover ,the combined size of all objects
declared for aparticular storage class was subject to the sane
limitation. In Version 2.í, the limit has been charged to 65535
bytes, for static arkj extern objects only. Structures may be
declared which are in excess of 32767 bytes, but the error
message "maximun object/storage size exceeded" will be generated
if an attanpt is made to declare mauto structure of that size.
2.2 CkmRrKj Line Definition of Pre-processor Sydxñs
'Ihe -d flag has bem exterüed to allow symbols to be ídef ined
frcm the ccmnarxi line .7his feature allo'ws source files contain-
ing conditional ccnpilation directives (#ifdeE, Ufridef, tit,
telse, #eMif) to be used to prodtre dif ferent results witMut
modifying the source Elle, simply by definiW the appropr late
syntxil on the Lcl cQmnam. The -d fWj in its simplest form
retains the same meaning as in the previous version (i.e. ,it
causes the ccmpiler to include line-number information in the
object file) .The new forms of the ccmnand are
-ásydbol
4SµdbD1"value
where "symbol" is astardard C idmtifier. The first form merely
defines the symbol with anull substitution text; the equivalent
Cstatmmt is
Klefine syt±ol
'Ihe second Eorm ees an equal sign to attach asubstitution text
"value"; its equivalmt is
tdeflne ~1 value
Several definitions can be wed in the sane LCl cxmnand; however,
macros with argments cannot be defined fran the ccmnand line .
2.3 Pre-deffned ~Is
As afurther assistance to conditional empilation, the compiler
now autcmatically #def ines several sµtols, which can be tested
in coMitional cxmpilation statments to select appropr late cede
sequences for the operating systm, memory mcdel, and so forth.
3
LÁttice 8086/8088 CCcmpíler Supplanent for Version 2.10
These symbols have also simplified the new version of LCG.H aM
eliminated the need for the MSÍXJS. H, SM8086.EI, R'18086.H,
IM8086. H, and LM8086.H heiáder files supplied with Version 2.00 of
the canpiler .
'I\nkj sµnWls are alwYs defined in the compiler:
[define MSJXE3 l
Hefine 18086 I
One of the following symbols is defined, depending on the manory
mcxiel s£?ecified:
ídefine IB086S ldefined if Smcdel, else trdefined
fdefine Í8086P ldefined if Pmdel, else mdefined
tdefine I8086D Idefined if Dmodel ,else tmdefined
tdefine I8086L Idefined if Lmodel, else uMefined
One or the other of the following is also defined, deWMi% on
the manory model:
tdefine SPTR Idefined if Sor Pcmdel
#define ~idefined if Dor Lmodel
If the -s option ms spcified on LCl, the following symbol is
defined:
tdefíne SELIG l
Finally, if the -d fliqj was specified (as "d", not "-dsyntx)]") f
the following symi»l is defined:
idef ine I
The automatic definition of these synúbols can be µevmted by
usirg a new ccinpiler flag:
—u
Specifying this fW on LCl cancels all of the above definitions.
2.4 Optional Wjüí Aligment
An option to s%Fxjrt aligment of data elanmts other than cMr
to an even (mrd) offset has bem provided :
-W
Speci fyinj this flag on LCl causes all data elanents except char
itans t"j be assigned tÁj even offsets. Uiis aligmmt prcduces
mre efficient cede on art 8086 processor, mere fetchirg amrd
on an odd byte Hundary requires four additional clock pericds.
tibe sane aligment was used as the default in version 1.04 of the
ccmpileL .
4
Lattice 8086/8088 CQmpiler Supplanmt for Version 2.10
2.5 &icpaMed Line ani Macro Sizes
Formerly, the substitution text for a#define macro was limited
to amaximm of 80 bytes; in Version 2.10, the new maximun is 256
bytes. Similary, the previous maximun size of an input source
line was 132 bytes; the new maximun is 256 bytes.
2.6 New WarniW Messqjes
Mnew warniW messages have been aided tiO Versicn 2. ID of the
canpiler. They are:
Warning 84: redefinition of pre-processor symbol "xxxx"
Warning 85: fimction return value mismatch
'lbe fi rst warning is issued whenever a#define statemen ti3
enco un ter ed for malreerly #defined synbol. As noted in tho
inanual ,the second definition takes precedence, but requires An
additional #undef statment before the symbol is truly undefined.
The secorü warning is issued Üjenever the value returned by a
function is mt of the sane type as the function itself. The
value specified is autcmatically converted to the appropriate
tyµz; the warning merely serves to notify you of the conver: ñon.
The warning can be eliminated by usirg acast 3perator to Fo rce
the return value to the fmction type.
Version 2.00 of the compiler generated warning 30 ("pointers clo
not point to sane object") only when the result of an assigment
statanent was apointer. In Version 2.10, the same warning 1:3
generated when apointer of any type is assigned to an arithnetic
object. anew warning (duplicate declarat.ion of item. "XXXX") is
now generated whm aformal par ane ter for afunction 1:3
redeclared at the lowest level inside the fmction, as in
f(X)
char x;
{
int x;
Finally, the Lgé of an undefined structure tm in apointer
declaration now causes only awarnim ,not an error ,if the
structure is never defined as loW as no attmpt is mMe to
refer to the structure's members, or to perform arithnetic with
the pinter .
2.7 New Error -|· · · ,1'·1
~
If either oFerand in alogical CR (II) or logical AND (&&)
expression is constant, the ccxnpiler now will generate the err3r
messaje "invalid constant expression". If the end of source file
input is detected inside aconstant, the error message
"mexpected end of file" will be generated.
5
mttice 8086/8088 CGcmpiler Supplanmt for Version 2.10
3.0 ms-dc6 vmsxm sen3ing
The start-up prcgran (see C.A&°l) now sets up aglobal variable
naned dos that indicates which version of MS-DKJS is active.
'Ihe li6rary fmctions then test this variable at appropriate
points in order to call the proper low-level operating systan
service fmctions.
You can refer to dos in twD mys, as follow:
extern char dos;
extern char "dos [2] ;
The ms-= major version ntxüer (l or 2) is then ffómd at dos
—.
(fl rst rnetMd) or dos[0] (secoM metPM) .The mino rversion
ntxnber is fotrid at dos[l] for the second metMd only.
As jpu can see by exanining c.m, the MS-= version information
is obtained via operatim sYstaa call 30, ídüch is fully
described in the MSAJOS or FC~ Téchnical Refermce. We wsure
that dos will never contain avalue of 0when operating uwüer
and we may use the 0value to indicate CP/M-86 in a
future release.
6
Lattice 8086/8088 CQxnpiler Supplanent for Version 2.10
4.0 AUKMATÍC SEN3ING AND USE OF 8087 MATH CHIP
The floatíryj point simulation functions in the library have betm
changed to detect the presence C1É the 8087 níath chip. IE the
chi pis -installed, Y3ü should notice aláLjQ pzr Eu)
rmáníü"
improvment in prograns that do many floatinj µÁnt Qµeratic}i1s.
Ñjtice that you do not need to usc" |.!íc? -E f!:vj i jor"h±í '..) obtát':
the benefits ctf the 8087 under Ver: Mn 2. :-F·-lrth: ?rmore, tim
progrms that you generate will rim c?rrg-: ¿:}' o: ' asys: am 'withou:
the math chip. Ink are still c-3n3íd'.'ri¡ij t'iú u.f.e of the -t fj'jj
to stimulate in-line 803? ccxle ,j'·m: itian, but this may bo
dropped if the bi-modal library appro ich píoy·g?s adequate.
7
uttice 8086/8088 CCkinpiler Suppl@mt for Version 2.10
5.0 LNIX-CCMFATIBLE MA7H FLNCTICN3
Version 2.1 incluies alarge portion of the floating pint math
functions that are usually provided with LNIX. Detailed
specif ications are given in the following manual pages. bbte
that tN heaier files math.h and limits.h should usually be
included when jNjU are using these functions.
8
Wttice 8086/8088 CCcxnpiler Supplanent for Version 2-ID
NIWE
exp,lcg Jcgl0,pw,sqrt -- exponential ftmctions
SYNOPSIS
r=exp(x) ;coonpute E**x
r=log(x); canµite natural leg of x
r=Icgl0(x); compute base 10 lcig of x
r=Fow(Xgy); compute x**y
r=sqrt(x); ccmpute square root of x
double r; result
dotble x,y; arg merits
[mmFTIcN
For lago jmgl0, and sqrt, the xargment mwt be positive,
and for pow, the yargunent mwt be an integer if xis
negative.
9
Lattice 8086/8088 C Ocmpiler Supplanmt for Version 2.10
NNQE
sin ,cos ,tan ,asin ,aco5 ,atan ,atan2 transceMmtal fmctions
SYNOPSIS
x=sin(r); canpute sine of r(r in radians)
x=cos(r); canpute cosine of r
x=tan(r) ;canpute tammt of r
r=asin(x); canpite arcsin of x
r=acos(x); compAe arccosine of x
r"atan(x) 7ccmµite arctangmt of x
r=atm2(y,x) ;canpute arctargmt of y/x
double r,x,y;
The sin, cos, and tan fmctíons canpite the normal
tr igometric fmctions of angles expressed in rMians.
The asín ftmction ccnputes ttM inverse sine and returns a
rallan value in the range -PI/2 to +PI/2.
7he acos function ccmputes the inverse cosine and retwns
arallan value in the range 0to PI.
7te atan f~tion cmNtes the inverse tangmt arid returns a
radian value in tN rmge -PI/2 to +PI/2.
The atan2 fmctíon ccmµites the imíerse sine of y/x aM
returns arMian value in the rarge -PI to +PI.
10
Lattice 8086/8088 C Cíxnpiler Supplement for Ver': ion 2.lcj
L
sinh,cosh ,tanh -- hyperbcl i: : func'ims
SJ/NOFE'IS
x-- sirih(y) ;-»mptíte hypcrbo: i: .:i::í-'
x=ccx: h(y); c{ycÉ)'jrl.? }:n-erb:}:! :¿'·jSZ:l?
x=tanh'g'); :a!íy'jt.e 7in?etb·}iz3 t.míje'rít
double x,y;
DESCRIPTION
'These fancticms si: mly zompute the normal :}Ype[!jot 'us.
l!
Lattice 8086/8088 C Compiler ~lment for version 2.10
rand,sraM símµle random nanber generation
S!LN0PSIS
x X rand();
srard(seed);
int x; random nunber
msigned seed; randcm number seed
The rarid fmction returns pseudo-randcm numbers in the rarEje
fran 0t3 the maximijn positive integer value. At any time,
you cauj call sreM to reset the nunber generator to anew
sta[tirü ·point. The initial default seed is I. See the
description Qf draM for more sophisticated rarxkm nuítber
generation .
12
Lattice 8086/8088 CQmpiler SUqÉjp1mmt for Version 2.10
bUWE
drard generate random nunljers
SYNOFSIS
x=drand48(); generate dotble (internal seed)
x=eraM48(y) ;generate double (external seed)
z=Irard48(); generate posi tive lom (internal seed)
z=nrand48(y) ;generate positive long (external seed)
z=wand48(); generate long (internal seed)
z*. jrand48(y) ;generate lorg (external seed)
srarid48(z) ;set high 32 bits of internal seed
p=seed48 (y) ;set al] 48 bits of internal seed
lcong48 (k) ;set linear congruence µiraneters
double x;
msigned stK)rt y{3];
long z;
msigned stort "p;
tnsigned stmt k[7];
Imm1?TIcN
These fmctions generate pseudo-randcm nunbers using the
linear congruential algorithn and 48-bit integer arithnetic.
The normal versions (drand48, lraM48, mrand48) utilize an
internal 48-bit storWe area for the seeá value. Special
versions (eraM48, nrand48, jrand48) are provided for cases
where several seeds are in use at the sane time, in which
case the =r provides the seed storage areas.
7he draü48 and erarñ48 fímctions return values mi founly
distr ibuted aver the interval from 0.0 up to but ntjt
including 1.0.
'Ihe lrand48 and nrand48 fmctions return non-negative lorU3
fntegers miformly distributed over the interval from 0to
2"*31-1.
The mrand48 and jraM48 fuictions return signed 1orY3
integers miformly dístr ibuted over tm interval from -2**31
to 2** 31—L
The srtM48 arid seed48 fmctions allow ydu to initialize the
internal 48-bit seed value to sKmethim other than the
defaults. Fbr sreM48, the speciEied long value is copied
into the high 32 bits of the seed, and +low 16 bits are
set to 0x330e. Fbr seed48, the mtire 48-bits are lomed
frcm the sFecified array, and the finction returns apointer
to the internal seed array.
13
Lattice 8086/8088 CCainpiler SuFpleum1t for version 2.10
'The lcong48 f mction allow you to do amuch more intr icate
initialization of the linear cQWruential álgorithn. tlhe
algoritkn is of the form:
X[n+l] =(a* xInj +C) fllKÁm
where mis 2*"48 and the default values for aand c are
0x5deece66d dKKÍ 0xb, resµzctively. ¶ie array passed to
lcorg48 contains the value for x{n] in k{0) to kf2} ,the
value for ain k[3] tD k[5], and mvalue for cin k[6]-
Ptien you call seed48, aarid c are reset to their original
default VálüéSe
14
Uttice 8086/8088 C Ctmpiler &|Fp1m@t for Version 2.10
NAME
cei1,fabs,fkor ,Emod ,frexp,ldexp,mcdf -- float conversions
SYNOPSIS
x=ceil(y); get ceiling integer
x=Eabs(y); get absolute value
x=floor(y); get floor integer
x = ~(Y,Z); get njcxí value
x=frexp(jhp); split into mantissa and exponent
x=ldexp(YÁN load exponent
x=md£(yfp); split into integer and fraction
double x,y,z;
int i;
double *p;
'These functions convert floating point nmbers into var ious
other forms.
The floor and ceil functions return the integE"r values that
are just below and jl-gt above the spec ified value,
respectively.
The HikxÍ fmction returns yif zis zero .Otherwi se ,it
returns avalue that has the same sign as y, is less than z,
and satisfies the relationship
y=i*z+x
where iis an integer.
The frexp fimction splits yinto its mantissa arid exj»n·mt
urts. 'The expcment is placed into the area pointed ro b'j
p, b&ji1e the mantissa is returned by the functiDn.
'Ihe ldexp function returns y* (2 ** i) .
The mcdf fmction returns the fractional part of ywith the
same sign as y and places the integer portion into the area
pinted to by p.
15
Lattice 8086/8088 CCompiler Supplmmt for Version 2.10
*
1unke
atof ,atoi ,atol simple ASCII conversions
SYNOFSIS
x=atof (p); ASCII to floatimg point
i=atoi(p) ;ASCII to integer
l=ato1(p); ASCII to lopj integer
double x;
int i;
long I;
char *p;
DESCRIPTI(JN
'Ihese Etmctions >^Ljj over my leMing 'diite space (i -e.
bIaí1k3 and tabs) and then per form the appropriate
cuñv€Tsion. 'Ihe conversion stops at the first ímrecognized
character, and no check is rnMe for overflow.
Fbr atof, the ASCII string may contain adecimal pint and
may be Followed by an e or an Earid asigned integer
exµmimt. For all functions, aleading minus sign indicates
jnegative noit±er. \díite space is not allowed between the
¿ninus sign and the number or betwem the number and the
?KEjonent*
16
Wttice 8086/8088 CCcmpiler SuWlanmt for Version 2.10
bQWE
strtol eonver tASCII to long integer
SJQK)FSIS
r=strtol(s,p,base);
long r; resul t
áar *3; strim to be scmned
char **p; returns pointer to terminating character
int base; conversion base
[EsaunIcN
ibis fmction converts an ascii strim into alom integer.
usim the sFecified number base for the conversion. Leatlinj
rdiite space (i.e. blanks and tabs) is skipped, aM the
conversion proceeds mtil munreccgnized character is hi t.
The pcñnter to the unreccgnized character is returned in p.
If no conversion can be performed, pwill contain s, and the
result will be 0.
The conversion base can be in the ranje from 0to 36. If it
is non-zero ,then the ASCII str ing may contain digit
characters frorn 0throüjh 9and frcxn the letter Athrocgh as
many letters as necessary, with no distinction made between
tpper and lower case. For exanple, if base is !3, then tiií-'
allowable digit characters are 0through 9and A,i3, and C'-k
a, b, and c. If base is 16, then aleading "Ox" or "OX" may
appear in the string.
If base is 0, then the leading characters of the stxifYj are
exanined to determine the conversion base. a 1eMin;j O
indicates octal conversion (base 8) ,while aleeding Ox or
DX iMicates hexMec iinal conversion (base 16) .Aleadin'j
digit from 1 to 9indicates decimal conversion (base ID) .
17
Lattice 8086/8088 CCkmpiler Súfpimmt for Version 2.10
NAME
ecvt -- convert floatiW point to ASCII
SYNOFSIS
p=ecvt(value ,ridig ,dec,sign) ;
char *p; pinter to ascii strim
double value ;value to convert
int ridig; nunber of digits in string
int *dec¿ returns position of decimal point
int "sign; non-zero if negative
This fmction converts the specified value into anull-
terminated ASCII string cQntainim the specified number off
dig its. 7he integer pointed to by dec will then contain the
relative location of the decimal point, with anegative
value meaning that the decimal is to the left of the
returned dig its. 'The actual decimal point character is not
incl txied in the generated string.
18
Lattice 8086/8088 C Qmpiler Supplanmt for Version 2.10
NAME
matherr -- haMle math fmction error
SYNOPSIS
code =mtherr(x) ;
int code; non-zero for new return value
struet exception *x; math exception block
ImmIprIcN
flhis fmction is called whenever one OE the other mat-h
functions detects an error. Upon entry, it receives the
exception block that describes the error in detail. 'M3
structure is defined in math.h, as follow:
struct exception
{
int type; error type
char *nane; nane of fmction having error
double argl; f irst. argunent
double arg2; second argunent
double ret; proposed return value
9:
The error type nanes defined in math.h are:
DCMAIN => domain error
SING => singularity
(NERFLKM => overflow
=> under flow
=> total loss of significance
FLOSS => partial loss of significance
Hjctj matherr is called ,the fmction that detected the error
will have placed its proposed return value into the
exception structure. If you want to substitute adifferent
value, then matherr mwt return a non-zero code.
If you do mt supply aversion of matherr, the stand ard
version will put the appropriate error nurber into errno and
return acede of 0.
19
Lattice 8086/8088 C Ckmpiler SuEpl%mt for version 2.10
6.0 FQRFYEXEC c~IbuLTIcN EUETIcFí6
Version 2contains asystm call tmt behaves like a
combination of +LNIX fork and exec functions. 1hat is, it
creates a"child" process which executes aspecified IOM module.
!Ihe "parent" process can @n retrieve the child's canpiletion
cede via another new systan call that is similar to the INIX mit
funct ion.
Qf course ,MS4jOS Version 2does not really sL«ort multi-
prcgrarmirg, arid so the parmt and child processes do not
actuaiiY timeshare the ccmpiter .Uie j;ár«jt umains swpeMed
mtil the child terminates. Ebwever ,if multi-progr=im is
added tD MS4X)S in the future, we expect that the interface
provided in our library will te maffected «cept tMt the parmt
will nc> lomer be totally out of bminess while ttm child
executes .
After reviewiW ~new ftnctions described in «followiW
manual pagm jpu might mrüer u}y we did not provide mexact
equivalent of LNIX's fórk fmction. The mswer is simply tmt 1Ñe
could not figure out ageneral way to repl icate the parmt
process' saídress spa: e on the 8086. mt is, ~typical
prcqran oFeratim txüer MS-4XJS contains absolute "'"j"' ""'" nuúbers,
which nakes it impossible to move tie progran for mecution in
another area of mmory.
Meukky Manqjanmt CNuige
In order to implanmt the FÚRK/EXEC capebility, =hM to chame
our approach to mmory allocation for Sand pmdels.
Version 2.0 of Lattice Crwained fully cxmpatíhle with the
earlier wallmw: del versions by placing the stack as high as
possible in the data segmmt and by µlacing the inanory pxíl {i .e.
the "heap") between the Static data area and ~stack. However ,
for the Dand Lmdels intrcxíwed with Version 2.0, rplaced tm
stack imediately above the static data and male all rmainirg
manory above the stack available for the heap.
In Version 2.1, the stack is located just above the static data
for all mmory models. \kder MS-DOG 2, thm, ~start-up
µo;jran (see "c./Lqq) returns all umainirg manory space to the
operatirrg systan so that there is roan to create achild process.
Ken you call djrk, it will attenpt to obtain tte r~ired anotnt
of space back frcm MS-DOS, and when you call rbrk, the space thw
obta int-d will once .again be givm back to MS-DC6. In other
'rjrcis, the manory allocation functions will appear to operate as
'íey did íxíder Version 2.0 cñ the compiler, but in fact tjñey will
.e much mjte closely coupled to the operating systm.
Che fly in the ointmmt is that achild process cm cMose to
terminate but remain resident in memory. If that happens, the
Farent may firid that its heap cannot grow because the child
20
Lattice 8086/8088 CQmpiler MPlmmt for version 2.10
process is in the my. lb help avoid this problan, @!ve added a
global variable called meed .'Ihis is simply along integer
that sµecifies the minTnun nunber of bytes neMed in the heap.
At star t-up time and each time yum call rbrk, meed is
consul ted .If sufficient sµce cannot be allocated, trié start-uµ
µrcgran aborts or rbrk returns a-l failure ccxie. Ñjt2 that ydli
can charge WbC£Xj each time jpu call rbrk.
Finally, if you referenced the pinters wbase and mext
directly witMut goiW throWh the tnmory al1&ation functions,
be aware that these are both 4-byte pointers cxxIer all memory
mcxiels. This impl les that under the S ard Pmodels thés<-·
pointers sMuld not be treated as [6-relative offsets. .The sbrk
fmction aMs top to the first mrd of _in order to return
aN-relative offset tD you. Also ,sbrk ensures that the heap
rmains within tM aidressing range of DEL
21
Lattice 8086/8088 C Gcmpiler suFp}anent for Version 2.}0
NNQE
forkjwit -- create child process and wit for it
SYNOFSIS
error =forkv(nme,argv) ;
error =Eorkl (nane,arg0,argl, ... ,argn.NKL) ;
erro r =forkvp(nane,argv) ;
error =forkjp(naoe,arg0,argl, . . ·¶argn0NULL) ;
code =mit();
int error; 0for success, ñoHzéro for error
int ccxie; child process return code
char "nane; file nme of loai module
char *argv[]; argunent pinter array
char *arg0,"argl, .. argment pñnters
DE3CRIPTKN
These fmctions create achild process that executes the
sµxñ£i«í load mdule and then passes a return code back to
the prent process. The sFecified argtnents are passed to
the child's main entry' p'int via the normal argc/argv
inechanim. By convention, the first argunmt (i.e. arg0 or
argv[0)) is the nane of the child µrocess loal mdule, which
is usually the sume as nane. Note, however, that this first
ar'junent is not actually passed to the child process because
of limitations in the MS—DQS process creation pr imitives.
Also note that these same limitations restrict the total
length "of all argunent strings to be no more than 127
characters.
The fmction naaes have been cMsen to match the var ious
forms of the LNIX exec fimction. 'The "V" suffix on forkv
and forkvp indicates that the argments are suppl led as a
vec tor in the argv form. 7hz last pointer in the vecto r
must be null. The "I" suffix on Eorkl arü forklp iMicates
that the argtmmts are supplied as alist of f'ointers, with
the last pointer being null. 'The "p" suffix on Eorkvp and
forklp indicates that the PATH enviroment variable sFmüd
be wed if the load mcxiule is not found in the current
jirectory. id~ stepping through the directDries, the
functions look for "name.CCM" and then "nane.EXE" in each
directory.
It the child process cmnot be created, the fork fmction
returns a non-zero result. Under MS-tOS, the global integer
oserr will contain the operating sYstxm error cede. If it
Is 0, the error occurred while processing the fork call
par meters .
cAUrI~
22
Lattice 8086/8088 CCjcmpiler Supplwmt for Version 2.10
urder MS-DOS the argunents are converted into atext string
no longer than 127 bytes. !n7e first argunmt (i.e. arg0 or
argv{0]) is dropµxi, arü ablank is placed between
sUcceediW argunmts. 1he resultim strim is passed to the
child in its camand line buffer .If the child is aC
pragran, its startup ©ase will comert the camnaM line
back iñtÁj an arg list.
23
Lattice 8086/8088 C Compiler Supplanmt for Version 2.10
7.0 ASCII/BINARY MOFE SPBCIFWRS CN FOPEN
Since the Éé of the finode global flag bas confused some users,
we've added mother"way to specify translated or mtranslated
mode when openim alevel 2file via fopen or freopen. You can
now specify translated mcxle by placing the letter 'a' in the
seco"nd position of the mode string. Similarly, the letter 'b'
sµci fies mtranslated mcrle. If the second letter is neither of
these, Einode is wed as before.
Note that this new approach is ncjt currwtly LNIX-compatible.
Fbwever ,several other Cccmpiler packages mrk this way, airü
proposals for this apprOach are floating around sene of the
standards ccjmnittees.
In sumary, foFen and freopen now reccgnize the following mcxie
strings:
ropen for reading (translation according to Encde)
ra open for reading (translated) "
rb open for re¿Kjim (mtrmslated)
wopen for writinj (translation accordirg to hncde)
wa 3perl Edi writing (translated) "
wb -- open for wr it¿W (mtranslated)
aopen for appendiW (trmslation accordiW to finode)
aa open for appendiW (translated) "
ab open for appending (mtranslated)
You cm also place aplus sign after any ,of these codes to
indicate opening for both reading md writing .If jk)u open for
reMing with aplim thm the file must alre&!y exist; but if ydu
open for writing with aplm, the file will be created anew.
Qpming' for appending with aplw will allow ydu to reed frcn
anjMhere in the file, but all write operations will occur at the
end of the file.
I/O ERRCR C=
Nm we wrote the Version 2manual ,we fngot to mention the
methDd by which you can determine what went wrom üíen one of
jptr I/O calls fails. In gmeral ,we've tried to adhere to
LNIX's technique for reporting errors. &en you get afailure
indication Eren mI/O f mction, consult the global integer
errno, which will contain one of the error cedes defined in the
healer file error.h. As afurther refinmmt, you cm look at
~global integer _omrr to see the MS~ error code, if any.
These codes are de&ribed in the MS4XX3 and FC4JC6 Reference
Mmuals.
24
Lattice 8086/8088 CCompiler %pp1anent for Version 2.10
8.0 ACCESS TO STRINGS
MS-ljOS Version 2supports the LNIX notion of "env irorrnent
strings", díich are of the fbrm "nane=value" ard are usually
def ined by the SET camand .'Ihe strings are stored one after
another in the erivironment at'ray, and the last one is followed by
anull strinj. Ü[joñ entry, the public pointer env point3 to
the cur rent enviroment array. Ebr the S and P" mdel.z: ,the
startup prcxjran copies the enviroment into the stack sc) that you
can address itrelative to [g. Note that the stack sfjáce
requir«] for this is added to the jaiue jpu specify' in stack
on the camard line.
7he LNIX-compatible getenv function has been aided to the library
t:j «iabl p you to easily find aµrticular nane in the
env irorvnent .
25
Kttice 8086/8088 C Cmpiler Supplmmt for Version 2.10
NAME
getenv get envirorxnent striW by nane
SYNOPSIS
p=getemr(nane) ;
char "p; points to value prt of matching mv string
char *nane ;errv nane
lmmpTIoN
'This fmction searches the errviroment array pointed to by
env and returns apinter to the value prtíon of the first
str ing wMse name prtion matches nme. If mmatch occurs,
aNULL pointer is returned.
26
Lattice 8086/8088 CCompiler SuRplanEs)t for Version 2.10
9.0 14ISCELLANE(XS LIBRARY ADOITI~ AND CCRRKTI=
By popular request, we've aided more of the string manipulation
functions from the proposed LNIX standard. Also, we've added the
Following functions:
rmove sane as ml ink
clearerr sane as clrerr
renane renane afile
bdosx -- trios ftmction wi th pinter
getche getch wi th eclK)
setjnip -- save current stack for lorg return
longjmp -- make lorA return
The library now contains callable versions of scxne of the
character type macros described in section 3of the Lattice C
Manual. Specifically, the following macros are also available in
function form:
isalFtba(c) non-zero if cis alphabetic
isupeer (c) non-zero if cis upper case
islower (C) non-zero if cis lower case
kdigft(c) non-zero if cis adecimal digit
iwpace(c) non-zero if cis white space
isa1ntm(c) non-zzro if cis alphanuneric
iscntrl (c) non-zero if cis acontrol character
toupFer (C) converts cix) üpper case if it is lower
tolower (c) converts cto lower case if it is upper
In order to use the function forms, do not #incluie the ctype.h
header flle in your compilation. If jNjü need ctype.h for sane
reason, jpu can #uMef the specific macros that should be treated
as fmctions.
The followim manual pages describe the fmctions that have been
added.
27
Lattice 8086/8088 C Gmpiler SuFplmmt for Version 2.IC
NAKE
strcat/strncat str ing concatenation
3tranFj/strnQnp str ing ccmpar ison
strcpy/strncpy str ing copy
strlm measure str %lmjth
strchr/strrchr find first or last occurrmce of character
strpbrk tim break cMracter
strspVstrcsµ7 find loWest initial sFan
SYNOFSIS
to mstrcat(to,fre) ;
to "strncat(to ,frcim,mw) ;
order =stranp(a,b) ;
order *8trn=p(agbemax) ;
to =8trcpy(to ,frum) ;
to "stirncpy(to ,frcmómax) ;
lergth "str1m(s) ;
pwstrchr(src)$
pmstrrchr(s.c);
p-strFbrk(8,t);
length *strgpn(8Ft);
lergth "Gp-.'-g'y (mt):
cMr *tjcj ,*frmj destination m9otirce strims
int mimtn nmber of characters
cMr "a,"bb strings to canpare
int order 6-if a<b
0IE ab
+ifa>b
cMr "W string to test
cMr "t; test str Lng
int 1ermh; result l€mth
cMr "p; result pinter
tmcRrpTIcN
The strcat and strncat fmctions append the " from" str kg to
tM "tD" string. Fbr 8txñcat, mmore than tibe specified
maximim ntmber of characters will be appeMed.
¶ie stranp ard strnmp f mctions perform mmsigned
character ccmparison of the specif Fed strings. Fbr strnanp,
no mre thm tte speci fled maximun nurber of characters will
be cxmpared-
The strcFy ard strncpy hmctions copy the Eran strim to the
to str im .Fbr 8trrKpyb no more tMn the sFecifLed maximun
28
Lattice 8086/8088 C Canpiler Supplan«it for Version 2.10
nmber of characters will be cmpied.
'Ihe strlen function returns acount :jf the nunber df
characters in the sµecified str ing, not inclíxiing the
terininatirg null .
'Ihe strchr function returns apointer to the first
occurrence of the sµ"cified character in the sµ"cified
str ing. Similarly, strrchr retur,ns apointer to the last
occur rence of the charactet .Both functions return anull
pointer if the character is mt found in the string.
The str pbr kfunction returns apinter to the first
occur rence in string sof any character Eran string t. A
null po inter is t"eáirned if mcharacter frcxa the test
strirvj is fourri.
The strsµi fmction returns the lmth of the initial
segment of string sthat consists entirely of characters
from strim t. Similarly, strcspn returns the length of the
initial stri% of characters not frocn string t.
0
29
Lattice 8086/8088 Campíler Suppltmmt for Version 2.10
NNQE
rmane -- rmane a file
SINOPSIS
error =rmane (old ,new) ;
int error; 0for sUccess
cMr "old; old file naae
char *new; new file nane
This fmction rmanes a file, if pssibl e. Afailure will
occur If the new file nme alreay wists or if the old file
nane does mt.
30
Lattice 8086/8088 CGcmpiler SuWlanent for Version 2.10
nnqe
txios/bdosx call BOOS function
SYNOPSIS
ret =bdos( fn Ax ,al) ;
ret =tx1osx(fn,dp,al) ;
int ret; return cede
int fn; BIXJS ftmction ntnber placed in AH
int dx; value to be placed in DX
char *dp; fjointer to be placed in 1j6: DX
int al; value t: jbe placed in AL
Performs aBOOS call via interrupt nunber 0x21. Fbr ttje S
arü Pmanory mcxíels, txlos ard txiosx behave identically. Fbr
the Dand Lmdels, jpu must use bdosx if the BDCG function
requi res aFDinter in IX3:DX or tdos if BW only wants an
integer in DX.
31
Lattice 8086/8088 CChnpiler SUFpl«nmt for Version 2.10
NAME
getch/prtch get/µit character directly to/from console
SYNOPSIS
c=getch(); get cMracter with mecM
c=getcte() ;get character with ecN
µitch(c) ;put character
int c;
These fmctions get arid pit characters directly to imid Eran
the console usiMg the lower-ntmbered BIXJE3 f unctions. Ni)
special processing is done except that pNch µíts acarriage
return character in front of each newline.
Previow versions of pitch masked off the high order bit of
the character imxj did not autmatically «nit carriWe
returns. EXisting prcgrms that gmerate "\r\n" sequences
dimild stfll behave the sane became the second '\r' anitted
by )h is merely redurdmt.
32
Lattice 8086/8088 C Cbmpiler Supplanent For 'jersion 2. 11·)
N/AM£
setjÍnp/lQrR jmp -- git Í-)l"q rK)E)-l32jl goto
SYNOPSIS
ret =setjmp(save) ;
1Dm jmp( save ,value) ;
int ret; return code
int value; return üaíúe
jtnp but save;
DESCRIPTION
'Ihe setjmp function saves the curcent stack tuatk 1!1 the
buffer area spmi fled by save and returns avalue of 0.
'lhen alater cAl to lorujmp will retur 11 to the next
statment after the original setjmp call wi th value as the
retucn ccxIe. If value is 0, it is forced to ! by longjmp·
1he jmp_buf descriptor is defined in the header file called
setjmp.h.
'Ihis iaechanim 13 useful f:n" quickly popping back up through
multiple layers gf funct ion calls under except ional
cl r:unstances. StructurM pr(jgrmlnim "gurus lose alot of
sleep over the "patholog ical connections" that can result
from indiscriminate waye·
CAJJTI06B
Calling longjmp with an inval id save area is an ef fective
my to disrupt jpur sYstan. (he carmon error is to use
lo'xjjmp after the function calling setjmp has returned to
its caller. If you think atjout how the stack mrks, )pú'1l
see \Áljf this doesn' t.
33
Lattice 8086/8088 C Camµiler Supplanmt for Version 2. ID
10.0 ccN\mIENcE .FEA=ES
This version contains severa! things that should make it easier
to use the Lattice CCXxnpiler, incl®irig:
—- Batch files for ZoMing the ccmpiler onto an IBM-XT
-- asimle la ccmnand to invoke both compiler passes
-- Batch files for canpiling and linking in standard ways
These are descr ibed in tte followim sections.
10.1 Batch Files for Lotding Qampiler onto IHYI-XT
Since the IEM-XT arü equivalent MS-DOS hard-disk machines sean to
be very ppular with Lattice Cusers,-w'e've included abatch file
that constructs our reccmnended directory structure ard asecorü
batch file that 1o&is the compiler onto the hard disk.
MAKEL£.BAT creates adirectory structure that will contain the
vario= mediales that make up the compiler package. 'R) execute
it, place the first release disk into drive aand type A: MAKELC.
Nen the procedure ccmpletes, the hard disk will conta in tm
following directory strtrture:
\lc Contains cxmpiler, heeder files, and utilities.
\lc\s Cbntains he&lers, objects, and libraries for S
mmory model .
\lc\p Cbntains heaers, objects, and librar les for P
manory model.
\lc\d Cbntains heMers, objects, and librar les for D
m«nory mdeL
\lc\l Cbntains healers, objects, and librar les for L
m«nory model .
\lc\c Cbnta ins heMers, objects, and librar les for
building .C(M files.
\lc\src Cbnta ins source Elles for utility and
dmonstration prograns .
The UJAIJLC.BAT procedure copies 6information from the release
disks to the hard disk. If jpu don't want to keep aparticular
mmory mcdel onl ine, simply renové its sttdirectory before
executing the lo?d procedure. 'Ib execute IAADLC, place the first
release disk into drive Aarid type:
34
Lattice 8086/8088 CCknpiler ~anent for Version 2.10
c:
cd \lc
oopy a :loadlc.bat
IoMIc
At the appropriate times ),kju will be prompted to chacrje the disk
in drive A.
After loaiing the compiler mcdules, you should set the default
search path f3r the camarü interpreter to include \lc. This can
either be done via the PATH comnaM or via the NJTCEXEC.BAT file
as demr ibed in the MS-IXJS reference manual .
10.2 LC
¶ie release disk contains aprogran called LC.CCM that uses the
new FCRK/EXEC fiímc tions to call the tWD canpiler passes
repeatedly for muí ti pI ecompilations. The ccxnmand has the
format:
IJC options files
where options is alist of ccmpiler oµions arid files is alist
of files, diich can include "wild cards" .
In gmeral ,the options are the same as for the LjCi and LC2
ccmands, except where ICl arid LC2 used the sine option letter to
mean different things. 'These cases were resolved as follows:
This option sFeciEies the Dmcxíel with the -S
option on LC2.
Sane as -mds.
-mis L mcxíel with -s option on lC2.
mn3s Sane as -mis.
-qx %eciEie5 prefix for cpaj files, sane as LCl -o.
In other mrds, the -s flag for pass 2aFpears as a suffix on the
-m and -ml manory rnMel sEecifiers, and the quad file drive is
indicated via -q insteixí of -o. Ncjte that these charUjes apply
only to the new lC ,not to LCl and LC2.
LC allow jpu to put ablank betwem an option letter arxí the
string that follow it, as in
IE -d xyz
bis is compatible with (NIX, but causes a problan if the -d itm
is just before the file rime part of the camand and ws intended
tD iMicate debljggim mcxle instead of defining asymbol, as in
35
Lattice 8086/8088 CCcmpiler SuFp1mmt for Version 2.10
IE -d µrogrm
'Ihe synbol "progran" will be Sdefined instead of beiW treated as
afile nane to be ccmpiled. Tb get around this problan, use the
UNIX convention of endiwj the options with asiwjle dash:
LC -d -prcgran
10.3 Batch Files for Cknpilinj and Linking
The release disks contain several ba tch flies that should
simpl ify the most camion compiling and linking scmarios.
LCS Cjcmpile for Smdel
LCP CMpile for Pímdel
ICD Ccmpile for Dmodel
LCL Gmpile for Lmodel
LINES Link for Smcxiel
LINKP Link for Pmrxíel
LINKD Link for Drmdel
LINKL Link for lmcdel
LINK Link for .CCM file
The LCX procedures acceFt up to 9argunmts consistirg of options
(as defined for 1£.CCM) and file nanes or file nane patterns.
'Ihe options met appear first .lhe LINKX µocdíures accept a
single argmmt that is the nane of the .(BJ file containing jpur
main prog ran.
11.0 LIST CF FIW
Version 2.10 is normally shipped on disks in the IBM 320K format.
As discwsed in section 10, the first disk contains batch files
that facilitate copying the release disks onto jpur mrd disk if
ydu use mIEM-XT or equivalmt. The actual release files are:
Batch Files
MAKELC.BAT Make bard disk directory structure
LQADLC.BAT Ibai Lattice C onto hard disk
LCX.BAT Ckmpile tMer m«nory mcxlel x
LñúCx.BAT Link urüer manory mcdel x
Executable Files
LC.CCM Qmpiler comand line MMler
LCI.EXE C c<mpi1er (phase l)
LC2.EXE C ccmpiler (phase 2)
FXU.EXE Ftnction extract utility
cmd.exe Qjject meddle disassmbler
plib86. exe cbject module librarian
36
Lattice 8086/8088 C(jampiler Wpplanmt for Version 2.10
Run-time and Library Files
CS.CBj C progran mtry/exit mcdule (for Smcxiel)
cp.m Cprcrjran extry/exit module (for Pinodel)
CD.CBJ C progran extry/exit module (for Dmodel)
ct~m Cprogran extry/exit mcxlule (for Lnkxiel)
CC.CBJ C progran mtry/exit module (for .CCM files)
LCS. LIB Run-time and I/O library (for S model)
LCP.LIB Run-time arid I/O library (for PincxjeL)
LCD.LIB Rm-time arid I/O library (for Dmodel)
LCL. LIB Rm-time and I/O library (for Lmcxiel)
CSource Files
MAIN.C Standard library version of wain
TINYMAIN.C Ptbreviated version of main
CONIC) C Basic console I/O functTons
FTUC.C Fahrenheit-to-Celsius sample prcg ran
CAT.C File concatenate sanple prcgram
FAJ.C Function extract utility
CHeader Files
STDIO.H Standard I/O header File
CTYPE. HCharacter' t'{p" macros healer file
DOS. li Enviroment information Nader file
ERROR. H Healer file defining (NIX error nunbers
FCNTL.H lkadet" file definin;j level lI/O codes
IOSI.H Healer file definiUj level II/O structures
MATH.H Mathmatical Emctions heaer file
LIMITS.H Defines limitirg values for math functions
Assanbly Langu¿uj2 Sourte Files
c.asm c pr%ran mtry/ex.it mcdule (all versions)
IO.ASM Sanple assanbler larrjuaje function
Assembly Lang%e Macro Files
CM8086 .MAC Macro include file used for .CCM files
SM8086.MAC Macro include file used with Smodel
M8086.MAC Macro include file oed with pmodel
IM8086.MAC Macro include file used with dtnodel
LM8086.MAC Macro include file wed with lmcdel
(Ñjte: in order to assanble the source modules, one of the above
files must be copied into IXjS.MEC; use the version aEpropriate
for the manory mcxlel desired-)
37
TECHNICAL BULLETIN
1B840523.001
DATE: May 23, 1984
PRODUCT: 8086/8088 C Ocmpiler, Version 2.10
SLBjE9CT: Supprt for .CCM files
lhe Version 2.10 disks contain several files that supprt the
construction of .CCM files. However ,we neglected to inclttle
information in the Version 2.10 addendun about this feature.
If y: >u use our standard installation procedure as dem"ribed in
the aidendun, your hard disk will contain adirectory "\lc\c" and
abatch file "linkc.bat". In the former )pü will find versions
Ed "c.obj" and "dos.mac" that must be lg21Í 'when constructing .CCM
flies. !Ihe general procedure is:
l. Compile ytjlk Cincdulc's under the mall mcidel (e.g .via
the LCS batch procedure) ;
2. Assemble yrmr assembl Y-larWjage prog rms wirK3
"\lc\c\dos .mac" .
3. Link everything oing the LINKC batch [Kocedure. This
sMuld cause a "NO stack sEayENr warning messaje, which can
be ignored .LINKC also calls the ms-ujs utility EXE2BIN to
convert the linker .EXE output into the desired .CCM fo mat.
Njte that j,rjl1 cannot produce a.CXM file if any of the included
modules defims astack segment or contains segment fixups.
Compiling mder the mall model md linking with the sFecial
version of "c-obj" guarmtees that these two criteria are met.
Assmbl irig with the special version of "dos.mac" does not
guarantee that your asstnbly-language can be used to construct a
.CXMr so you might want to take alook at "c.am" tD see Ikyw" we
set it up to avoid segment fixups.
"**ENIM*
TECFNICAL BULLETIN
'IB840523. 002
IjATE: May 23, 1984
FR(XjUCT: 8086/8088 CGcmpiler, Version 2.10
SLBjBCT: Nturn values for wrocs and INT86
°Ihe Version 2.10 iáddendun did not mmtim achange that we made
in IÑITRS, INT'DC6X, INT86, arxí IbW86X as a result of requests
frcxn many users. These fmctions now return the processor status
flags instead of the AX register valw. Many MS-lXj¢3 interrupt
functions use the flags (especially the carry flag) to convey
information back to the caller, arid there fS previously no way
for the Cpí»;jran to obtain this information after calling one
the above functions. The fl'ags are defined in any 8086/8088
instruction manual .
Note that if jpur prcxjran is assuning that these functions return
AX, it must be changed to obtain AX fran the "outregs" stcucture
as descr ibed in the Lattice C Manual.
We have also had several queries Eran people ^are tryim to
use IW86 or INT86X to perform absolute disk reads and writes via
interrupts 0x2S and 0X26. This will not mrk because tNse Uk)
interrupts return with the status flags still µished on the
stack, as is discussed in the MS-DOS aM FC-IXJG Programér's
Reference.
***END***
TECHNICAL BULLETFN
TB8406I5.001 '
DATE: june 15, 1984
PRODUCT: 8086/8088 CCompiler, Version 2.Zl
SUBjECT: Vecsion 2.12 Update
Version 2.12 of the 8086/8088 Ccompiler has been released to
correct the following problems:
l. Null #defines were not handled correctly. That is, a
statement such as
#define XYZ
caused aspurious error message.
2. The STRNCMP function did not always return the correct
vaíue.
3. The character count returned by the STCCPY function did
not include the null terminator under some circumstances.
4. Flit fields were not compiled correctly as a result of
changes introduced in Version 2.10.
5. The ÍNT86 and INT86X functions did not work correctly in
ail cases because some DOS interrupts destroyed the bp
register.
6. When you defined fmode to Ox8000, the standard files
(stáin, stdotit, and átáerO were not switched into raw mode
by main.
7. Because of apackaging error, the Version 2.00 copy of
MAIN.C was included on the 2.1 release disks. The correct
fiLe is called MAIN.C and is now included. Do not use the
old MAIN.C with Version 2.1.
8. STDIO.H has been changed to define NULL as Ofor the S
and pinemory models and as DL for the Dand L models.
9. Sevetml people complained about the load module size
increase caused by the DOS compatibility feature described
in Section 3of the 2.1 addendum. Therefore, we have
changed the átandard libraries so that the I/O functions
work only with DOS 2. If you still want to becompati5le
vñth DOS I, the release disks contain files named IOSIX.OBj,
where xis the memory model (S,D,P, or L). Include the
approDriate copy of IOSl when you link, and your program
will work with both DOS IandDOS 2. If you want to save a
Little more memory, examine _MAIN.C and remove the code that
is specific to DOS I.
LO. If you declared afunction to return achar or float
value, the function would actually return an int or a
double, respectively. This has been corrected. Note that
this bug is suspected to exist in several other compilers,
particularly on UNIX sYstems, and some people have fallen
into sloppy coding practices because of it. The most common
pitfaLl ia illustrated below:
In module ti:
char func()
{
chac c;
return(c);
]
In module 12:
int x;
x=func();
The contents of x"s high order byte will be garbage, because
the modale 42 implicitly declares func to return an int even
though it is actually returning achar. On the 8086, what
this means is that func places cin theAL register and does
nothing with AH, which is acode improvement.
II. Section 2.7 of the 2.1 addendum indicates that constants
are not allowed as operands in logical expressions. This
restriction has been removed because it broke several
existing programs.
12. There is atypo on page 5of the 2.1 addendum. In the
second last line, the word "constant" should be "comment".
13. There is atypo on page 35 of the 2.1 addendum. In the
description of the -mds option, the -3 flag applies to LCl,
not LC2.
14. The -X and -n flags were not recognized by the LC.COM
command.
15. The header file SETJMP.H was omitted from the 2.10 and
2.11 release disks.
16. The 2.10 and 2.11 releases contained libraries that were
not compiled with the -s option, which resulted in a
performance degradation.
17. The 2.1 addendum did not make it clear that LC.COM only
recognizes Csource files that are "in the current directory.
If you type
LC \stuff\abc
the command will not find the source file.
If you have already purchased 2.10 or 2.11, you can receive a
free update to 2.12 by simply sending the original release disks
to us with areturn mailer.
***END***
?lib86: PSA object Library Manager
Table of Contents
Table of Contents
Library Manager Concepts .. . . . .l-l
Using Plib86 .. . . . . . .. . . . 2-l
Creating/Merging Libraries . . . . 2-l
Library Search ... . . . . . . . 2-2
Updating alibrary .... . .. . 2-3
Module Extraction ........2-3
Cross reference listing . . . . .2-4
Plib86 Commands .... . . . . ...3-l
Input Format .. . .. . .. . ..3-l
Identifiers ...... . . . . 3-l
Disk File Names . . ......3-2
Initiating Plib86 ...... . 3-3
Command Format . . . . .. . . 3-5
object Files ... . .. . . . . . 3-6
FILE, LIBRARY, SEARCH .....3-6
AS .. . .. . ... . . . . . 3-8
INCLUDE, EXCLUDE .. . . . . . 3-8
Building aLibrary ....... . 3-9
BUILD ... . . . . . . ....3-9
INTEL . . . . ........ 3-lO
Extracting aLibrary Module . . 3-ll
Generating Reports ... . ...3-12
WIDTH, HEIGHT .... . . . . 3-13
BRIEF ........ . ... 3-13
Controlling the Library Index .3-14
NOINDEX .. . .......·. 3-14
BLOCKS .. . . . .. . . . .3-15
Miscellaneous Commands . . . . .3-17
VERBOSE ...... . . . ..3-17
BATCH .. . . . . ... . . .3-17
LOWERCASE . . . . . . . . ..3-17
Appendix A-Warning Messages .. . .A-l
Appendix B-Error Messages . . ...B-l
Appendix C-Reporting Problemg ...C-l
Plib86: PSA object Library Manager i
Introduction
Plib86 (tm) is aPhoenix Software
Associates Ltd. software system that can
manipulate libraries of object files. It
supplements the PSA linkage editor
Plink86 (tm), and is intended for use on
the Intel Corporation (l) 8086 (or 8088)
processor (tm) under the MS-DOS (2) or
CP/M-86 (3) operating systems.
plib86 handles object files and
libraries conforming to the INTEL
relocatable file format described in
their document "8086 Reloeátable object
Module Formats" #121748-001. This format
is used in compilers written by Microsoft
Corporation, creator of the MSDOS
operating system, by most other companies
wUtinú compilers for MSDOS, and by afew
compilers written for Digital Research's
CP/M-86 operating system. However, a
different library index is used by
Microsoft to achieve faster library
searches. ?lib86 can read and generate
both tkt' Intel and Microsoft library
index torrnats.
The first Section of this manuál
provides an explanation of the "object
library" concept and the capabilities gf
Plib86. User's unfamiliar with library
managers would do well to start here.
Also, the Plink86 user's guide contains a
chapter discussing object files and
linkage editors that may be helpful.
The next section of this manual
describes how to use plib86 to handle
several common object library situations.
At the same time it provides an informal
explanation of what the commands do.
Those readers experienced with linkage
plib86: PSA object Library Mañager ii
Introduction
ediÉors and library managers rnay wish to
skip directly to this portion of the
manual: it provides enough information
to handle most jobs.
The final portion of the manual is
an exhaustive list of the commands and
features offered by PIib86. This should
be examined when it becomes necessary to
go beyond the examples given in the
previous section. Side issues such as
error codes are generally referred to
appendices.
Trademark Acknowledgements:
(I) INTEL is atrademark of Intel
Corporation
(2) MS-DOS is atrademark of Microsoft,
Inc.
(3) CP/M-86 is atrademark of Digital
Research.
Plib86: PSA object Library Managér l-l
Library Manager Concepts
Typically it is convenient (if not
essential) to divide alarge programming
job into smaller pieces called "modules"
that can be edited and compiled
separately. Actually, compilers
available on micro-computers tend to have
severe limitations on how many lines of
code can be compiled at one time, forcing
the programmer to use modularization
anyway. On the positive side, modular
programming offers amethod of organizing
aprogram into manageable pieces that are
easier to understand and work with.
After the program modules are
created and compiled the programmer must
"link" them together with a"linkage
editor" to produce the executable program
(see Plink86 user's manual).
Once one has created amodular
program one may find that some of the
modules are useful in adifferent
program. With alittle effort these
modules can be made more general in
function and can be used in many
programs. The programmer can gradually
build up a"library" of useful routines
that can be hooked in by the linkage
editor whenever needed.
In fact, virtually all compilers are
sold with a"library", since functions
like arithmetic on real numbers are often
not supported by the hardware and have to
be implemented as procedure calls. The
compiler library also contains modules
that support the high level features of
the language such as formatted output in
FORTRAN. This library is often called
the "run time support" since its modules
are required while the program executes.
Plib86: PSA object Library Manager l-2
Library Manager Concepts
Other software products in addition
to compiler runtime support routine8 ate
sold in the form of libraries. An
example might be aset of data base
management routines that is combined with
the application program by the linkage
editor to produce acomplete system.
Because of the importance of
libraries, linkage editors typically have
special facilities for handling them. To
save memory space, only those modules in
the library that are actually required by
the program are linked in. Sometimes a
library is simply aconCatenation of
object modules, requiring the linkage
ediÉor to search sequentially for the
required modules. More sophisticated
systems provide a"library index". It
contains alist of the public symbols
offered by each library module, and the
location of the module that defines each
symbol. Therefore the linkage editor can
rapidly locate the modules that are
required. The Microsoft and Intel
library formats are indexed structures.
The purpose of the library manager
is to create and manipulate object module
libraries. It is therefore auseful
assistant to the linkage editor.
plib86 provides commands to create
libraries from individual object modules,
and to extract aselected module from a
library. It can also merge libraries,
and can replicate the library search
process undertaken by the linkage editor
while creating aprogram. In other
words, one can create alibrary
consisting of only those modules that the
link"age editor would include in a
particular program.
Plib86: psa object Library Manager l-3
Library Manager Concepts
Plib86 also provides apowerful
cross-reference function. It optionally
generates a.report listing each public
symbol, the module which defines it, and
alist of other modules that refer to it.
This may be used to cross-reference a
single library or several librarje3
together, or, in combination with the
library search feature described above,
to generate across-reference of a
program that will be created by the
linkage editor.
Plib86: PSA object Library lqanage¥ 2-l
Using plib86
Creating/Merging Libraries
To create anew library use the
BUILD command and the FILE command. For
example, executing plib86 and entering
BUILD DB.LIB
FILE BTREE, SORT, REPGEN,
FIRSTLIB.LIB;
in response to the prompt would create a
library named DB.LIB containing the files
listed'after the FILE command. These
files could be single object modules or
complete libraries. Everything is merged
into asingle library. The default file
type for the files appearing in the FILE
statement is "OBJ".
PIib8ÉA PSA Object Library Manager 2-2
Using Plib86
Normally you can just execute Plib86
and type in commands on as many lines as
desired. Then end the last line with a
semi-colon to begin processing. Each
statement begins with akey word like
BUILD or FILE and is followed by
arguments, possibly separated by commas.
Input is free format, and blank lines are
ignored. Also, key words may be
abbreviated by leaving off characters at
the end. For example, you can use BU and
FI instead of BUILD and FILE. An error
message will be given if the abbreviation
could be confused with ánotíjer command.
Another way to use Plib86 is to give
the commands as it is executed. For
example, the above library could have
been created by entering (on one line):
PLIB86 BU DB FI EJTREE, SORT,
REPGEN, FIRSTLIB.LIB
Note that the output file type
defaults to "LIB" automatically.
Library Search
Suppose you want to create alibrary
consisting of several modules plus those
portions of another library that are
referenced by the modules. Use the
LIBRARY command:
BU DB FI BTREE, SORT, REPGEN
LIB FIRSTLIB.LIB
The portions of FIRSTLIB not
referenced by the three.other files are
not put into the DB library.
plib8G: PSA object Library Manager 2-3
Using plib86
Updating alibrary
To update alibrary it is necessary
to copy the old library to the output
file while omitting the module to be
updated, and to include the new module.
For example, to replace module COSINE in
library MATHLIB, rename the current
MATHLIB.LIB to MATHLIB.OLD and enter
BU MATHLIB FI COSINE,
MATHLIB.OLD EXC COSINE
The EXCLUDE statement applies to the
previous file name given and causes the
COSINE module in the MATHLIB to be
omitted.
Module Extraction
The EXTRACT statement causes a
single object module file to be created.
It may not be used at the same time as
BUILD. The first object module found in
the input files is extracted, so the
particular module to be selected from a
library must be specified. The object
file extracted may be given any file
name. The module name remains the same.
For example, typing
EXT OLDCOS FI MATHLIB.LIB
INCLUDE COSINE
creates file OLDCOS.OBJ containing object
module COSINE. The INCLUDE statement is
the counterpart of EXCLUDE: it applies
to the previous input file and causes
only those modules named to be considered
for processing. There wouldn't be any
point to INCLUDing more than one module
in this case since only the first one
found is extracted.
plib86: PSA object Library Manager 2-4
Using plib86
Cross reference listing
To create across-reference listing
use the LIST command with input file
statements similar to those given in
previous examples. For example,
LIST =DB S
FI BTREE, SORT, REPGEN, FIRSTLIB.LIB
creates across reference report named
DB.LST describing the modules in all of
the.files listed. The "S" selects the
cross-reference report. For a
description of other reports available
see the LIST command description. The
"=" specifies that the report is to be
put into adisk file. If omitted the
report appears on the console.
Plib86: PSA object Library Manager 3-l
Plib86 Commands
Input Format
This portion of the manual describes some
basic input elements. Later sections
show how these are combined to create
full statements.
Identifiers
An identifier is the name of some
object, such as amodule or symbol. An
identifier is asequence of no more than
64 characters containing no spaces, and
containing none of the following:
"=;<>/,\!'#U'+-: @DEL
Lower case letters, when used, are
automatically translated into upper case.
The first character of an iáentifier may
not be adigit 0-9.
The above restrictions on valid
identifier characters may be avoided by
using the escape character """. The
character immediately following the
escape character is treated as a normal
identifier character.
The following are examples olE valid
identifiers:
Programl
SORT3
ABC"@ (the "@" is escaped)
The following are not valid
identifier8:
34ABC -begins with anumber
NII'I A-containB aspace
Plib86: PSA object Linirary Kanágc'r :J-¿
Plíb86 Commands
PROGtl -starts acomment wittj "*"
The above identifíers could all be
made valid witn the escape character:
"34ABC
NIM" A
PROG"tl
To include the escape character in
an identifier enter two escape characters
Identifiers appearing in object
files are truncated to 50 characters for
purposes of comparison with other
identifiers in the program. Identifiers
may be truncated again for inclusion in
reports (see the LIST command).
Disk file Names
Plib86 adapts itself to the file
name format used by the operating system
it is executing under. The first
character not allowed to be in afile
name terminates the name. The escape
character rnay be used to put any
character into afile name.
In this manual, MS-DOS format file names
are used for purposes of discussion.
These file names are of the form
[device: ]namel.type), with optional
portions in brackets. Here are some
exampi¢zs:
MATHLIB.L"IB
B: CHESS.OBJ
SCANNER
Plib86: PSA Object Library Manager 3-3
Plib86 Commands
When the "device: "is not given,
plib86 assumes that the ctjrrently
logged-in disk is to be used.
Initiating Plib86
Plib86 may be used interactively, or
input may be given as it is executed:
plib86 statements <cr>
where <cf> means to press the RETURN key.
This means that Plib86 may used in .BAT
files.
To use Plib86 in the interactive
mode, enter
Plib86<cr>
on the console. Plib86 will read lines
from the console, prompting-with "=>"
The standard line editing features
8upplied by the operating system are
available. plib86 checks input lines for
syntax and stores them until asemi-colon
';' is entered at the end of aline.
Then processing of the input files
begins.
Adisk file containing all or,only
part of acommand may be inserted into
the input at any point by preceding the
disk file name with an Y". The default
file type is ".LNK". These disk files
can contain further "@" specifications,
up to three levels deep. The most common
use of this feature is to prepare afile
containing acomplete command; then,
entering
plib86 @file name <cr>
Plib86: PSA object Library Manager 3-4
Plib86 Commands
creates the library. Sometimes these
".LNK" files may be prepared once for a
given library and used over and over
again, greatly simplifying the whole
process.
plib86 reads an entire command,
checking for syntax only, Defore any file
processing is done.
Plib86: PSA object Library Manager 3-5
Plib86 Commands
Command Format
All Plib86 input is free format.
Blank lines are ignored, and acommand
may extend to any number of lines.
Comments may be included with input from
any source by using apercent sign "%".
When this is encountered, all remaining
characters on the same line are ignored.
Input is alist of statements:
<statement> <statement> ... <statement>
Each statement begins with akey
word, and many are followed by arguments
separated by commas. For example, in
FILE A,B,C
0
FILE is the key word, and A, B, and
Care the arguments. Key worás may"be
abbreviated by omitting trailing
characters, as long as the abbreviation
is unique among the entire group of key
words. For instance, the previous
statement could have been entered as
FI A,B,C
If asyntax error is found, the,
current input line is echoed with two
question marks inserted after the point
at which the error was detected. This is
followed by an error message (see
Appendix). Hib86 pust then be
re-executed.
If an error occurs during file
processing, plib86 terminates with ar,
error message also listed in the
appendix.
Plib86: PSA Object Litnary Manager 3-6
plib86 Commands
Object Files
FILE, LIBRARY, SEARCH
Plib86 must be told what object
files and libraries to use for input and
what modules to select from them. The
FILE command is typically used, and
normally causes all modules with the
given files to be processed:
FILE COSINE, SIN, ARCTAN
Ttie library and SEARCH commands are
similar, but are used only on libraries
and select only those modules that define
apublic symbol that is needed by some
other module that has already been
processed. This is called a"library
search" and is aprocess carried out by
most linkage editors. It insures that
onl',' those library modules that are
ar ally needed are included in the
>gram.
LIBRARY MATHLIB
SEARCH FORTRAN
The LIBRARY command causes the given
libraries to be searched once. When the
SEARCH command is used the libraries are
searched repeatedly as long as undefined
symbols remain. This won't be needed
unless two or more libraries are being
searched that each refer to symbols
defined in the others.
If Plib86 can't find arequested
object file, and is running under the
MSDOS 2.0 operating system, it will look
in the environment for astring named
"OBJ". The value of this string is
Plib86: PSA object Library Manager 3-7
plib86 Commands
assumed to be one or more directory path
names, separated by semi-cqlons (just
like the MSDOS 2.0 PATH Command). These
path names are appended to the front of
the object file name (any disk drive ID
is removed first) one at atime in an
effort to find the file. The path name
separator '\' is added between the path
name and file name. For example, 'if
SET OBJ =\OBJECT; \LIBRARIES
were entered before running plib86, and
file TEST.OBJ was being searched fór, it
would look for \OBJECT\TEST.OBJ and
\LIBRARIES\TEST.OBJ. This means that
commonly used object files can be left in
adirectory for use by many programs.
If an input file can't be found by
using the OBJ path names, or if MSDOS 2.0
is not the operating system being used,
the operator will be asked to enter a
file name prefix string (e.g. "A:"or
"\OBJECT\" that will be appended to the
front of the file name after stripping
any drive id .Diskettes may be changed
at tÍÜ8 time if necessary. of course,
the operator must insure that any
diskettes removed do not contain open
file8 like the BUILD or EXTRACT file.
AÁbo, if Plib86 runs out of memory a work
file 18 opened on the default diMc, which
then may not be removed.
Plib86: psa OLject Library f!arjdger 3-8
Plib86 Commands
AS
If an object file (not alibrary) is
being processed the module it contains is
given the same module name as the name of
the file it came from This is done
because some compilers don't supply a
unique module name. This default may be
changed by using the as statement. It
supplies the module name for the last
file náme given. For example,
FILE MATHI AS COSINE
would name the module in KATHI COSINE
instead of HATHI.
INCLUDE, EXCLUDE
The modules selected from alibrary
may be further restricted by using the
INCLUDE and EXCLUDE 6tatements. The6e
are followed by alist of module names:
FILE MATHLIB INCLUDE SIN, COSINE
LIB t'lATHLIB, DB EXCLUDE BTREE
The INCLUDE statement causes only
those modules listed to be considered for
processing, and this selection precedes a
librSlry search. EXCLUDE is the opposite.
The modules listed are not processed.
INCLUDE ana EXCLUDE apply to the FILE,
LIBRARY or SEARCH file immediately
preeeding. In the second example above,
for instance, the EXCLUDE BTREE applies
only to the DB. library, not MATHLIB.
plib86: PSA Object Library Manager 3-9
Plib86 Commands
Building aLibrary
BUILD
The BUILD command is used to create
alibrary out of the modules selected
from the input files. It is followed by
the name of the file to create. The file
type defaults to .LIB:
BUILD DB.LIB
BUILD D:PIATHLIB
After all modules are output the library
index is created.
One must be careful that the output
file does not have the same name as any
of the input files. For instance,
entering
BUILD MATHLIB
FI COSINE, ARCTAN, MATHLIB
won't work because MATHLIB will be erased
before it is read.
The BUILD command may not be used
Mnultaneously with the EXTRACT command
(described next). If no output is
requested from plib86 (i.e there is no
BUILD, EXTRACT or LIST command) then
plib86 will simply read the input modules
and report any errors it finds.
plib86: PSA object Library Manager 3-ID
Plib86 Commands
INTEL
By default, the BUILD command
constructs aMicrosoft format index for
the library file under construction.
When this statement appears, however, an
INTEL format index is constructed
instead. No arguments are required.
When creating an INTEL format index, tbe
LOWERCASE statement may have to be used
to inhibit translation of symbol name
characters in the index to upper case.
Sorne compilers using Intel format
libraries distinguish between upper and
lower case when comparing symbol names.
plib86: PSA Object Library Manager 3-ll
plib86 Commands
Extracting aLÍbrary'Module
The EXTRACT command is used to
extract asingle object module from a
library file and place it into aseparate
disk file. It is followed by the name of
the file to create:
EXTRACT COSINE.OBJ
EXTRACT ARCTAN
If the file type is omitted OBJ is
assumed.
The EXTRACT command extracts the
first module found in the input files.
Therefore it is usually necessary to use
the INCLUDE statement to specify which
library module should be extracted. For
instance,
EXTRACT COSINE FI MATHLIB
extracts the very first module in
PLATHLIB, even if it is not the COSINE
module. To get the correct one enter
EXTRACT COSINE FI MATHLIB INC COSINE
Plib86: PSA Object Library Manager 3-12
Plib86 Commands
Generating Reports
The LIST command is used to generate
reports about the object files being
processed. It may optionally be followed
by afile name, causing the reports to be
directed to that disk file or device.
The file name must be preceded by an
equal sign. Then acharacter is entered
for each report desired, separated by
commas. There are two reports available:
M-Alist of all modules processed
in alphabetical order. Next to
each module is listed all of the
symbols defined within it.
S-Alist of all public and
external symbols in alphabetical
order. Each is followed by the
name of the module defining the
symbol in parenthesis (this will
be blank for symbols not defined
by any module read). Following
this is an alphabetical list of
all modules that access the
symbol (i.e. this is a
cross-reference report).
Here are some examples:
LIST YI
LIST =DB.LST PI, S
LIST =XREE.LST S
plib86: PSA Object Library lianager Y-13
plib86 Commands
WIDTH, HEIGHT
The report generator can be
re-configured for different size paper.
It assumes 80 columns and 66 rows per
page as a default. The number of columns
may be changed with the WIDTH command,
and the number of rows wíth the HEIGHT
command. Here are sorne examples:
WIDTH 132
HEIGHT 88
BRIEF
The Soption of the LIST command can
be quite long. If the BRIEF command is
used, however, all undefined symbols are
deleted from the report, making it more
manageable. These undefined symbols
might be from libraries that you did not
search in creating the report, and wight
not be necessary in the report. The
BRIEF statement has no arguments.
plib86: PSA object Library Manager 3-14
Plib86 Commands
Controlling the Library Index
NOINDEX
Normally all public symbols from all
modules are inserted into the library
index. If aduplicate symbol is found
library creation continues but awarning
message is given and the index entry for
that symbol will select the first module
defining the symbol.
Sometimes it is useful to exclude
certain symbols from the library index.
This may be accomplished by using the
NOINDEX command. For example,
NOINDEX SYMI, SYM2, SYM3
excludes SYMI, SYM2, and SYPi3 from the
index.
Suppose you wish to create alibrary
that contains several versions of the
same module, for instance adevice driver
for some kind of hardware. If you try to
place all of the modules into the library
you will get duplicate symbol warnings,
and at link time the linkage editor
wouldn't be able to select the desired
module.
This can be made to work by using
NOINDEX on most of the moáule entry
points. This excludes all of these
symbols from the library index. To get
the linkage editot to select the correct
module insert an un-used but unique dummy
symbol into each one. At linkage edit
time one of these dummy symbols would be
accessed in order to create aneed for
the desired modulo. TfW linkage editor
Plib86: PSA Object Library Mañager 3-15
Plib86 Commands
would then select it when the library is
searched.
Using plink86, for instance, one
could use astatement like
DEFINE FOO=DRIVERI
to select the module containing the
"driverl" dummy entry point. An
alternative which works in aMicrosoft
format library is to rely on the fact
that the name of each module is actually
in the library index as well, followed by
an exclamation point. For example, if
the library contains amodule nainea
DRIVERI then there will be adummy index
entry named DRIVERI!. These symbols can
be used instead of creating adurnmy
module entry point as discussed above.
BLOCKS
The Microsoft library index consists
of aprime number of hash blocks. Plib86
will choose the amount of index space
needed so that everything fits and then
adds about a10% slop factor. The extra
is added because the hash blocks are set
up as a"scatter table" (see Knuth's
volumes of computer programming) and
search time can increase dramatically as
the blocks become nearly filled.
However, if the linkage editor reads most
or all of the index into memory when
doing alibrary search (as plink86 does)
this may not matter too much. The extra
time spent comparing iáentifiers is more
than made up for by the savings from
reading fewer index blocks from disk.
plib86: PSA object Library Manager 3-16
Plib86 Commands
The BLOCKS command functions only
when the BUILD command is used, and
specifies the number of index blocks to
be used. For example,
BLOCKS 7
forces Plib86 to use 7blocks. If
some of the symbols won't fit into the
index Plib86 will print warning messages.
If the argument to the blocks command is
not aprime number Plib86 will increase
it until it is. The limit on the number
of library index blocks is 997.
plib86: PSA Object Library Manager 3-17
plib86 Commands
Miscellaneous Commands
VERBOSE
When processing alarge library file
it is sometimes useful to know what
plib86 is doing. When the VERBOSE
statement is used Plib86 will maintain a
status line at the bottom of the CRT
screen indicating what is going on. This
statement should not be used on a
hard-copy terminal.
BATCH
If Plib86 can't find an object file
or library it will normally prompt the
operator to enter the name of adisk
drive or directory path name where the
file may be found. The BATCH command
will cause Plib86 to stop with afatal
error without prompting the operator. It
is useful when running plib86 from within
abatch file and no operator is available
to respond to aprompt.
LOWERCASE
Any object files and libraries
conforming to the Microsoft standard
normally use only upper case letters in
identifiers. Therefore Plib86 normally
translates all lower case letters to
upper case. This statement inhibits this
translation for all identifiers found in
object files, library indices, or Plib86
commands. It is sometimes necessary to
use this command when an Intel format
library is being built (see the INTEL
command).
plib86: PSA object Library Mañager 3-J.
Appendix A-Warning Messages
Occasionally PliD8E. ctetectm a
situation that looks like It ÍüiYtjt be a
problem when the iñpti'c Cbt outp: "object
files are processed by the link: age
editor. It then issues auarning m"?32;age
and continues to execute. TMse lne.4sages
should be self-explanatory, but anurabc!:
is also given that may be lookec' '.ip in
this appendix to get amore complete
explanation of what has happened.
I-There may be only one definition for
each global (i.e. PUBLIC) symbol in
the object modules being processed.
Plib86 ignores the duplicate
definition and retains the first one
lck use in any library index or
reports being generated.
2-Each record in an object file
contains acheck field at the end
for validation purposes. This
message indicates the checksum was
bad, but processing continues.
These messages are inhibited after a
few have been printed. Was the
object file patched on disk before
Plib86 read it? TYpically people
who patch object files don't bother
changing the checksum. Also, some
compilers and other librarians seem
to be sloppy about making sure the
checksums are correct. If the file
is really smashed afatal error will
probably occur soon after this
message appears.
Plib86: PSA object Library Manager A-2
Appendix A-Warning í'tessages
3-Each record in an object file is
preceded by aword giving the record
size. This error means that Plib86
reached the end of the record and
found that the number of bytes
processed iSdifferent from the
specified size. The object file is
probably smashed, but Plib86 will
attempt to continue reading it.
4There is no room in the Microsoft
library index being created with the
BUILD command for the named symbol.
You probably used the BLOCKS command
to reduce the size of the index, and
now it is too small to hold
everything. This warning should
never occur if you haven't used the
BLOCKS command: contact Phoenix
Software if i" does.
plib86: psa object Library Mañager B-l
Appendix B-Error Messages
When afatal error is detected by
plib86 aconsole message is printed which
should be self-explanatory. However, an
error number is also printed which may be
looked up in the table below. Alonger
discussion of the error will be found
there.
Command Syntax Errors
These errors are caused by mistakes
made in the input given to Plib86.
Re-run Plib86 after correcting the
problem The input line causing the
problem will be displayed on the
terminal, with acouple of question marks
inserted after the point where the error
was detected. These should aid in
locating the problem, but occasionally
Plib86 may not detect the error until
more text is processed. In other words,
if the error location is given as the
front of aline, check the end of the
previous line.
I-"@" files are nested too deeply.
Only three levels of "e" files may
be active at any given time. Do
you have aloop in your "@" file
references?
2-Disk error encountered while
reading Y" file. Try re-building
the file.
5-The item given for input at thi8
point is too large. The maximum
size allowed is 64 characters.
plib86: psa object Library Manager B-2
Appendix B-Error Messages
6-Invalid digit in number (i.e. not 0
thru 9).
10 -Invalid file name. The input
stream should contain avalid file
name for the particular operating
system being used.
II -Expecting astatement. Akey word
which begins astatement should be
present here.
12 -The INCLUDE and EXCLUDE statements
may not be used simultaneously on
the same input file.
í4 -Expecting identifier. Asection,
module, segment, or symbol name
must be entered at this point.
16 -Expecting avalue. An expression
or l6-bit quantity must appear at
this point.
17 -No files were given to process!
You must use the FILE statement and
specify at least one input file.
18 -The BUILD and EXTRACT commands may
not be used simultaneously. You
must run Plib86 twice with one
command in each.
plib86: PSA object Library Manager B-3
Appendix B-Error Messages
Work File Errors
when Plib86 runs out of memory it opens a
woEk file on disk named Plib86.WRK to
hold the description of the library.
These error codes indicate aproblem with
processing the work file.
30 -The work file can't be created.
Probably there is no space in the
disk directory.
31 -An I/O error occurred while writing
the work file.
32 -Ari I/O error occurred while reading
the work file.
33 -An I/O error occurred while
positioning the work file.
34 -There are too many module
description objects in this library
(about 50,000 symbols, modules, and
so on may be defined). This
library is too large for plib86 to
handle.
Plib86: PSA object Library Manager B-4
Appendix B-Error Messages
Input object File Errors
The following errors have to do with the
object files that are given to plib86 to
process. Usually they occur when afile
has been corrupted somehow. Try
re-compiling to get anew copy of the
object file. If it is alibrary supplied
by the compiler manufacturer that is
causing the problem, try to get afresh
copy of it.
41 premature end of input object file.
The end of the indicated file was
reached unexpectedly. Possibly,
the file was truncated by copying
it with aprogram that assumes a
CNTL-Z (IAH) is end of file.
42 -Fatal read error in object input
file.
plib86: PSA object Library Manager B-5
Áppendix B-Error Messages
Output File Errors
The following errors are caused by a
problem in creating the output code file
or memory map file (when written to
disk). Often, they are caused by afull
dísk or disk directory, adisk that is
write-protected, or some kind of hardware
problem with the disk.
45 -Can't create output disk file.
Possibly the disk directory is
full, or the disk is write
protected.
46 -Output file too large. The given
modules won't fit into the library.
You will have to break up the
library into one or wore smaller
ones.
47 -Fatal disk write error in output
file. Possibly the disk is full or
write protected, or some kind of
hardware error has occurred.
48 -Fatal disk read error in output
file. An irrecoverable hardware
error has probably occurred.
49 -Can't close output file. The disk
is probably write protected, or a
hardware error has occurred.
50 -Can't create the LIST output file.
possibly the disk directory is
full, or the disk is write
protected.
plib86: PSA object Library Manager B-6
Appendix B-Error Messages
Miscellaneous Errors
51 -There are too many symbols to be
placed into the library index. You
will have to break up the library
into one or more smaller ones.
52 -No modules were selected (by
library search, INCLUDE, or
EXCLUDE) to be placed in the output
file (BUILD or EXTRACT).
54 -There isn't enough memory in the
computer to run plib86. You must
have areally tiny memory -better
buy more!
Plib86: PSA object Library Manager B-7
Appendix B-Error Messages
Plib86 Bugs
These errors indicate abug in Plib86 has
occurred through no fault of your own.
They are li8ted here for completeness in
the manual, although it is unlikely that
you can do anything to correct them. Try
running plib86 again. If the error
persists, please gather the relevant
information and contact Phoenix Software
Associates.
201 -No NeedRead Buffers (NRnew).
20S -Seek errors while writing output
file (attempt to seek past end of
file).
210 -Requested record size too large
(Newrec).
219 -Bad object block (GetBlock).
221 -Invalid object key (Q).
222 -Invalid object key (QK).
Plib86: PSA object Library Mañager C-l
Appendix C-Reporting problems
We ask that you make areasonable
effort to solve your difficulties
yourself before contacting us, and to
phone only if you are trying to deal with
an emergency. Otherwise, please report
your problem in writing. We can read
much more quickly than we can listen.
Our address is:
Phoenix Software Associates, Ltd.
1420 providence Highway
Suite 260
Norwood, MA 02062
Be sure to include with your
description of the problem the input you
are trying to use and where your object
files came from. If you like, send
input, object, and library files on
diskettes (MSDOS l.l or 2.0 51/4 format,
single or double sided), and instructions
on how to run the software to make the
error condition occur. Source files are
usually unnecessary. We will be happy to
sign non-disclosure agreements to protect
your software, if having it will help us
identify abug more quickly, and to
return the diskettes to you after the
problem has been identified.
LIFKbOiAT ASSOCIATKS sorrvw ñO6W RKPORT
Ple&8e u8é thíB form to report error8 or problea8 Id Boftv&re BupplIed by
Lifeboat ABBocÍaCem Thh form i$ deB[Brbed to act a6 a tranBmí[t&l 8Íleet.
Software Product Name: Kedí& Format:
Ver6íorj No.: SeríU No.: Invoice No.:
Purchaoed Froa:
Wte of Purchaee: Kecurn AuehorizmEFon t:
H8b the mftvnre reglstmtíon card been recurned?
Co.puter [ked: CPÚ (8080/B085/Z-dO):
WbÍk C&paclty: Nmber of Drlveo: Mmory S1Ee:
Operating Sy8tem/Ver8¿oQ (If not liBted &bove): l
Softvare uBed vlth the above product, (e.g. int the BASIC umd if you are
reporting aproblem with mPayroll progrem that ubcb ft).
Nmme of Software VerUon
Docb che 8oftY&re come wLth B8Rple or té8t prograwH
If bo, Mve you been &b1e to ubc tbm BucceB8ful}y?
Pleaee deecríbe the problem you Imve encountered. Include reterence6 to the
mwiudl ff appropriate. Try to reduce the problem to awSmple teBt caBe.
Enclo8e aoy appropriate programs (preferably on dhk). It you feel thA[ the
proble® m8y be camed by the d[8k being defective, you my prefer to retura the
origlKj8l U8jl with U1Íb report to &chieve the faBteDt re&olutiorl of the
problem. (U bo, cUI for &Return Authortzú£on No. ahandjAmg cMrge m»y be
incurred. No handllmg ch&r8e will be m&de it &product or portion thereof io
returned DUB TO DISKKTTE PQKDIA DEYECTS wíthlm JO d&yB from the dete of ule).
0Inform&tion on product ehAnBe8, bugji, fíxé$ and current verwion Rumber8 are
publLBhed tu Llfelimm our ooftware oevUetter.
PRQBLEK WSCRIPTION: (Cotltíaue on Md£tlonU p&ge6 if neceuary)
Aru Phoñe Wum EXtw
Mme: ()"()
Addre8B: ( ) "( )
City: StÁte: up Code:
Return to: Lifeboat MBoci&te8 Technicnl B8BIBtánce í8 &v&llab]e
1651 Third Avenue Honday -Friday, from ll:üO mm.
Nev York, N.Y., 10028 to 7: 00 pm., É88terrj tine.
1-(212) 860-0300
002prob.bn.09.8l TVX: 710-581-2524 Telex: 64U693

Navigation menu