프로그래밍/MSX 개발

HI-TECH C User's Manual

windship 2023. 9. 14. 17:46

HI-TECH C USER'S MANUAL i
CONTENTS
1. Introduction 1
1.1. Features 1
1.2. System Requirements 2
1.3. Using this Manual 2
2. Getting Started 3
3. Compiler Structure 5
4. Operating Details 7
5. Specific Features 13
5.1. ANSI C Standard Compatibility 13
5.2. Type Checking 13
5.3. Member Names 13
5.4. Unsigned Types 14
5.5. Arithmetic Operations 14
5.6. Structure Operations 15
5.7. Enumerated Types 16
5.8. Initialization Syntax 16
5.9. Function Prototypes 17
5.10. Void and Pointer to Void 18
5.11. Type qualifiers 19
5.12. 20
5.13. Pragma Directives 20
6. Machine Dependencies 21
6.1. Predefined Macros 21
7. Error Checking and Reporting 23
8. Standard Libraries 25
8.1. Standard I/O 25
8.2. Compatibility 25
8.3. Libraries for Embedded Systems 25
8.4. Binary I/O 26
8.5. Floating Point Library 27
9. Stylistic Considerations 29
9.1. Member Names 29
9.2. Use of Int 30
9.3. Extern Declarations 30
10. Memory Models 31
11. What Went Wrong 33
12. Z80 Assembler Reference Manual 35
12.1. Introduction 35
12.2. Usage 35
12.3. The Assembly Language 36
12.3.1. Symbols 36
12.3.1.1. Temporary Labels 37
12.3.2. Constants 37
12.3.2.1. Character Constants 38
ii HI-TECH C USER'S MANUAL
12.3.2.2. Floating Constants 38
12.3.2.3. Opcode Constants 38
12.3.3. Expressions 38
12.3.3.1. Operators 38
12.3.3.2. Relocatability 39
12.3.4. Pseudo-ops 40
12.3.4.1. DEFB, DB 40
12.3.4.2. DEFF 41
12.3.4.3. DEFW 41
12.3.4.4. DEFS 41
12.3.4.5. EQU 41
12.3.4.6. DEFL 41
12.3.4.7. DEFM 42
12.3.4.8. END 42
12.3.4.9. COND, IF, ELSE, ENDC 42
12.3.4.10. ELSE 42
12.3.4.11. ENDC 42
12.3.4.12. ENDM 43
12.3.4.13. PSECT 43
12.3.4.14. GLOBAL 43
12.3.4.15. ORG 44
12.3.4.16. MACRO 44
12.3.4.17. LOCAL 45
12.3.4.18. REPT 46
12.3.5. IRP and IRPC 47
12.3.6. Extended Condition Codes 48
12.4. Assembler Directives 48
12.5. Diagnostics 49
12.6. Z80/Z180/64180 Instruction Set 50
13. Linker Reference Manual 69
13.1. Relocation and Psects 69
13.1.1. Program Sections 69
13.1.2. Local Psects and the Large Model 70
13.2. Global Symbols 70
13.3. Operation 71
13.4. Examples 74
13.5. Invoking the Linker 74
14. Librarian 75
14.1. The Library Format 75
14.2. Using 75
14.3. Examples 76
14.4. Supplying Arguments 77
14.5. Listing Format 77
14.6. Ordering of Libraries 77
14.7. Error Messages 78
15. Objtohex 79
16. Cref 83
APPENDIX 1 Error Messages 85
APPENDIX 2 Standard Library Functions 99
INDEX 165
HI-TECH C COMPILER
User's Manual
March 1989
1. Introduction
The HI-TECH C Compiler is a set of software which
translates programs written in the C language to executable
machine code programs. Versions are available which compile
programs for operation under the host operating system, or
which produce programs for execution in embedded systems
without an operating system.
1.1. Features
Some of HI-TECH C's features are:
A single command will compile, assemble and link entire
programs.
The compiler performs strong type checking and issues
warnings about various constructs which may represent
programming errors.
The generated code is extremely small and fast in exe-
cution.
A full run-time library is provided implementing all
standard C input/output and other functions.
The source code for all run-time routines is provided.
A powerful general purpose macro assembler is included.
Programs may be generated to execute under the host
operating system, or customized for installation in
ROM.
PC-DOS/MS-DOS
CP/M-86
Concurrent DOS
Atari ST
Xenix
Unix
CP/M-80
Table 1. Supported Hosts


Page 2 HI-TECH C USER'S MANUAL

1.2. System Requirements
The HI-TECH C Compilers operate under the operating
sytems listed in table 1. Ensure that the version of the
compiler you have matches the system you have. Note that in
general you must have a hard disk or two floppy disks on
your system (it is possible to use one floppy disk of 800K
or more). A hard disk is strongly recommended. Note that
the CP/M-80 native compiler does not have all the features
described in this manual, as it has not been upgraded past
V3.09 due to memory limitations. The Z80 cross compiler
does support all of the features described here and can be
used to generate programs to execute under CP/M-80.
1.3. Using this Manual
The documentation supplied with the HI-TECH C compiler
comprises two separate manuals within the one binder. The
manual you are reading now covers all versions of the com-
piler (reflecting the portable nature of the compiler). A
separate manual covers machine dependent aspects of your
compiler, e.g. installation.
This manual assumes you are familiar with the C
language already. If you are not, you should have at least
one reference book covering C, of which a large number are
available from most computer bookstores, e.g. "A Book on C"
by Kelley and Pohl. Other suitable texts are "Programming in
ANSI C" by S. Kochan and "The C Programming Language", by
Kernighan and Ritchie. You should read the "Getting Started"
chapter in this manual, and the "Installation" chapter in
the machine-specific manual. This will provide you with
sufficient information to work through the introductory
examples in the C reference you are using.
Once you have a basic grasp of the C language, the
remainder of this manual will provide you with information
to enable you to explore the more advanced aspects of C.
Most of the manual covers all implementations of the
HI-TECH C compiler. A separate manual is provided for the
macro assembler for your particular machine, and other
machine-dependent information.


HI-TECH C USER'S MANUAL Page 3

2. Getting Started
If using the compiler on a hard disk system you will
need to install the compiler before using it. See the
"Installation" chapter for more details. If using a floppy
disk based system, in general you should have a copy of the
distribution disk #1 in drive A: and maintain your files on
a disk in the B: drive. Again see the "Installation" chapter
for more information.
main()
{
printf("Hello, world\n");
}
Fig. 1. Sample C Program
Before compiling your program it must be contained in a
file with an extension (or file type, i.e. that part of the
name after the '.') of .C. For example you may type the
program shown in fig. 1 into a file called HELLO.C. You will
need a text editor to do this. Generally any text editor
that can create a straight ASCII file (i.e. not a "word pro-
cessor" type file) will be suitable. If using editors such
as Wordstar, you should use the "non-document mode". Once
you have the program in such a file all that is required to
compile it is to issue the C command, e.g. to compile
HELLO.C simply type the command
C -V HELLO.C
Cross compilers (i.e. compilers that operate on one system
but produce code for a separate target system) will have a
compiler driver named slightly differently, e.g. the 68HC11
cross compiler driver is called C68.
If you are using a floppy disk based system (or a CP/M
system) it may be necessary to specify where to find the C
command, e.g. if the C command is on a disk in drive A: and
you are working on B:, type the command
A:C -V HELLO.C
The compiler will issue a sign on message, then proceed
to execute the various passes of the compiler in sequence to
compile the program. If you are using a floppy disk based
system where the compiler will not fit on a single disk you
will be prompted to change disks whenever the compiler can-
not find a pass. In this case you should insert a copy of
the next distribution disk in drive A: and press RETURN.
As each pass of the compiler is about to be executed, a
command line to that pass will be displayed on the screen.


Page 4 HI-TECH C USER'S MANUAL

This is because the -V option has been used. This stands for
Verbose, and had it not been given the compilation would
have been silent except for the sign on message. Error mes-
sages can be redirected to a file by using the standard out-
put redirection notation, e.g. > somefile.
After completion of compilation, the compiler will exit
to command level. You will notice that several temporary
files created during compilation will have been deleted, and
all that will be left on the disk (apart from the original
source file HELLO.C) will be an executable file. The name of
this executable file will be HELLO.EXE for MS-DOS, HELLO.PRG
for the Atari ST, HELLO.COM for CP/M-80 and HELLO.CMD for
CP/M-86. For cross compilers it will be called HELLO.HEX or
HELLO.BIN depending on the default output format for the
particular compiler. To execute this program, simply type
HELLO
and you should be rewarded with the message "Hello, world!"
on your screen. If you are using a cross compiler you will
need to put the program into EPROM or download to the target
system to execute it. Cross compilers do not produce pro-
grams executable on the host system.
There are other options that may be used with the C
command, but you will not need to use them unless you wish
to do so. If you are new to the C language it will be advis-
able to enter and compile a few simple programs (e.g. drawn
from one of the C reference texts mentioned above) before
exploring other capabilities of the HI-TECH C compiler.
There is one exception to the above; if you compile a
program which uses floating point arithmetic (i.e. real
numbers) you MUST specify to the compiler that the floating
point library should be searched. This is done with a -LF
option at the END of the command line, e.g.
C -V FLOAT.C -LF


HI-TECH C USER'S MANUAL Page 5

3. Compiler Structure
The compiler is made up of several passes; each pass is
implemented as a separate program. Note that it is not
necessary for the user to invoke each pass individually, as
the C command runs each pass automatically. Note that the
machine dependent passes are named differently for each pro-
cessor, for example those with 86 in their name are for the
8086 and those with 68K in their name are for the 68000.
The passes are:
CPP The pre-processor - handles macros and conditional com-
pilation
P1 The syntax and semantic analysis pass. This writes
intermediate code for the code generator to read.
CGEN, CG86 etc.
The code generator - produces assembler code.
OPTIM, OPT86 etc.
The code improver - may optionally be omitted, reducing
compilation time at a cost of larger, slower code pro-
duced.
ZAS, AS86 etc.
The assembler - in fact a general purpose macro assem-
bler.
LINK
The link editor - links object files with libraries.
OBJTOHEX
This utility converts the output of LINK into the
appropriate executable file format (e.g. .EXE or .PRG
or .HEX).
The passes are invoked in the order given. Each pass
reads a file and writes a file for its successor to read.
Each intermediate file has a particular format; CPP produces
C code without the macro definitions and with uses of macros
expanded; P1 writes a file containing a program in an inter-
mediate code; CGEN translates this to assembly code; AS pro-
duces object code, a binary format containing code bytes
along with relocation and symbol information. LINK accepts
object files and libraries of object files and writes
another object file; this may be in absolute form or it may
preserve relocation information and be input to another LINK
command.
There are also other utility programs:
LIBR
Creates and maintains libraries of object modules


Page 6 HI-TECH C USER'S MANUAL

CREF
Produces cross-reference listings of C or assembler
programs.


HI-TECH C USER'S MANUAL Page 7

4. Operating Details
HI-TECH C was designed for ease of use; a single com-
mand will compile, assemble and link a C program. The syntax
of the C command is as follows:
C [ options ] files [ libraries ]
The options are zero or more options, each consisting
of a dash ('-'), a single key letter, and possibly an argu-
ment following the key letter with no intervening space. The
files are one or more C source files, assembler source
files, or object files. Libraries may be zero or more
library names, or the abbreviated form -lname which will be
expanded to the library name libname.lib.
The C command will, as determined by the specified
options, compile any C source files given, assemble them
into object code unless requested otherwise, assemble any
assembler source files specified, then link the results of
the assemblies with any object or library files specified.
If the C command is invoked without arguments, then it
will prompt for a command line to be entered. This command
line may be extended by typing a backslash ('\') on the end
of the line. Another line will then be requested. If the
standard input of the command is from a file (e.g. by typing
C < afile) then the command lines will be read from that
file. Within the file more than one line may be given if
each line but the last ends with a backslash. Note that this
mechanism does not work in MS-DOS batch file, i.e. the com-
mand file for the C command must be a separate file. MS-DOS
has no mechanism for providing long command lines or stan-
dard input from inside a batch file.
The options recognized by the C command are as follows:
-S Leave the results of compilation of any C files as
assembler output. C source code will be interspersed as
comments in the assembler code.
-C Leave the results of all compiles and assemblies as
object files; do not invoke the linker. This allows the
linker to be invoked separately, or via the C command
at a later stage.
-CR Produce a cross reference listing. -CR on its own will
leave the raw cross-reference information in a tem-
porary file, allowing the user to run CREF explicitly,
while supplying a file name, e.g. -CRFRED.CRF will
cause CREF to be invoked to process the raw information
into the specified file, in this case FRED.CRF.
-CPM
For the Z80 cross compiler only, produce CP/M-80 COM
files. Unless the -CPM option is given, the Z80 cross


Page 8 HI-TECH C USER'S MANUAL

compiler uses the ROM runtime startoff module and pro-
duces hex or binary images. If the -CPM option is
given, CP/M-80 runtime startoff code is linked used and
a CP/M-80 COM file is produced.
-O Invoke the optimizer on all compiled code; also
requests the assembler to perform jump optimization.
-OOUTFILE
Specify a name for the executable file to be created.
By default the name for the executable file is derived
from the name of the first source or object file speci-
fied to the compiler. This option allows the default to
be overridden. If no dot ('.') appears in the given
file name, an extension appropriate for the particular
operating system will be added, e.g. -OFRED will gen-
erate a file FRED.EXE on MS-DOS or FRED.CMD on CP/M-86.
For cross compilers this also provides a means for
specifying the output format, e.g. specifying an output
file PROG.BIN will make the compiler generate a binary
file, while specifying PROG.HEX will make it generate a
hexadecimal file.
-V Verbose: each step of the compilation will be echoed as
it is executed.
-I Specify an additional filename prefix to use in search-
ing for #include files. For CP/M the default prefix is
0:A: (user number 0, disk drive A). For MS-DOS the
default prefix is A:\HITECH\. Under Unix and Xenix the
default prefix is /usr/hitech/include/. Note that on
MS-DOS a trailing backslash must be appended to any
directory name given as an argument to -I; e.g.
-I\FRED\ not -I\FRED. Under Unix a trailing slash
should be added.
-D Define a symbol to the preprocessor: e.g. -DCPM will
define the symbol CPM as though via #define CPM 1.
-U Undefine a pre-defined symbol. The complement of -D.
-F Request the linker to produce a symbol file, for use
with the debugger.
-R For the Z80 CP/M compiler only this option will link in
code to perform command line I/O redirection and wild
card expansion in file names. See the description of
_getargs() in appendix 5 for details of the syntax of
the redirections.
-X Strip local symbols from any files compiled, assembled
or linked. Only global symbols will remain.
-M Request the linker to produce a link map.
-A This option, for the Z80 only, will cause the compiler
to produce an executable program that will, on execu-
tion, self-relocate itself to the top of the TPA


HI-TECH C USER'S MANUAL Page 9

(Transient Program Area). This allows the writing of
programs which may execute other programs under them-
selves. Note that a program compiled in such a manner
will not automatically reset the bdos address at loca-
tion 6 in order to protect itself. This must be done by
the program itself.
For cross compilers this provides a way of specifying
to the linker the addresses that the compiled program
is to be linked at. The format of the option is
-AROMADR,RAMADR,RAMSIZE. ROMADR is the address of the
ROM in the system, and is where the executable code and
initialized data will be placed. RAMADR is the start
address of RAM, and is where the bss psect will be
placed, i.e. uninitialized data. RAMSIZE is the size
of RAM available to the program, and is used to set the
top of the stack.
For the 6801/6301/68HC11 compiler, the -A option takes
a fourth value which is the address of a four byte
direct page area called ctemp which the compiled code
uses as a scratch pad. If the ctemp address is omitted
from the -A option, it defaults to address 0. Normally
this will be acceptable, however some 6801 variants
(like the 6303) have memory mapped I/O ports at address
0 and start their direct page RAM at address $80.
For the large memory model of the 8051 compiler, the -A
option takes the form -AROMADR,INTRAM,EXTRAM,EXTSIZE.
ROMADR is the address of ROM in the system. INTRAM is
the start address of internal RAM, and is where the
rbss psect will be placed. The 8051 internal stack
will start after the end of the rbss psect. EXTRAM is
the start address of external RAM, and is where the bss
psect will be placed. EXTSIZE is the size of external
RAM available to the program, and is used to set the
top of the external stack.
-B For compilers which support more than one "memory
model", this option is used to select which memory
model code is to be generated for. The format of this
option is -Bx where x is one or more letters specifying
which memory model to use. For the 8086, this option
is used to select which one of five memory models
(Tiny, Small, Medium, Compact or Large) is to be used.
For the 8051 compiler this this option is used to
select which one of the three memory models (Small,
Medium or Large) is to be used. For the 8051 compiler
only, this option can also be used to select static
allocation of auto variables by appending an A to the
end of the -B option. For example, -Bsa would select
small model with static allocation of all variables,
while -Bm would select medium model with auto variables
dynamically allocated on the stack.


Page 10 HI-TECH C USER'S MANUAL

-E By default the 8086 compiler will initialize the exe-
cutable file header to request a 64K data segment at
run time. This may be overridden by the -E option. It
takes an argument (usually in hexadecimal representa-
tion) which is the number of BYTES (not paragraphs) to
be allocated to the program at run time. For example
-E0ffff0h will request a megabyte. Since this much will
not be available, the operating system will allocate as
much as it can.
-W This options sets the warning level, i.e. it determines
how picky the compiler is about legal but dubious type
conversions etc. -W0 will allow all warning messages
(default), -W1 will suppress the message "Func()
declared implicit int". -W3 is recommended for compil-
ing code originally written with other, less strict,
compilers. -W9 will suppress all warning messages.
-H This option generates a symbol file for use with
debuggers. The format of the symbol file is described
elsewhere. The default name of the symbol file is
l.sym. An alternate name may be specfied with the
option, e.g. -Hsymfile.abc.
-G Like -H, -G also generates a symbol file, but one that
contains line and file number information for a source
level debugger. Like -H a file name may be specified.
When used in conjunction with -O, only partial optimi-
zation will be performed to avoid confusing the
debugger.
-P Execution profiling is available on native compilers
running under DOS, CP/M-86 and on the Atari ST. This
option generates code to turn on execution profiling
when the program is run. A -H option should also be
specified to provide a symbol table for the profiler
EPROF.
-Z For version 5.xx compilers only, the -Z option is used
to select global optimization of the code generated.
For the 8086 and 6801/6301/68HC11 compilers the only
valid -Z option is -Zg. For the 8051 compiler, the
valid -Z options are -Zg which invokes global optimiza-
tion, -Zs which optimizes for space, and -Zf which
optimizes for speed. The s and f options may be used
with the g option, thus the options -Zgf and -Zgs are
valid. Speed and space optimization are mutually
exclusive, i.e. the s and f options cannot be used
together.
-1 For the 8086 compiler only, request the generation of
code which takes advantage of the extra instructions of
the 80186 processor. A program compiled with -1 will
not execute on an 8086 or 8088 processor. For the 68000
compiler, generate instructions for the 68010 proces-
sor.


HI-TECH C USER'S MANUAL Page 11

-2 Like -1 but for the 80286 and 68020.
-11 For the 6801/HC11 compiler, this option will request
generation of instructions specific to the 68HC11 pro-
cessor.
-6301
For the 6801/HC11 compiler, this option will request
generation of instructions specific to the 6301/6303
processors.
Some examples of the use of the C command are:
c prog.c
c -mlink.map prog.c x.obj -lx
c -S prog.c
c -O -C -CRprog.crf prog.c prog2.c
c -v -Oxfile.exe afile.obj anfile.c -lf
Upper and lower case has been used in the above exam-
ples for emphasis: the compiler does not distinguish between
cases, although arguments specifying names, e.g. -D, are
inherently case sensitive.
Taking the above examples in order; the first compiles
and links the C source file prog.c with the standard C
library. The second example will compile the file prog.c and
link it with the object file x.obj and the library libx.lib;
a link map will be written to the file link.map.
The third example compiles the file prog.c, leaving the
assembler output in a file prog.as. It does not assemble
this file or invoke the linker. The next example compiles
both prog.c and prog2.c, invoking the optimizer on both
files, but does not perform any linking. A cross reference
listing will be left in the file prog.crf.
The last example pertains to the 8086 version of the
compiler, It runs the compiler with the verbose option, and
will cause anfile.c to be compiled without optimization to
object code, yielding anfile.obj, then afile.obj and
anfile.obj will be linked together with the floating point
library (from the -LF option) and the standard library to
yield the executable program xfile.exe (assuming this is
performed on an MS-DOS system). One would expect this pro-
gram to use floating point, if it did not then the -LF
option would have been required.
If more than one C or assembler source file is given to
the C command, the name of each file will be printed on the
console as it is processed. If any fatal errors occur dur-
ing the compilation or assembly of source files, further
source files will be processed, but the linker will not be


Page 12 HI-TECH C USER'S MANUAL

invoked.
Other commands which may be issued by the user, rather
than automatically by the C command, are:
ZAS The Z80 assembler.
AS86
The 8086 assembler.
LINK
The linker
LIBR
The library maintainer
OBJTOHEX
Object to hex converter
CREF
Cross reference generator.
In general, these commands accept the same type of com-
mand line as the C command, i.e. zero or more options (indi-
cated by a leading '-') followed by one or more file argu-
ments. If the linker or the librarian is invoked with no
arguments, it wll prompt for a command line. This allows
command lines of more than 128 bytes to be entered. Input
may also be taken from a file by using the redirection capa-
blities (see _getargs() in the library function listing).
See the discussion above of the C command. These commands
are described in further detail in their respective manuals.


HI-TECH C USER'S MANUAL Page 13

5. Specific Features
The HI-TECH C compiler has a number of features, which
while largely compatible with other C compilers, contribute
to more reliable programming methods.
5.1. ANSI C Standard Compatibility
At the time of writing the Draft ANSI Standard for the
C Language was at an advanced stage, though not yet an offi-
cial standard. Accordingly it is not possible to claim com-
pliance with that standard, however HI-TECH C includes the
majority of the new and altered features in the draft ANSI
standard. Thus it is in the sense that most people under-
stand it "ANSI compatible".
5.2. Type Checking
Previous C compilers have adopted a lax approach to
type checking. This is typified by the Unix C compiler,
which allows almost arbritary mixing of types in expres-
sions. The HI-TECH C compiler performs much more strict type
checking, although in most cases only warning messages are
issued, allowing compilation to proceed if the user knows
that the errors are harmless. This would occur, for example,
when an integer value was assigned to a pointer variable.
The generated code would almost certainly be what the user
intended, however if in fact it represented an error in the
source code, the user is prompted to check and correct it
where necessary.
5.3. Member Names
In early C compilers member names in different struc-
tures were required to be distinct except under certain cir-
cumstances. HI-TECH C, like most recent implementations of
C, allows member names in different structures and unions to
overlap. A member name is recognized only in the context of
an expression whose type is that of the structure in which
the member is defined. In practice this means that a member
name will be recognized only to the right of a '.' or '->'
operator, where the expression to the left of the operator
is of type structure or pointer to structure the same as
that in which the member name was declared. This not only
allows structure names to be re-used without conflict in
more than one structure, it permits strict checking of the
usage of members; a common error with other C compilers is
the use of a member name with a structure pointer of the
wrong type, or worse with a variable which is a pointer to a
simple type.
There is however an escape from this, where the user
desires to use as a structure pointer something which is not
declared as such. This is via the use of a typecast. For
example, suppose it is desired to access a memory-mapped i/o
device, consisting of several registers. The declarations


Page 14 HI-TECH C USER'S MANUAL

and use may look something like the code fragment in fig. 2.
struct io_dev
{
short io_status; /* status */
char io_rxdata; /* rx data */
char io_txdata; /* tx data */
};
#define RXRDY 01 /* rx ready */
#define TXRDY 02 /* tx ready */
/* define the (absolute) device address */
#define DEVICE ((struct io_dev *)0xFF00)
send_byte(c)
char c;
{
/* wait till transmitter ready */
while(!(DEVICE->io_status & TXRDY))
continue;
/* send the data byte */
DEVICE->io_txdata = c;
}
Fig. 2. Use of Typecast on an Absolute Address
In this example, the device in question has a 16 bit
status port, and two 8 bit data ports. The address of the
device (i.e. the address of its status port) is given as
(hex)0FF00. This address is typecast to the required struc-
ture pointer type to enable use of the structure member
names. The code generated by this will use absolute memory
references to access the device, as required.
Some examples of right and wrong usage of member names
are shown in fig. 3.
5.4. Unsigned Types
HI-TECH C implements unsigned versions of all integral
types; i.e. unsigned char, short, int and long. If an
unsigned quantity is shifted right, the shift will be per-
formed as a logical shift, i.e. bringing zeros into the
rightmost bits. Similarly right shifts of a signed quantity
will sign extend the rightmost bits.
5.5. Arithmetic Operations
On machines where arithmetic operations may be per-
formed more efficiently in lengths shorter than int,
operands shorter than int will not be extended to int length
unless necessary.
For example, if two characters are added and the result
stored into another character, it is only necessary to


HI-TECH C USER'S MANUAL Page 15

struct fred
{
char a;
int b;
} s1, * s2;
struct bill
{
float c;
long b;
} x1, * x2;
main()
{
/* wrong - c is not a member of fred */
s1.c = 2;
/* correct */
s1.a = 2;
/* wrong - s2 is a pointer */
s2.a = 2;
/* correct */
x2->b = 24L;
/* right, but note type conversion
from long to int */
s2->b = x2->b;
}
Fig. 3. Examples of Member Usage
perform arithmetic in 8 bits, since any overflow into the
top 8 bits will be lost. However, if the sum of two charac-
ters is stored into an int, the addition should be done in
16 bits to ensure the correct result.
In accordance with the draft ANSI standard, operations
on float rather than double quantities will be performed in
the shorter precision rather than being converted to double
precision then back again.
5.6. Structure Operations
HI-TECH C implements structure assignments, structure
arguments and structure-valued functions in their full gen-
erality. The example in fig. 4 is a function returning a
structure. Some legal (and illegal) uses of the function are
also shown.


Page 16 HI-TECH C USER'S MANUAL

struct bill
{
char a;
int b;
}
afunc()
{
struct bill x;
return x;
}
main()
{
struct bill a;
a = afunc(); /* ok */
pf("%d", afunc().a); /* ok */
/* illegal, afunc() cannot be assigned
to, therefore neither can
afunc().a */
afunc().a = 1;
/* illegal, same reason */
afunc().a++;
}
Fig. 4. Example of a Function Returning a Structure
5.7. Enumerated Types
HI-TECH C supports enumerated types; these provide a
structured way of defining named constants.
The uses of enumerated types are more restricted than
that allowed by the Unix C compiler, yet more flexible than
permitted by LINT. In particular, an expression of
enumerated type may be used to dimension arrays, as an array
index or as the operand of a switch statement. Arithmetic
may be performed on enumerated types, and enumerated type
expressions may be compared, both for equality and with the
relation operators. An example of the use of an enumerated
type is given in fig. 5.
5.8. Initialization Syntax
Kernighan and Ritchie in "The C Programming Language"
state that pairs of braces may be omitted from an initial-
izer in certain contexts; the draft ANSI standard provides
that a conforming C program must either include all braces
in an initializer, or leave them all out. HI-TECH C allows
any pairs of braces to be omitted providing that the front
end of the compiler can determine the size of any arrays
being initialized, and providing that there is no ambiguity
as to which braces have been omitted. To avoid ambiguity if
any pairs of braces are present then any braces which would


HI-TECH C USER'S MANUAL Page 17

/* a represents 0, b -> 1 */
enum fred { a, b, c = 4 };
main()
{
enum fred x, y, z;
x = z;
if(x < z)
func();
x = (enum fred)3;
switch(z) {
case a:
case b:
default:
}
}
Fig. 5. Use of an Enumerated Type
enclose those braces must also be present. The compiler will
complain ("initialization syntax") if any ambiguity is
present.
5.9. Function Prototypes
A new feature of C included in the proposed ANSI for C,
known as "function prototypes", provides C with an argument
checking facility, i.e. it allows the compiler to check at
compile time that actual arguments supplied to a function
invocation are consistent with the formal parameters
expected by the function. The feature allows the programmer
to include in a function declaration (either an external
declaration or an actual definition) the types of the param-
eters to that function. For example, the code fragment
shown in fig. 6 shows two function prototypes.
void fred(int, long, char *);
char *
bill(int a, short b, ...)
{
return a;
}
Fig. 6. Function Prototypes
The first prototype is an external declaration of the
function fred(), which accepts one integer argument, one
long argument, and one argument which is a pointer to char.
Any usage of fred() while the prototype declaration is in
scope will cause the actual parameters to be checked for
number and type against the prototype, e.g. if only two
arguments were supplied or an integral value was supplied
for the third argument the compiler would report an error.
Page 18 HI-TECH C USER'S MANUAL
In the second example, the function bill() expects two
or more arguments. The first and second will be converted to
int and short respectively, while the remainder (if present)
may be of any type. The ellipsis symbol (...) indicates to
the compiler that zero or more arguments of any type may
follow the other arguments. The ellipsis symbol must be last
in the argument list, and may not appear as the only argu-
ment in a prototype.
All prototypes for a function must agree exactly, how-
ever it is legal for a definition of a function in the old
style, i.e. with just the parameter names inside the
parentheses, to follow a prototype declaration provided the
number and type of the arguments agree. In this case it is
essential that the function definition is in scope of the
prototype declaration.
Access to unspecified arguments (i.e. arguments sup-
plied where an ellipsis appeared in a prototype) must be via
the macros defined in the header file <stdarg.h>. This
defines the macros va_start, va_arg and va_end. See va_start
in the library function listing for more information.
NOTE that is is a grave error to use a function which
has an associated prototype unless that prototype is in
scope, i.e. the prototype MUST be declared (possibly in a
header file) before the function is invoked. Failure to
comply with this rule may result in strange behaviour of the
program. HI-TECH C will issue a warning message ("func()
declared implicit int") whenever a function is called
without an explicit declaration. It is good practice to
declare all functions and global variables in one or more
header files which are included wherever the functions are
defined or referenced.
5.10. Void and Pointer to Void
The void type may be used to indicate to the compiler
that a function does not return a value. Any usage of the
return value from a void function will be flagged as an
error.
The type void *, i.e. pointer to void, may be used as a
"universal" pointer type. This is intended to assist in the
writing of general purpose storage allocators and the like,
where a pointer is returned which may be assigned to another
variable of some other pointer type. The compiler permits
without typecasting and without reporting an error the
conversion of void * to any other pointer type and vice
versa. The programmer is advised to use this facility care-
fully and ensure that any void * value is usable as a
pointer to any other type, e.g. the alignment of any such
pointer should be suitable for storage of any object.
HI-TECH C USER'S MANUAL Page 19
5.11. Type qualifiers
The ANSI C standard introduced the concept of type
qualifiers to C; these are keywords that qualify the type to
which they are applied. The type qualifiers defined by ANSI
C are const and volatile. HI-TECH C also implements several
other type qualifiers. The extra qualifiers include:
far
near
interrupt
fast interrupt
port
Not all versions of the compilers implement all of the extra
qualifiers. See the machine dependent section for further
information.
When constructing declarations using type qualifiers,
it is very easy to be confused as to the exact semantics of
the declaration. A couple of rules-of-thumb will make this
easier. Firstly, where a type qualifier appears at the left
of a declaration it may appear with any storage class
specifier and the basic type in any order, e.g.
static void interrupt func();
is semantically the same as
interrupt static void func();
Where a qualifier appears in this context, it applies
to the basic type of the declaration. Where a qualifier
appears to the right of one or more '*' (star) pointer
modifiers, then you should read the declaration from right
to left, e.g.
char * far fred;
should be read as "fred is a far pointer to char". This
means that fred is qualified by far, not the char to which
it points. On the other hand,
char far * bill;
should be read as "bill is a pointer to a far char", i.e.
the char to which bill points is located in the far address
space. In the context of the 8086 compiler this will mean
that bill is a 32 bit pointer while fred is a 16 bit
pointer. You will hear bill referred to as a "far pointer",
however the terminology "pointer to far" is preferred.
Page 20 HI-TECH C USER'S MANUAL
5.12.
There are two methods provided for in-line assembler
code in C programs. The first allows several lines of
assembler anywhere in a program. This is via the #asm and
#endasm preprocessor directives. Any lines between these
two directives will be copied straight through to the assem-
bler file produced by the compiler. Alternatively you can
use the asm("string"); construct anywhere a C statement is
expected. The string will be copied through to the assembler
file. Care should be taken with using in-line assembler
since it may interact with compiler generated code.
5.13. Pragma Directives
The draft ANSI C standard provides for a #pragma
preprocessor directive that allows compiler implementations
to control various aspects of the compilation process.
Currently HI-TECH C only supports one pragma, the pack
directive. This allows control over the manner in which
members are allocated inside a structure. By default, some
of the compilers (especially the 8086 and 68000 compilers)
will align structure members onto even boundaries to optim-
ize machine accesses. It is sometimes desired to override
this to achieve a particular layout inside a structure. The
pack pragma allows specification of a maximum packing fac-
tor. For example, #pragma pack1(1) will instruct the com-
piler that no additional padding be inserted between struc-
ture members, i.e. that all members should be aligned on
boundaries divisible by 1. Similarly #pragma pack(2) will
allow alignment on boundaries divisible by 2. In no case
will use of the pack pragma force a greater alignment than
would have been used for that data type anyway.
More that one pack pragma may be used in a program. Any
use will remain in force until changed by another pack or
until the end of the file. Do not use a pack pragma before
include files such as <stdio.h> as this will cause incorrect
declarations of run-time library data structures.
HI-TECH C USER'S MANUAL Page 21
6. Machine Dependencies
HI-TECH C eliminates many of the machine dependent
aspects of C, since it uniformly implements such features as
unsigned char. There are however certain areas where machine
dependencies are inherent in the C language; programmers
should be aware of these and take them into account when
writing portable code.
The most obvious of these machine dependencies is the
varying size of C types; on some machines an int will be 16
bits, on others it may be 32 bits. HI-TECH C conforms to the
following rules, which represent common practice in most C
compilers.
char is at least 8 bits
short is at least 16 bits
long is at least 32 bits
int is the same as either short or long
float is at least 32 bits
double is at least as wide as float
Because of the variable width of an int, it is recom-
mended that short or long be used wherever possible in
preference to int. The exception to this is where a quantity
is required to correspond to the natural word size of the
machine.
Another area of machine differences is that of byte
ordering; the ordering of bytes in a short or long can vary
significantly between machines. There is no easy approach to
this problem other than to avoid code which depends on a
particular ordering. In particular you should avoid writing
out whole structures to a file (via fwrite()) unless the
file is only to be read by the same program then deleted.
Different compilers use different amounts of padding between
structure members, though this can be modified via the
#pragma pack(n) construct.
6.1. Predefined Macros
One technique through which machine unavoidable machine
dependencies may be managed is the predefined macros pro-
vided by each compiler to identify the target processor and
operating system (if any). These are defined by the compiler
driver and may be tested with conditional compilation
preprocessor directives.
The macros defined by various compilers are listed in
table 2. These can be used as shown in the example in fig .
Page 22 HI-TECH C USER'S MANUAL
___________________________________________
|_Macro______________Defined_for___________|
| i8051 8051 processor family |
| i8086 8086 processor family |
| i8096 8096 processor family |
| z80 Z80 processor and derivatives |
| m68000 68000 processor family |
| m6800 6801, 68HC11 and 6301 processors|
| m6809 6809 processor |
| DOS MS-DOS and PC-DOS |
| CPM CP/M-80 and CP/M-86 |
| TOS Atari ST |
|__________________________________________|
Table 2. Predefined Macros
#if DOS
char * filename = "c:file";
#endif /* DOS */
#if CPM
char * filename = "0:B:afile";
#endif /* CPM */
Use this page for notes
HI-TECH C USER'S MANUAL Page 23
7. Error Checking and Reporting
Errors may be reported by any pass of the compiler,
however in practice the assembler and optimizer will not
encounter any errors in the generated code. The types of
errors produced by each pass are summarized below. In gen-
eral any error will be indentified by the name of the source
file in which it was encountered, and the line number at
which it was detected. P1 will also nominate the name of
the function inside which the error was detected.
Errors may be redirected to a file with the usual syn-
tax, i.e. a 'greater than' symbol ('>') followed by the name
of a file into which the errors should be written. The file
name may of course be a device name, e.g. LST: for CP/M or
PRN for MS-DOS.
CPP will report errors relating to macro definitions
and expansions, as well as conditional compilation.
P1 is the pass which reports most errors; it performs
syntax and semantic checking of the input, and will report
both fatal and warning errors when encountered. Syntax
errors will normally be expressed as "symbol expected" or
"symbol unexpected". Semantic errors may relate to unde-
clared, redeclared or misdeclared variables. P1 will also
report variable definitons which are unused or unreferenced.
These errors are warnings, as are most type checking errors.
When P1 encounters errors it will list the source line
containing the error on the screen, and underneath display
the error message and an up arrow pointing to the point at
which the compiler detected the error. In some cases the
actual cause of the error may be earlier in the line or even
on previous line.
CGEN may occasionally report errors, usually warnings,
and mostly related to unusual combinations of types with
constants, for example testing if an unsigned quantity is
less than zero. One fatal error produced by CGEN is "can't
generate code for this expression" and means that the
expression currently being compiled is in some way too com-
plicated to produce code for. This can usually be overcome
by rewriting the source code. Such errors are rare and will
occur only for unusual constructs.
The linker will report undefined or multiply defined
symbols. Note that variable declarations inside a header
file which is included in more than one source file must be
declared as extern, to avoid multiply defined symbol errors.
These symbols must then be defined in one and one only
source file.
A comprehensive list of error messages is included in
an appendix.
Page 24 HI-TECH C USER'S MANUAL
Use this page for notes
HI-TECH C USER'S MANUAL Page 25
8. Standard Libraries
8.1. Standard I/O
C is a language which does not specify the I/O facil-
ites in the language itself; rather all I/O is performed via
library routines. In practice this results in I/O handling
which is no less convenient than any other language, with
the added possibility of customising the I/O for a specific
application. For example it is possible to provide a routine
to replace the standard getchar() (which gets one character
from the standard input) with a special getchar(). This is
particulary useful when writing code which is to run on a
special hardware configuration, while maintaining a high
level of compatibility with "standard" C I/O.
There is in fact a Standard I/O library (STDIO) which
defines a portable set of I/O routines. These are the rou-
tines which are normally used by any C application program.
These routines, along with other non-I/O library routines,
are listed in detail in a subsequent section of the manual.
8.2. Compatibility
The libraries supplied with HI-TECH C are highly compa-
tible with the ANSI libraries, as well as the V7 UNIX
libraries, both at the Standard I/O level and the UNIX sys-
tem call level. The Standard I/O library is complete, and
conforms in all respects with the UNIX Standard I/O library.
The library routines implementing UNIX system call like
functions are as close as possible to those system calls,
however there are some UNIX system calls that cannot be
simulated on other systems, e.g. the link() operation. How-
ever the basic low level I/O routines, i.e. open, close,
read, write and lseek are identical to the UNIX equivalents.
This means that many programs written to run on UNIX, even
if they do not use Standard I/O, will run with little modif-
ication when compiled with HI-TECH C.
8.3. Libraries for Embedded Systems
The cross compilers, designed to produce code for tar-
get systems without operating systems, are supplied with
libraries implementing a subset of the STDIO functions. Not
provided are those functions dealing with files. Included
are printf(), scanf() etc. These operate by calling two low
level functions putch and getch() which typically send and
receive characters via a serial port. Where the compiler is
aimed at a single-chip micro with on-board UART this is
used. The source code for all these functions is supplied
enabling the user to modify it to address a different serial
port.
Page 26 HI-TECH C USER'S MANUAL
8.4. Binary I/O
On some operating systems, notably CP/M, files are
treated differently according to whether they contain ASCII
(i.e. printable) or binary data. MD-DOS also suffers from
this problem, not due to any lack in the operating system
itself, but rather because of the hangover from CP/M which
results in many programs putting a redundant ctrl-Z at the
end of files. Unfortunately there is no way to determine
which type of data a file contains (except perhaps by the
name or type of the file, and this is not reliable). To
overcome this difficulty, there is an extra character which
may be included in the MODE string to a fopen() call. To
open a file for ASCII I/O, the form of the fopen() call is:
fopen("filename.ext", "r") /* for reading */
fopen("filename.ext", "w") /* for writing */
To open a file for binary I/O, the character 'b' may be
appended to the
fopen("filename.ext", "rb")
fopen("filename.ext", "wb")
The additional character instructs the STDIO library
that this file is to be handled in a strict binary fashion.
On CP/M or MS-DOS, a file opened in ASCII mode will have the
following special character handling performed by the STDIO
routines:
newline
('\n') converted to carriage return/newline on output.
return
('\r') ignored on input
Ctrl-Z
interpreted as End-Of-File on input and, for CP/M only,
appended when closing the file.
The special actions performed on ASCII files ensure
that the file is written in a format compatible with other
programs handling text files, while eliminating the require-
ment for any special handling by the user program - the file
appears to the user program as though it were a UNIX-like
text file.
None of these special actions are performed on a file
opened in binary mode. This is required when handling any
kind of binary data, to ensure that spurious bytes are not
inserted, and premature EOF's are not seen.
Since the binary mode character is additional to the
normal mode character, this usage is quite compatible with
UNIX C. When compiled on UNIX, the additional character will
be ignored.
HI-TECH C USER'S MANUAL Page 27
A mention here of the term `stream' is appropriate;
stream is used in relation to the STDIO library routines to
mean the source or sink of bytes (characters) manipulated by
those routines. Thus the FILE pointer supplied as an argu-
ment to the STDIO routines may be regarded as a handle on
the corresponding stream. A stream may be viewed as a
featureless sequence of bytes, originating from or being
sent to a device or file or even some other indeterminate
source. A FILE pointer should not be confused with the 'file
descriptors' used with the low-level I/O functions open(),
close(), read() and write(). These form an independent group
of I/O functions which perform unbuffered reads and writes
to files.
8.5. Floating Point Library
HI-TECH C supports floating point as part of the
language, however the Z80 implementation provides single
precision only; double floats are permitted but are no dif-
ferent to floats. In addition, the standard library,
LIBC.LIB, does not contain any floating point routines.
These have been separated out into another library,
LIBF.LIB. This means that if this library is not searched no
floating point support routines will be linked in, thus
avoiding any size penalty for the floating point support if
it is not used. This is particulary important for printf and
scanf, and thus LIBF.LIB contains versions of printf and
scanf that do support floating point formats.
Thus, if floating point is used, a -LF option should be
used AFTER the source and/or object files to the C command.
E.g.:
C -V -O x.c y.c z.obj -LF
Page 28 HI-TECH C USER'S MANUAL
Use this page for notes
HI-TECH C USER'S MANUAL Page 29
9. Stylistic Considerations
Although it is not the purpose of this manual to set
out a coding standard for C, some comments regarding use of
some of the features of HI-TECH C may be useful.
9.1. Member Names
Although HI-TECH C allows the same structure or union
member name to be used in more than one structure or union,
this may not be allowed by another C compiler. To help
ensure portability of the code, it is recommended that
member names all be distinct, and a useful way of ensuring
this is to prefix each member name with one or two letters
derived from the name of the structure itself. An example is
given in fig. 7.
struct tree_node
{
struct tree_node * t_left;
struct tree_node * t_right;
short t_operator;
};
Fig. 7. Member Naming
Because HI-TECH C insists on use of all intermediate
names when referencing a member nested inside several struc-
tures, some simple macro definitions can serve as a short-
hand. An example is given in fig. 8.
struct tree_node
{
short t_operator;
union
{
struct tree_node * t_un_sub[2];
char * t_un_name;
long t_un_val;
} t_un;
};
#define t_left t_un.t_un_sub[0]
#define t_right t_un.t_un_sub[1]
#define t_name t_un.t_un_name
#define t_val t_un.t_un_val
Fig. 8. Member Name Shorthand
This enables the variant components of the structure to
be referred to by short names, while guaranteeing portabil-
ity and presenting a clean definition of the structure.
Page 30 HI-TECH C USER'S MANUAL
9.2. Use of Int
It is recommended that the type int be avoided wherever
possible, in preference to the types short or long. This is
because of the variable size of int, whereas short is com-
monly 16 bits and long 32 bits in most C implementations.
9.3. Extern Declarations
Some compilers permit a non-initialized global variable
to be declared in more than one place, with the multiple
definitions being resolved by the linker as all defining the
same thing. HI-TECH C specifically disallows this, since it
may lead to subtle bugs. Instead, global variables may be
declared extern in as many places as you wish, and must be
defined in one and one only place. Typically this will mean
declaring global variables in a header file as extern, and
defining each variable in the file most closely associated
with that variable.
This usage will be portable to virually all other C
implementations.
HI-TECH C USER'S MANUAL Page 31
10. Memory Models
With many of the processors supported by the HI-TECH C
compilers there are more than one address space accessible
to a program. Typically one address space is more economical
to access than another, larger address space. Thus it is
desirable to be able to tailor a prorgram's use of memory to
achieve the greatest economy in addressing (thus minimizing
program size and maximizing speed) while allowing access to
as much memory as the program requires.
This concept of different address spaces is not catered
for by either K&R or ANSI C (except to recognize the possi-
bility of separate address spaces for code and data).
Without any extensions to the language itself it is possible
to devise more than one memory model for a given processor,
selected at compile time. This has the effect of selecting
one addressing method for all data and/or code. This permits
the model for a particular program to be chosen depending on
that program's memory requirements.
In many programs, however, only one or two data struc-
tures are large enough to need to be placed in the larger
address space. Selection of a "large" memory model for the
whole of the program makes the whole program larger and
slower just to allow a few large data structures. This can
be overcome by allowing individual selection of the address
space for each data structure. Unfortunately this entails
extensions to the language, never a desirable approach. To
minimize the effect of such extensions they should satisfy
the following criteria:
1. As far as possible the extensions should be consistent
with common practice.
2. The extensions should fit a machine-independent model
to maximize portability across processors and operating
systems.
These goals have been achieved within HI-TECH C by
means of the following model:
Each memory model defines three address spaces
each for code and data. These address spaces are
known as the near, far and default spaces. Any
object qualified by the near keyword will be
placed in the near address space, any object qual-
ified by the far keyword shall be placed in the
far address space, and all other objects shall be
placed in the default address space. The near
address space shall be a (possibly improper) sub-
space of the default address space, while the
default address space shall be a (possibly
improper) subspace of the far address space. There
shall be up to three kinds of pointers correspond-
ing to the three address spaces, each capable of
Page 32 HI-TECH C USER'S MANUAL
addressing an object in its own address space or a
subspace of that address space.
This implies that the address of an object may be con-
verted to a pointer into a larger address space, e.g. a near
object may have its address converted to a pointer to far,
but a far object may not be able to be addressed by a
pointer to near.
In practice the default address space will usually
correspond exactly to either the near or far address spaces.
If all three address spaces correspond to the same memory
then there is only one memory model possible. This occurs
with the 68000 processor. Where the default code and data
spaces may each correspond to either the near or far address
spaces then there will be a total of four memory models.
This is the case with the 8086 processor.
The keywords far and near are supported by all the HI-
TECH C compilers, but the exact correspondence of address
spaces is determined by the individual characteristics of
each processor and the choice of memory model (if there is a
choice). However code written using these keywords will be
portable providing it obeys the constraints of the model
described above.
This model also corresponds well with other implementa-
tions using the near and far keywords, although such imple-
mentations do not appear to have been designed around a for-
mal, portable model.
HI-TECH C USER'S MANUAL Page 33
11. What Went Wrong
There are numerous error messages that the compiler may
produce. Most of these relate to errors in the source code
(syntax errors of various kinds and so forth) but some
represent limitations, particularly of memory. The two
passes most likely to be affected by memory limitations are
the code generator and the optimizer. The code generator
will issue the message "No room" if it runs out of dynamic
memory. This can usually be eliminated by simplifying the
expression at the line nominated in the error message. The
more complex the expression, the more memory is required to
store the tree representing it. Reducing the number of sym-
bols used in the program will also help.
Note that this error is different from the message
"Can't generate code for this expression" which indicates
that the expression is in some way too difficult for the
code generator to handle. This message will be encountered
very infrequently, and can be eliminated by changing the
expression in some way, e.g. computing an intermediate value
into a temporary variable.
The optimizer reads the assembler code for a whole
function into memory at one time. Very large functions will
not fit, giving the error message "Optim: out of memory in
_func" where func is the name of the function responsible.
In this case the function should be broken up into smaller
functions. This will only occur with functions with several
hundred lines of C source code. Good coding practice will
normally limit functions to less than 50 lines each.
If a pass exits with the message "Error closing file",
or "Write error on file", this usually indicates that there
is insufficient room on the current disk.
If you use a wordprocessing editor such as Wordstar,
ensure that you use the "non-document" mode or whatever the
corresponding mode is. The edited file should not contain
any characters with the high bit set, and the line feed at
the end of the line must be present. Lines should be not
more than 255 characters long.
When using floating point, ensure that you use a -LF
flag at the END of the command line, to cause the floating
point library to be searched. This will cause floating ver-
sions of printf and scanf to be linked in, as well as
specific floating point routines.
If the non-floating version of printf is used with a
floating format such as %f then it will simply print the
letter f.
If the linker gives an "Undefined symbol" message for
some symbol which you know nothing about, it is possible
that it is a library routine which was not found during the
Page 34 HI-TECH C USER'S MANUAL
library search due to incorrect library ordering. In this
case you can search the library twice, e.g. for the stan-
dard library add a -LC to the end of the C command line, or
-LF for the floating library. If you have specified the
library by name simply repeat its name.
HI-TECH C USER'S MANUAL Page 35
12. Z80 Assembler Reference Manual
12.1. Introduction
The assembler incorporated in the HI-TECH C compiler
system is a full-featured relocating macro assembler accept-
ing Zilog mnemonics. These mnemonics and the syntax of the
Z80 assembly language are described in the "Z80 Assembly
Language Handbook" published by Zilog and are included at
the end of this manual as a reference. The assembler imple-
ments certain extensions to the operands allowed, and cer-
tain additional pseudo-ops, which are described here. The
assembler also accepts the additional opcodes for the Hita-
chi 64180 and Z180 processors.
12.2. Usage
The assembler is named zas, and is invoked as follows:
ZAS options files ...
The files are one or more assembler source files which
will be assembled, but note that all the files are assembled
as one, not as separate files. To assemble separate files,
the assembler must be invoked on each file separately. The
options are zero or more options from the following list:
-N Ignore arithmetic overflow in expressions. The -N
option suppresses the normal check for arithmetic over-
flow. The assembler follows the "Z80 Assembly Language
Handbook" in its treatment of overflow, and in certain
instances this can lead to an error where in fact the
expression does evaluate to what the user intended.
This option may be used to override the overflow check-
ing.
-J Attempt to optimize jumps to branches. The -J option
will request the assembler to attempt to assemble jumps
and conditional jumps as relative branches where possi-
ble. Only those conditional jumps with branch
equivalents will be optimized, and jumps will only be
optimized to branches where the target is in branch
range. Note that the use of this option slows the
assembly down, due to the necessity for the assembler
to make an additional pass over the input code.
-U Treat undefined symbols as external. The -U option
will suppress error messages relating to undefined sym-
bols. Such symbols are treated as externals in any
case. The use of this option will not alter the object
code generated, but merely serves to suppress the error
messages.
Page 36 HI-TECH C USER'S MANUAL
-Ofile
Place the object code in file. The default object file
name is constructed from the name of the first source
file. Any suffix or file type (i.e. anything following
the rightmost dot ('.') in the name is stripped, and
the suffix .obj appended. Thus the command
ZAS file1.as file2.z80
will produce an object file called file1.obj. The use
of the -O option will override this default convention,
allowing the object file to be arbitrarily named. For
example:
ZAS -ox.obj file1.obj
will place the object code in x.obj.
-Llist
Place an assembly listing in the file list, or on stan-
dard output if list is null A listfile may be produced
with the -L option. If a file name is supplied to the
option, the list file will be created with that name,
otherwise the listing will be written to standard out-
put (i.e. the console). List file names such as CON:
and LST: are acceptable.
-Wwidth
The listing is to be formatted for a printer of given
width The -W option specifies the width to which the
listing is to be formatted. E.g.
ZAS -Llst: -W80 x.as
will output a listing formatted for an 80 column
printer to the list device.
-C This options requests ZAS to produce cross reference
information in a file. The file will be called xxx.crf
where xxx is the base part of the first source file
name. It will then be necessary to run the CREF utility
to turn this information into a formatted listing.
12.3. The Assembly Language
As mentioned above, the assembly language accepted by
zas is based on the Zilog mnemonics. You should have some
reference book such as the "Z80 Assembly Language Handbook".
Described below are those areas in which zas differs, or has
extensions, compared to the standard Zilog assembly
language.
12.3.1. Symbols
The symbols (labels) accepted by the assembler may be
of any length, and all characters are significant. The char-
acters used to form a symbol may be chosen from the upper
and lower case alphabetics, the digits 0-9, and the special
HI-TECH C USER'S MANUAL Page 37
symbols underscore ('_'), dollar ('$') and question mark
('?'). The first character may not be numeric. Upper and
lower case are distinct. The following are all legal and
distinct symbols.
An_identifier
an_identifier
an_identifier1
$$$
?$_123455
Note that the symbol $ is special (representing the
current location) and may not be used as a label. Nor may
any opcode or pseudo-op mnemonic, register name or condition
code name. You should note the additional condition code
names described later.
12.3.1.1. Temporary Labels
The assembler implements a system of temporary labels,
useful for use within a localized section of code. These
help eliminate the need to generate names for labels which
are referenced only in the immediate vicinity of their
definition, for example where a loop is implemented.
A temporary label takes the form of a digit string. A
reference to such a label requires the same digit string,
plus an appended b or f to signify a backward or forward
reference respectively. Here is an example of the use of
such labels.
entry_point: ;This is referenced from far away
ld b,10
1: dec c
jr nz,2f ;if zero, branch forward to 2:
ld c,8
djnz 1b ;decrement and branch back to 1:
jr 1f ;this does not branch to the
;same label as the djnz
2: call fred ;get here from the jr nz,2f
1: ret ;get here from the jr 1f
The digit string may be any positive decimal number 0
to 65535. A temporary label value may be re-used any number
of times. Where a reference to e.g. 1b is made, this will
reference the closest label 1: found by looking backwards
from the current point in the file. Similarly 23f will
reference the first label 23: found by looking forwards from
the current point in the file.
12.3.2. Constants
Constants may be entered in one of the radices 2, 8, 10
or 16. The default is 10. Constants in the other radices may
be denoted by a trailing character drawn from the following
set:
Page 38 HI-TECH C USER'S MANUAL
Character Radix Name
B 2 binary
O 8 octal
Q 8 octal
o 8 octal
q 8 octal
H 16 hexadecimal
h 16 hexadecimal
Hexadecimal constants may also be specified in C style,
for example LD A,0x21. Note that a lower case b may not be
used to indicate a binary number, since 1b is a backward
reference to a temporary label 1:.
12.3.2.1. Character Constants
A character constant is a single character enclosed in
single quotes ('). Multi character constants may be used
only as an operand to a DEFM pseudo-op.
12.3.2.2. Floating Constants
A floating constant in the usual notation (e.g. 1.234
or 1234e-3) may be used as the operand to a DEFF pseudo-op.
12.3.2.3. Opcode Constants
Any z80 opcode may be used as a constant in an expres-
sion. The value of the opcode in this context will be the
byte that the opcode would have assembled to if used in the
normal way. If the opcode is a 2-byte opcode (CB or ED pre-
fix byte) only the second byte of the opcode will be used.
This is particularly useful when setting up jump vectors.
For example:
ld a,jp ;a jump instruction
ld (0),a ;0 is jump to warm boot
ld hl,boot ;done here
ld (1),hl
12.3.3. Expressions
Expressions are constructed largely as described in the
"Z80 Assembly Language Handbook".
12.3.3.1. Operators
The following operators may be used in expressions:
Operator Meaning
& Bitwise AND
* Multiplication
+ Addition
- Subtraction
HI-TECH C USER'S MANUAL Page 39
.and. Bitwise AND
.eq. Equality test
.gt. Signed greater than
.high. Hi byte of operand
.low. Low byte of operand
.lt. Signed less than
.mod. Modulus
.not. Bitwise complement
.or. Bitwise or
.shl. Shift left
.shr. Shift right
.ult. Unsigned less than
.ugt. Unsigned greater than
.xor. Exclusive or
/ Divison
< Signed less than
= Equality
> Signed greater than
^ Bitwise or
Operators starting with a dot "." should be delimited
by spaces, thus label .and. 1 is valid but label.and.1 is
not.
12.3.3.2. Relocatability
Zas produces object code which is relocatable; this
means that it is not necessary to specify assembly time
where the code is to be located in memory. It is possible to
do so, by use of the ORG pseudo-op, however the preferred
approach is to use program sections or psects. A psect is a
named section of the program, in which code or data may be
defined at assembly time. All parts of a psect will be
loaded contiguously into memory, even if they were defined
in separate files, or in the same file but separated by code
for another psect. For example, the following code will load
some executable instructions into the psect named text, and
some data bytes into the data psect.
Page 40 HI-TECH C USER'S MANUAL
psect text, global
alabel:
ld hl,astring
call putit
ld hl,anotherstring
psect data, global
astring:
defm 'A string of chars'
defb 0
anotherstring:
defm 'Another string'
defb 0
psect text
putit:
ld a,(hl)
or a
ret z
call outchar
inc hl
jr putit
Note that even though the two blocks of code in the
text psect are separated by a block in the data psect, the
two text psect blocks will be contiguous when loaded by the
linker. The instruction "ld hl,anotherstring" will fall
through to the label "putit:" during execution. The actual
location in memory of the two psects will be determined by
the linker. See the linker manual for information on how
psect addresses are determined.
A label defined in a psect is said to be relocatable,
that is, its actual memory address is not determined at
assembly time. Note that this does not apply if the label is
in the default (unnamed) psect, or in a psect declared abso-
lute (see the PSECT pseudo-op description below). Any
labels declared in an absolute psect will be absolute, that
is their address will be determined by the assembler.
With the version of ZAS supplied with version 7 or
later of HI-TECH C, relocatable expressions may be combined
freely in expressions. Older versions of ZAS allowed only
limited arithmetic on relocatable expressions.
12.3.4. Pseudo-ops
The pseudo-ops are based on those described in the "Z80
Assembly Language Handbook", with some additions.
12.3.4.1. DEFB, DB
This pseudo-op should be followed by a comma-separated
list of expressions, which will be assembled into sequential
HI-TECH C USER'S MANUAL Page 41
byte locations. Each expression must have a value between
-128 and 255 inclusive. DB can be used as a synonym for
DEFB. Example:
DEFB 10, 20, 'a', 0FFH
DB 'hello world',13,10,0
12.3.4.2. DEFF
This pseudo-op assembles floating point constants into
32 bit HI-TECH C format floating point constants. For exam-
ple:
pi: DEFF 3.14159
12.3.4.3. DEFW
This operates in a similar fashion to DEFB, except that
it assembles expressions into words, without the value res-
triction. Example:
DEFW -1, 3664H, 'A', 3777Q
12.3.4.4. DEFS
Defs reserves memory locations without initializing
them. Its operand is an absolute expression, representing
the number of bytes to be reserved. This expression is
added to the current location counter. Note however that
locations reserved by DEFS may be initialized to zero by the
linker if the reserved locations are in the middle of the
program. Example:
DEFS 20h ;reserve 32 bytes of memory
12.3.4.5. EQU
Equ sets the value of a symbol on the left of EQU to
the expression on the right. It is illegal to set the value
of a symbol which is already defined. Example:
SIZE equ 46
12.3.4.6. DEFL
This is identical to EQU except that it may redefine
existing symbols. Example:
Page 42 HI-TECH C USER'S MANUAL
SIZE defl 48
12.3.4.7. DEFM
Defm should be followed by a string of characters,
enclosed in single quotes. The ASCII values of these char-
acters are assembled into successive memory locations.
Example:
DEFM 'A string of funny *@$ characters'
12.3.4.8. END
The end of an assembly is signified by the end of the
source file, or the END pseudo-op. The END pseudo-op may
optionally be followed by an expression which will define
the start address of the program. This is not actually use-
ful for CP/M. Only one start address may be defined per pro-
gram, and the linker will complain if there are more. Exam-
ple:
END somelabel
12.3.4.9. COND, IF, ELSE, ENDC
Conditional assembly is introduced by the COND pseudo-
op. The operand to COND must be an absolute expression. If
its value is false (zero) the code following the COND up to
the corresponding ENDC pseudo-op will not be assembled.
COND/ENDC pairs may be nested. IF may be used as a synonym
for COND. The ELSE pseudo operation may be included within
a COND/ENDC block, for example:
IF CPM
call 5
ELSE
call os_func
ENDC
12.3.4.10. ELSE
See COND.
12.3.4.11. ENDC
See COND.
HI-TECH C USER'S MANUAL Page 43
12.3.4.12. ENDM
See MACRO.
12.3.4.13. PSECT
This pseudo-op allows specification of relocatable pro-
gram sections. Its arguments are a psect name, optionally
followed by a list of psect flags. The psect name is a sym-
bol constructed according to the same rules as for labels,
however a psect may have the same name as a label without
conflict. Psect names are recognized only after a PSECT
pseudo-op. The psect flags are as follows:
ABS Psect is absolute
GLOBAL Psect is global
LOCAL Psect is not global
OVRLD Psect is to be overlapped by linker
PURE Psect is to be read-only
If a psect is global, the linker will merge it with any
other global psects of the same name from other modules.
Local psects will be treated as distinct from any other
psect from another module. Psects are global by default.
By default the linker concatenates code within a psect
from various modules. If a psect is specified as OVRLD, the
linker will overlap each module's contribution to that
psect. This is particularly useful when linking modules
which initialize e.g. interrupt vectors.
The PURE flag instructs the linker that the psect is to
be made read-only at run time. The usefulness of this flag
depends on the ability of the linker to enforce the require-
ment. CP/M fails miserably in this regard.
The ABS flag makes a psect absolute. The psect will be
loaded at zero. This is useful for statically initializing
interrupt vectors and jump tables. Examples:
PSECT text, global, pure
PSECT data, global
PSECT vectors, ovrld
12.3.4.14. GLOBAL
Global should be followed by one more symbols (comma
separated) which will be treated by the assembler as global
symbols, either internal or external depending on whether
they are defined within the current module or not. Example:
Page 44 HI-TECH C USER'S MANUAL
GLOBAL label1, putchar, _printf
12.3.4.15. ORG
An ORG pseudo-op sets the current psect to the default
(absolute) psect, and the location counter to its operand,
which must be an absolute expression. Example:
ORG 100H
12.3.4.16. MACRO
This pseudo-op defines a macro. It should be either
preceded or followed by the macro name, then optionally fol-
lowed by a comma-separated list of formal parameters. The
lines of code following the MACRO pseudo-op up to the next
ENDM pseudo-op will be stored as the body of the macro. The
macro name may subsequently be used in the opcode part of an
assembler statement, followed by actual parameters. The text
of the body of the macro will be substituted at that point,
with any use of the formal parameters substituted with the
corresponding actual parameter. For example:
print MACRO string
psect data
999: db string,'$'
psect text
ld de,999b
ld c,9
call 5
ENDM
When used, this macro will expand to the 3 instructions
in the body of the macro, with the actual parameters substi-
tuted for func and arg. Thus
print 'hello world'
expands to
psect data
999: db 'hello world','$'
psect text
ld de,999b
ld c,9
call 5
Macro arguments can be enclosed in angle brackets ('<'
HI-TECH C USER'S MANUAL Page 45
and '>') to pass arbitrary text including delimiter charac-
ters like commas as a single argument. For example, suppose
you wanted to use the print macro defined above to print a
string which includes the carriage return and linefeed char-
acters. The macro invocation:
print 'hello world',13,10
would fail because 13 and 10 are treated as extra arguments
and ignored. In order to pass a string which includes commas
as a single argument, you could write:
print <'hello world',13,10>
which would cause the text 'hello world',13,10 to be passed
through as a single argument. This would expand to the fol-
lowing code:
psect data
999: db 'hello world',13,10,'$'
psect text
ld de,999b
ld c,9
call 5
ZAS supports two forms of macro declaration for compa-
tibility with older versions of ZAS and other Z80 assem-
blers. The macro name may be declared either in the label
field before the MACRO pseudo-op, or in the operand field
after the MACRO pseudo-op. Thus these two MACRO declara-
tions are equivalent:
bdos MACRO func,arg
ld de,arg
ld c,func
call 5
ENDM
and
MACRO bdos,func,arg
ld de,arg
ld c,func
call 5
ENDM
12.3.4.17. LOCAL
The LOCAL pseudo-op allows unique labels to be defined
for each expansion of a macro. Any symbols listed after the
LOCAL directive will have a unique assembler-generated sym-
bol substituted for them when the macro is expanded. For
Page 46 HI-TECH C USER'S MANUAL
example:
copy MACRO source,dest,count
LOCAL nocopy
push af
push bc
ld bc,source
ld a,b
or c
jr z,nocopy
push de
push hl
ld de,dest
ld hl,source
ldir
pop hl
pop de
nocopy: pop bc
pop af
ENDM
when expanded will include a unique assembler generated
label in place of nocopy. For example, copy
(recptr),buf,(recsize) will expand to:
push af
push bc
ld bc,(recsize)
ld a,b
or c
jr z,??0001
push de
push hl
ld de,buf
ld hl,(recptr)
ldir
pop hl
pop de
??0001: pop bc
pop af
if invoked a second time, the label nocopy would expand to
??0002.
12.3.4.18. REPT
The REPT pseudo-op defines a temporary macro which is
then expanded a number of times, as determined by its argu-
ment. For example:
REPT 3
ld (hl),0
inc hl
ENDM
will expand to
HI-TECH C USER'S MANUAL Page 47
ld (hl),0
inc hl
ld (hl),0
inc hl
ld (hl),0
inc hl
12.3.5. IRP and IRPC
The IRP and IRPC directives are similar to REPT, how-
ever instead of repeating the block a fixed number of times
it is repeated once for each member of an argument list. In
the case of IRP the list is a conventional macro argument
list, in the case of IRPC it is successive characters from a
string. For example:
IRP string,<'hello world',13,10>,'arg2'
LOCAL str
psect data
str: db string,'$'
psect text
ld c,9
ld de,str
call 5
ENDM
would expand to
psect data
??0001: db 'hello world',13,10,'$'
psect text
ld c,9
ld de,??0001
call 5
psect data
??0002: db 'arg2','$'
psect text
ld c,9
ld de,??0002
call 5
Note the use of LOCAL labels and angle brackets in the same
manner as with conventional macros.
IRPC is best demonstrated using the following example:
IRPC char,ABC
ld c,2
ld e,'char'
call 5
ENDM
Page 48 HI-TECH C USER'S MANUAL
will expand to:
ld c,2
ld e,'A'
call 5
ld c,2
ld e,'B'
call 5
ld c,2
ld e,'C'
call 5
12.3.6. Extended Condition Codes
The assembler recognizes several additional condition
codes. These are:
_________________________________________________
| Code| Equivalent| Meaning |
| alt | m | Arithmetic less than |
| llt | c | Logical less than |
| age | p | Arithmetic greater or equal|
| lge | nc | Logical greater or equal |
| di | | Use after ld a,i for test-|
| ei | | ing state of interrupt|
| | | enable flag - enabled or|
|_____|____________|__disabled_respectively._____|
12.4. Assembler Directives
An assembler directive is a line in the source file
which produces no code, but rather which modifies the
behaviour of the assembler. Each directive is recognized by
the presence of an asterisk in the first column of the line,
followed immediately by a word, only the first character of
which is looked at. the line containing the directive itself
is never listed. The directives are:
*Title
Use the text following the directive as a title for the
listing.
*Heading
Use the text following the directive as a subtitle for
the listing; also causes an *Eject.
*List
May be followed by ON or OFF to turn listing on or off
respectively. Note that this directive may be used
inside a macro or include file to control listing of
that macro or include file. The previous listing state
will be restored on exit from the macro or include
file.
HI-TECH C USER'S MANUAL Page 49
*Include
The file named following the directive will be included
in the assembly at that point.
*Eject
A new page will be started in the listing at that
point. A form feed character in the source will have
the same effect.
Some examples of the use of these directives:
*Title Widget Control Program
*Heading Initialization Phase
*Include widget.i
12.5. Diagnostics
An error message will be written on the standard error
stream for each error encountered in the assembly. This mes-
sage identifies the file name and line number and describes
the error. In addition the line in the listing where the
error occurred will be flagged with a single character to
indicate the error. The characters and the corresponding
messages are:
Page 50 HI-TECH C USER'S MANUAL
A: Absolute expression required
B: Bad arg to *L
Bad arg to IM
Bad bit number
Bad character constant
Bad jump condition
D: Directive not recognized
Digit out of range
E: EOF inside conditional
Expression error
G: Garbage after operands
Garbage on end of line
I: Index offset too large
J: Jump target out of range
L: Lexical error
M: Multiply defined symbol
O: Operand error
P: Phase error
Psect may not be local and global
R: Relocation error
S: Size error
Syntax error
U: Undefined symbol
Undefined temporary label
Unterminated string
12.6. Z80/Z180/64180 Instruction Set
The remainder of this chapter is devoted to a complete
instruction set listing for the Z80, Z180, 64180 and NSC800
processors. The Z180 and 64180 will execute all Z80
instructions, although the timing is different.
HI-TECH C USER'S MANUAL Page 51
Page 52 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 53
Page 54 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 55
Page 56 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 57
Page 58 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 59
Page 60 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 61
Page 62 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 63
Page 64 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 65
Page 66 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 67
Page 68 HI-TECH C USER'S MANUAL
HI-TECH C USER'S MANUAL Page 69
13. Linker Reference Manual
HI-TECH C incorporates a relocating assembler and
linker to permit separate compilation of C source files.
This means that a program may be divided into several source
files, each of which may be kept to a manageable size for
ease of editing and compilation, then each object file com-
piled separately and finally all the object files linked
together into a single executable program.
The assembler is described in the machine-specific
manual. This appendix describes the theory behind and the
usage of the linker.
13.1. Relocation and Psects
The fundamental task of the linker is to combine
several relocatable object files into one. The object files
are said to be relocatable since the files have sufficient
information in them so that any references to program or
data addresses (e.g. the address of a function) within the
file may be adjusted according to where the file is ulti-
mately located in memory after the linkage process. Thus the
file is said to be relocatable. Relocation may take two
basic forms; relocation by name, i.e. relocation by the
ultimate value of a global symbol, or relocation by psect,
i.e. relocation by the base address of a particular section
of code, for example the section of code containing the
actual excutable instructions.
13.1.1. Program Sections
Any object file may contain bytes to be stored in
memory in one or more program sections, which will be
referred to as psects. These psects represent logical group-
ings of certain types of code bytes in the program. The
section of the program containing executable instructions is
normally referred to as the text psect. Other sections are
the initialized data psect, called simply the data psect,
and the uninitialized data psect, called the bss psect.
In fact the linker will handle any number of psects,
and in fact more may be used in special applications. How-
ever the C compiler uses only the three mentioned, and the
names text, data and bss are simply chosen for identifica-
tion; the linker assigns no special significance to the name
of a psect.
The difference between the data and bss psects may be
exemplified by considering two external variables; one is
initialized to the value 1, and the other is not initial-
ized. The first will be placed into the data psect, and the
second in the bss psect. The bss psect is always cleared to
zeros on startup of the program, thus the second variable
will be initialized at run time to zero. The first will how-
ever occupy space in the program file, and will maintain its
Page 70 HI-TECH C USER'S MANUAL
initialized value of 1 at startup. It is quite possible to
modify the value of a variable in the data psect during exe-
cution, however it is better practice not to do so, since
this leads to more consistent use of variables, and allows
for restartable and romable programs.
The text psect is the section into which all executable
instructions are placed. On CP/M-80 the text psect will nor-
mally start at the base of the TPA, which is where execution
commences. The data psect will normally follow the text
psect, and the bss will be last. The bss does not occupy
space in the program (.COM) file. This ordering of psects
may be overridden by an option to the linker. This is espe-
cially useful when producing code for special hardware.
For MS-DOS and CP/M-86 the psects are ordered in the
same way, but since the 8086 processor has segment registers
providing relocation, both the text and data psects start at
0, even though they will be loaded one after the other in
memory. This allows 64k code and 64k data and stack. Suffi-
cient information is placed in the executable file (.EXE or
.CMD) for the operating system to load the program in
memory.
13.1.2. Local Psects and the Large Model
Since for practical purposes the psects are limited to
64K on the 8086, to allow more than 64K code the compiler
makes use of local psects. A psect is considered local if
the .psect directive has a LOCAL flag. Any number of local
psects may be linked from different modules without being
combined even if they have the same name. Note however that
no local psect may have the same name as a global psect.
All references to a local psect within the same module
(or within the same library) will be treated as references
to the same psect. Between modules however two local psects
of the same name are treated as distinct. In order to allow
collective referencing of local psects via the -P option
(described later) a local psect may have a class name asso-
ciated with it. This is achieved witht the CLASS flag on the
.psect directive.
13.2. Global Symbols
The linker handles only symbols which have been
declared as global to the assembler. From the C source
level, this means all names which have storage class exter-
nal and which are not declared as static. These symbols may
be referred to by modules other than the one in which they
are defined. It is the linker's job to match up the defini-
tion of a global symbol with the references to it.
HI-TECH C USER'S MANUAL Page 71
13.3. Operation
A command to the linker takes the following form:
LINK options files ...
Options is zero or more linker options, each of which
modifies the behaviour of the linker in some way. Files is
one or more object files, and zero or more library names.
The options recognized by the linker are as follows: they
will be recognized in upper or lower case.
-R Leave the output relocatable.
-L Retain absolute relocation info. -LM will retain only
segement relocation information.
-I Ignore undefined symbols.
-N Sort symbols by address.
-Caddr
Produce a binary output file offset by addr.
-S Strip symbol information from the output file.
-X Suppress local symbols in the output file.
-Z Suppress trivial (compiler-generated) symbols in the
output file.
-Oname
Call the output file name.
-Pspec
Spec is a psect location specification.
-Mname
Write a link map to the file name.
-Usymbol
Make symbol initially undefined.
-Dfile
Write a symbol file.
-Wwidth
Specify map width.
Taking each of these in turn:
The -R option will instruct the linker to leave the
output file (as named by a -O option, or l.obj by default)
relocatable. This is normally because there are further
files to be linked in, and the output of this link will be
used as input to the linker subsequently. Without this
option, the linker will make the output file absolute, that
Page 72 HI-TECH C USER'S MANUAL
is with all relocatable addresses made into absolute refer-
ences. This option may not be used with the -L or -C
options.
The -L option will cause the linker to output null
relocation information even though the file will be abso-
lute. This information allows self-relocating programs to
know what addresses must be relocated at run time. This
option is not usable with the -C option. In order to create
an executable file (i.e. a .COM file) the program objtohex
must be used. If a -LM option is used, only segment reloca-
tion information will be retained. This is used in conjuc-
tion with the large memory model. Objtohex will use the
relocation information (when invoked with a -L flag) to
insert segment relocation addresses into the executable
file.
The -I option is used when it is desired to link code
which contains symbols which are not defined in any module.
This is normally only used during top-down program develop-
ment, when routines are referenced in code written before
the routines themselves have been coded.
When obtaining a link map via the -M option, the symbol
table is by default sorted in order of symbol name. To sort
in order of address, the -N option may be used.
The output of the linker is by default an object file.
To create an executable program, this must be converted into
an executable image. For CP/M this is a .COM file, which is
simply an image of the executable program as it should
appear in memory, starting at location 100H. The linker will
produce such a file with the -C100H option. File formats for
other applications requiring an image binary file may also
be produced with the -C option. The address following the
-C may be given in decimal (default), octal (by using o or O
suffix) or hexadecimal (by using an h or H suffix).
Note that because of the complexity of the executable
file formats for MS-DOS and CP/M-86, LINK will not produce
these (.EXE and .CMD resp.) formats directly. The compiler
automatically runs OBJTOHEX with appropriate options to gen-
erate the correct file format.
The -S, -X and -Z options, which are meaningless when
the -C option is used, will strip respectively all symbols,
all local symbols or all trivial local symbols from the out-
put file. Trivial symbols are symbols produced by the com-
piler, and have the form of one of a set of alphabetic char-
acters followed by a digit string.
The default output file name is l.obj, or l.bin when
the -C option is used. This may be overridden by the -Oname
option. The output file will be called name in this
instance. Note that no suffix is appended to the name; the
file will be called exactly the argument to the option.
For certain specialized applications, e.g. producing
HI-TECH C USER'S MANUAL Page 73
code for an embedded microprocessor, it is necessary to
specify to the linker at what address the various psects
should be located. This is accomplished with the -P option.
It is followed by a specification consisting of a comma-
separated list of psect names, each with an optional address
specification. In the absence of an address specification
for a psect listed, it will be concatenated with the previ-
ous psect. For example
-Ptext=0c000h,data,bss=8000h
This will cause the text psect to be located at 0C000H,
the data psect to start at the end of the text psect, and
the bss psect to start at 8000H. This may be for a processor
with ROM at 0C000H and RAM at 8000H.
Where the link address, that is the address at which
the code will be addressed at execution time, and the load
address, that is the address offset within the output file,
are different (e.g for the 8086) it is possible to specify
the load address separately from the link address. For exam-
ple:
-Ptext=100h/0,data=0C000h/
This specification will cause the text segment to be
linked for execution at 100h, but loaded in the output file
at 0, while the data segment will be linked for 0C000h, but
loaded contiguously with the text psect in the file. Note
that if the slash (`/') is omitted, the load address is the
same as the link address, while if the slash is supplied,
but not followed by an address, the psect will be loaded
after the previous psect.
In order to specify link and load addresses for local
psects, the group name to which the psects belong may be
used in place of a global psect name. The local psects will
then have a link address as specified in the -P option, and
load addresses incrementing upwards from the specified load
address.
The -Mname option requests a link map, containing sym-
bol table and module load address information to be written
onto the file name. If name is omitted, the map will be
written to standard output. -W may be used to specify the
desired width of the map.
The -U option allows the specification to the linker of
a symbol which is to be initially entered into the symbol
table as undefined. This is useful when loading entirely
from libraries. More than one -U flag may be used.
If it is desired to use the debugger on the program
being linked, it is useful to produce a symbol file. The
-Dfile option will write such a symbol file onto the named
file, or l.sym if no file is given. The symbol file consists
Page 74 HI-TECH C USER'S MANUAL
of a list of addresses and symbols, one per line.
13.4. Examples
Here are some examples of using the linker. Note how-
ever that in the normal case it is not necessary to invoke
the linker explicitly, since it is invoked automatically by
the C command.
LINK -MMAP -C100H START.OBJ MAIN.OBJ A:LIBC.LIB
This command links the files start.obj and main.obj
with the library a:libc.lib. Only those modules that are
required from the library will be in fact linked in. The
output is to be in .COM format, placed in the default file
l.bin. A map is to be written to the file of the name map.
Note that the file start.obj should contain startup code,
and in fact the lowest address code in that file will be
executed when the program is run, since it will be at 100H.
LINK -X -R -OX.OBJ FILE1.OBJ FILE2.OBJ A:LIBC.LIB
The files file1.obj and file2.obj will be linked with
any necessary routines from a:libc.lib and left in the file
x.obj. This file will remain relocatable. Undefined symbols
will not cause an error. The file x.obj will probably later
be the object of another link invocation. All local symbols
will be stripped from the output file, thus saving space.
13.5. Invoking the Linker
The linker is called LINK, and normally resides on the
A: drive, under CP/M, or in the directory A:\HITECH\ under
MS-DOS. It may be invoked with no arguments, in which case
it will prompt for input from standard input. If the stan-
dard input is a file, no prompts will be printed. The input
supplied in this manner may contain lower case, whereas CP/M
converts the entire command line to upper case by default.
This is useful with the -U and -P options. This manner of
invocation is generally useful if the number of arguments to
LINK is large. Even if the list of files is too long to fit
on one line, continuation lines may be included by leaving a
backslash ('\') at the end of the preceding line. In this
fashion, LINK commands of almost unlimited length may be
issued.
HI-TECH C USER'S MANUAL Page 75
14. Librarian
The librarian program, LIBR, has the function of com-
bining several object files into a single file known as a
library. The purposes of combining several such object
modules are several.
a. fewer files to link
b. faster access
c. uses less disk space
In order to make the library concept useful, it is
necessary for the linker to treat modules in a library dif-
ferently from object files. If an object file is specified
to the linker, it will be linked into the final linked
module. A module in a library, however, will only be linked
in if it defines one or more symbols previously known, but
not defined, to the linker. Thus modules in a library will
be linked only if required. Since the choice of modules to
link is made on the first pass of the linker, and the
library is searched in a linear fashion, it is possible to
order the modules in a library to produce special effects
when linking. More will be said about this later.
14.1. The Library Format
The modules in a library are basically just con-
catenated, but at the beginning of a library is maintained a
directory of the modules and symbols in the library. Since
this directory is smaller than the sum of the modules, the
linker is speeded up when searching a library since it need
read only the directory and not all the modules on the first
pass. On the second pass it need read only those modules
which are required, seeking over the others. This all minim-
izes disk i/o when linking.
It should be noted that the library format is geared
exclusively toward object modules, and is not a general pur-
pose archiving mechanism as is used by some other compiler
systems. This has the advantage that the format may be
optimized toward speeding up the linkage process.
14.2. Using
The librarian program is called LIBR, and the format of
commands to it is as follows:
LIBR k file.lib file.obj ...
Interpreting this, LIBR is the name of the program, k
is a key letter denoting the function requested of the
librarian (replacing, extracting or deleting modules, list-
ing modules or symbols), file.lib is the name of the library
file to be operated on, and file.obj is zero or more object
Page 76 HI-TECH C USER'S MANUAL
file names.
The key letters are:
r replace modules
d delete modules
x extract modules
m list module names
s list modules with symbols
When replacing or extracting modules, the file.obj
arguments are the names of the modules to be replaced or
extracted. If no such arguments are supplied, all the
modules in the library will be replaced or extracted respec-
tively. Adding a file to a library is performed by request-
ing the librarian to replace it in the library. Since it is
not present, the module will be appended to the library. If
the r key is used and the library does not exist, it will be
created.
Under the d keyletter, the named object files will be
deleted from the library. In this instance, it is an error
not to give any object file names.
The m and s keyletters will list the named modules and,
in the case of the s keyletter, the symbols defined or
referenced within (global symbols only are handled by the
librarian). As with the r and x keyletters, an empty list of
modules means all the modules in the library.
14.3. Examples
Here are some examples of usage of the librarian.
LIBR m file.lib
List all modules in the library file.lib.
LIBR s file.lib a.obj b.obj c.obj
List the global symbols in the modules a.obj, b.obj and
c.obj
LIBR r file.lib 1.obj 2.obj
Replace the module 1.obj in the file file.lib with the
contents of the object file 1.obj, and repeat for
2.obj. If the object module is not already present in
the library, append it to the end.
LIBR x file.lib
Extract, without deletion, all the modules in file.lib
and write them as object files on disk.
LIBR d file.lib a.obj b.obj 2.obj
Delete the object modules a.obj, b.obj and 2.obj from
the library file.lib.
HI-TECH C USER'S MANUAL Page 77
14.4. Supplying Arguments
Since it is often necessary to supply many object file
arguments to LIBR, and command lines are restricted to 127
characters by CP/M and MS-DOS, LIBR will accept commands
from standard input if no command line arguments are given.
If the standard input is attached to the console, LIBR will
prompt. Multiple line input may be given by using a
backslash as a continuation character on the end of a line.
If standard input is redirected from a file, LIBR will take
input from the file, without prompting. For example:
LIBR
libr> r file.lib 1.obj 2.obj 3.obj \
libr> 4.obj 5.obj 6.obj
will perform much the same as if the .obj files had been
typed on the command line. The libr> prompts were printed by
LIBR itself, the remainder of the text was typed as input.
LIBR <lib.cmd
Libr will read input from lib.cmd, and execute the com-
mand found therein. This allows a virtually unlimited length
command to be given to LIBR.
14.5. Listing Format
A request to LIBR to list module names will simply pro-
duce a list of names, one per line, on standard output. The
s keyletter will produce the same, with a list of symbols
after each module name. Each symbol will be preceded by the
letter D or U, representing a definition or reference to the
symbol respectively. The -W option may be used to determine
the width of the paper for this operation. For example LIBR
-w80 s file.lib will list all modules in file.lib with their
global symbols, with the output formatted for an 80 column
printer or display.
14.6. Ordering of Libraries
The librarian creates libraries with the modules in the
order in which they were given on the command line. When
updating a library the order of the modules is preserved.
Any new modules added to a library after it has been created
will be appended to the end.
The ordering of the modules in a library is significant
to the linker. If a library contains a module which refer-
ences a symbol defined in another module in the same
library, the module defining the symbol should come after
the module referencing the symbol.
Page 78 HI-TECH C USER'S MANUAL
14.7. Error Messages
Libr issues various error messages, most of which
represent a fatal error, while some represent a harmless
occurence which will nonetheless be reported unless the -w
option was used. In this case all warning messages will be
suppressed.
HI-TECH C USER'S MANUAL Page 79
15. Objtohex
The HI-TECH linker is capable of producing simple
binary files, or object files as output. Any other format
required must be produced by running the utility program
OBJTOHEX. This allows conversion of object files as pro-
duced by the linker into a variety of different formats,
including various hex formats. The program is invoked thus:
OBJTOHEX options inputfile outputfile
All of the arguments are optional. If outputfile is
ommitted it defaults to l.hex or l.bin depending on whether
the -b option is used. The inputfile defaults to l.obj.
The options are:
-Baddr
Produce a binary image output. This is similar to the
-C option of the linker. If addr is supplied, the
start of the image file will be offset by addr. If addr
is omitted, the first byte in the file will be the
lowest byte initialized. Addr may be given in decimal,
octal or hexadecimal. The default radix is decimal, and
suffix letters of o or O indicate octal, and h or H
indicate hex. Thus -B100H will produce a file in .COM
format.
-I Include symbol records in the Intel format hex output.
Each symbol record has a form similar to an object
record, but with a different record type. The data
bytes in the record are the symbol name, and the
address is the value of the symbol. This is useful for
downloading to ROM debuggers.
-C Read a checksum specification from the standard input.
The checksum specification is described below. Typi-
cally the specification will be in a file.
-Estack
This option produces an MS-DOS .EXE format file. The
optional stack argument will determine the maximum
stack size the program will be allocated on execution.
By default the program will be allocated the maximum
stack available, up to the limit of 64K data. If a
stack argument is supplied, the stack size will not
exceed the argument. This is useful to limit the amount
of memory a program will use. The stack argument takes
the same form as the argument to -B above.
-8stack
This option will produce a CP/M-86 .CMD file. The stack
argument is the same as for the -E option.
Page 80 HI-TECH C USER'S MANUAL
-Astack
This is used when producing a.out format files for unix
systems (specifically Venix-86). If the stack argument
is zero, the size of the data segment will be 64k, oth-
erwise the stack will be placed below the data segment,
and its size set to stack. This must be co-ordinated
with appropriate arguments to the -p option of the
linker.
-M This flag will instruct objtohex to produce Motorola
'S' format hex output.
-L This option is used when producing large model pro-
grams; the linker will have been used with the -LM
option to retain segment relocation information in the
object file. Use of the -L option to objtohex will
cause it to convert that segment relocation information
into appropriate data in the executable file for use
when the program is loaded. Either the operating system
or the run-time startup code will use the relocation
data to adjust segment references based on where in
memory the program is actually loaded. If the -L
option is followed by a symbol name, then the reloca-
tion information will be stored at the address
represented by that symbol in the output file, e.g.
-L__Bbss will cause it to be stored at the base of the
bss psect (__Bbss is defined by the linker to be the
load address of the bss psect). If the special symbol
Dos_hdr is used then the relocation information will be
stored in the .EXE file header. This is only valid in
conjunction with the -E option.
-S The -S option instructs objtohex to write a symbol
file. The symbol file name is given after the -S, e.g.
-Sxx.sym.
Unless another format is specifically requested,
objtohex will produce a file in Intel hex format. This is
suitable for down-line loading, PROM programming etc. The
HP format is useful for transferring code to an HP64000 for
emulation or PROM programming.
The checksum specification allows automated checksum
calculation. The checksum specification takes the form of
several lines, each line describing one checksum. The syntax
of a checksum line is:
addr1-addr2 where1-where2 +offset
All of addr1, addr2, where1, where2 and offset are hex
numbers, without the usual H suffix. Such a specification
says that the bytes at addr1 through to addr2 inclusive
should be summed and the sum placed in the locations where1
through where2 inclusive. For an 8 bit checksum these two
addresses should be the same. For a checksum stored low byte
first, where1 should be less than where2, and vice versa.
The +offset is optional, but if supplied, the value offset
HI-TECH C USER'S MANUAL Page 81
will be used to initialize the checksum. Otherwise it is
initialized to zero. For example:
0005-1FFF 3-4 +1FFF
This will sum the bytes in 5 through 1FFFH inclusive,
then add 1FFFH to the sum. The 16 bit checksum will be
placed in locations 3 and 4, low byte in 3. The checksum is
initialized with 1FFFH to provide protection against an all
zero rom, or a rom misplaced in memory. A run time check of
this checksum would add the last address of the rom being
checksummed into the checksum. For the rom in question, this
should be 1FFFH. The initialization value may, however, be
used in any desired fashion.
Page 82 HI-TECH C USER'S MANUAL
Use this page for notes
HI-TECH C USER'S MANUAL Page 83
16. Cref
The cross reference list utility CREF is used to format
raw cross-reference information produced by the compiler or
the assembler into a sorted listing. A raw cross-reference
file is produced with the -CR option to the compiler. The
assembler will generate a raw cross-reference file with a -C
option (Z80 or 8086 assemblers) or by using an OPT CRE
directive (6800 series assemblers) or a REF control line
(8096 assembler).. The general form of the CREF command is:
CREF options files
where options is zero or more options as described below and
files is one or more raw cross-reference files. CREF takes
the following options:
-Ooutfile
Allows specification of the output file name. By
default the listing will be written to the standard
output and may be redirected in the usual manner.
Alternatively using the -O option an output file name
may be specified, e.g. -Oxxx.lst.
-Pwidth
This option allows the specification of the width to
which the listing is to be formatted, e.g. -P132 will
format the listing for a 132 column printer. The
default is 80 columns.
-Llength
Specify the length of the paper on which the listing is
to be produced, e.g. if the listing is to be printed
on 55 line paper you would use a -L55 option. The
default is 66 lines.
-Xprefix
The -X option allows the exclusion of symbols from the
listing, based on a prefix given as argument to -X. For
example if it was desired to exclude all symbols start-
ing with the character sequence xyz then the option
-Xxyz would be used. If a digit appears in the charac-
ter sequence then this will match any digit in the sym-
bol, e.g. -XX0 would exclude any symbols starting with
the letter X followed by a digit.
-F -F will exclude from the listing any references from
files with a full path name. A full path name means
either: a file name starting with a slash ('/') or
backslash ('\') or a file name starting with a CP/M
user number/drive letter prefix, e.g. 0:A:. This is
intended to force omission from the listing of any sym-
bol references derived from standard header files, e.g.
using -F would omit any references from the header file
STDIO.H.
Page 84 HI-TECH C USER'S MANUAL
-Hstring
The -H option takes a string as an argument which will
be used as a header in the listing. The default heading
is the name of the first raw cross-ref information file
specified.
-Sstoplist
The -S option should have as its argument the name of a
file containing a list of symbols not to be listed in
the cross-reference. Multiple stoplists may be supplied
with multiple -S options.
Cref will accept wild card filenames and I/O redirec-
tion. Long command lines may be supplied by invoking CREF
with no arguments and typing the command line in response to
the cref> prompt. A backslash at the end of the line will be
interpreted to mean that more command lines follow.
HI-TECH C USER'S MANUAL Page 85
APPENDIX 1
Error Messages
Error Messages produced by the compiler are listed
below. Each message is followed by the name of the program
which produces it, and some further description of what
causes the message or what to do about it.
'.' expected after '..' P1
The ellipsis symbol must have three dots
actuals too long CPP
Reduce length of macro arguments
argument list conflicts with prototype P1
The argument list in a function definition must agree
with a prototype if one exists
argument redeclared P1
This argument has been declared twice
arithmetic overflow in constant expression CGEN
Evaluation of this constant expression produced an
arithmetic overflow. This may or may not represent a
true error.
array index out of bounds P1
An array index expression evaluates to a constant which
is less than zero or greater than or equal to the
dimension of the array
Assertion CGEN
Internal error - contact HI-TECH
attempt to modify const object P1
An attempt has been made to assign to or otherwise
modify an object designated as 'const'
bad bitfield type P1
Bitfields must be of type 'int'
Bad conval CGEN
Internal error - contact HI-TECH
Bad dimensions CGEN
An array has bad dimensions - probably zero
Bad element count expr CGEN
Internal error - contact HI-TECH
bad formal CPP
Check macro defintion syntax
Page 86 HI-TECH C USER'S MANUAL
bad include syntax CPP
Use only "" and <> for include files
Bad int. code CGEN
The intermediate code file has been corrupted - can be
caused by running out of disk space
Bad -M option CGEN
A -M option passed to the code generator is unknown
Bad mod '+' for how = c CGEN
Internal error - contact HI-TECH
bad object code format LINK
This file is either corrupted or not a valid object
file
Bad op d to swaplog CGEN
Internal error - contact HI-TECH
Bad op n to revlog CGEN
Internal error - contact HI-TECH
bad origin format in spec LINK
An address in a -p option is invalid
bad '-p' format LINK
The -p option provided is invalid
Bad pragma c CGEN
The code generator has been passed a pragma it does not
know about
Bad putwsize CGEN
Internal error - contact HI-TECH
bad storage class P1, CGEN
The speficied storage class is illegal
Bad U usage CGEN
Internal error - contact HI-TECH
Bit field too large (n bits) CGEN
A bit field may not be larger than an int
Cannot get memory LINK
The linker has run out of dynamic memory
Can't be both far and near P1
The 'far' and 'near' keywords cannot appear in the same
type specifier
can't be long P1
Chars and shorts cannot be long
can't be register P1
An extern or static variable may not be register
HI-TECH C USER'S MANUAL Page 87
can't be short P1
Float and char cannot be short
can't be unsigned P1
Float cannot be unsigned
can't call an interrupt function P1
A function qualified 'interrupt' can only be called by
hardware, not by an ordinary function call
Can't create filename CGEN
The file specified could not be created
Can't create xref file P1
The cross reference file specified could not be created
Can't create CPP
Output file could not be created
Can't create LINK
The linker cannot create a file
Can't find include file CPP
Check and correct the include file name - spaces are
not allowed in file names
Can't find register for bits CGEN
Internal error - contact HI-TECH
Can't generate code for this expression CGEN
The code generator is unable to generate code for this
expression - simplifying the expression (e.g. computing
values into temporary variables) will usually correct
it, otherwise contact HI-TECH
can't have array of functions P1
You cannot have an array of functions - you can have an
array of pointers to functions
Can't have 'port' variable CGEN
You cannot declare a variable to be qualified 'port' -
you can only use port to qualify pointers or typecast
constant values
can't have storage class P1
A storage class may not appear in a prototype argument
can't initialise auto aggregates P1
You cannot initialise a structure or array inside a
function unless it is static
can't initialize arg P1
An argument cannot have an initializer
can't mix proto and non-proto args P1
You cannot mix prototype and non-prototype arguments
even in a function definition
Page 88 HI-TECH C USER'S MANUAL
Can't open filename CGEN
The file specified could not be opened for reading
Can't open LINK
The linker cannot open a file
Can't seek LINK
The linker could not seek in file
can't take address of register variable P1
You can't take the address of a variable in a register
can't take sizeof func CGEN
You can't take the size of a function. You can take the
size of a function call
can't take this address P1
The expression does not have an address
'case' not in switch P1
A 'case' label is permitted only inside a switch
char const too long P1
A character constant may have only one character in it
close error (disk space?) P1
Probably out of disk space
common symbol psect conflict LINK
A common symbol is defined to be in more than one psect
constant conditional branch CGEN
You have a program structure testing a constant expres-
sion, e.g. while(1). You should substitute for this the
more efficient for(;;)
constant expression required P1
A constant expression is required in e.g. an array
dimension
constant operand to || or && CGEN
A logical operator has a constant operand which has
been optimized out
declarator too complex P1
This declaration is too complex for the compiler to
handle
default case redefined P1
Only one default case is permitted in a switch
'default' not in switch P1
A 'default' label is permitted only inside a switch
digit out of range P1
An octal constant may not contain 7 or 8, and a decimal
constant may not contain A-F
HI-TECH C USER'S MANUAL Page 89
dimension required P1
A dimension is required for all except the most signi-
ficant in an array declaration
Division by zero CGEN
Attempt to divide by zero in this expression
Duplicate case label n CGEN
There are two case labels in this switch that have the
same value
Duplicate -d flag LINK
Only one -d flag is allowed to the linker
duplicate label P1
This label is defined twice
Duplicate -m flag LINK
Only one -m flag is allowed to the linker
duplicate qualifier P1
The same qualifier appears more than once in this type
specifier
entry point multiply defined LINK
A program can only have one entry point (start address)
EOF in #asm P1
End of file was encounterd after #asm and before a
#endasm was seen
Error closing output file CGEN,CPP
Probably means you have run out of disk space
excessive -I file ignored CPP
Use fewer -I options
expand - bad how CGEN
Internal error - contact HI-TECH
expand - bad which CGEN
Internal error - contact HI-TECH
exponent expected P1
An exponent is expected after the 'e' or 'E' in a
floating point constant. The exponent must contain only
+, - and digits 0-9
Expression error CGEN
Internal error - contact HI-TECH
expression generates no code CGEN
This expression has no side effects and thus generates
no code. It has been optimized out
expression syntax P1
The expression is badly formed
Page 90 HI-TECH C USER'S MANUAL
expression too complex P1
The expression has too many nested parantheses or other
nested constructs
Fixup overflow referencing LINK
The linker has relocated a reference to a psect or sym-
bol and the relocated address is too big to fit into
the space, e.g. a relocated one byte address exceeds
256 or a relocated 16 bit address exceeds 65536
float param coerced to double P1
This float parameter has been converted to double - a
prototype will override this coercion
function() declared implicit int P1
This function has been called without an explicit
declaration. It is wise to explicitly declare all func-
tions, preferably with a prototype. This will avoid
many potential errors where your program comprises more
than one source file
function does not take arguments P1
The prototype for this function indicates it takes no
arguments
function or function pointer required P1
A function identifier or pointer to function is
required for a function call.
functions can't return arrays P1
A function cannot return an array - it can return a
pointer
functions can't return functions P1
A function cannot return a function - it can return a
pointer to function
hex digit expected P1
A hex digit is expected after '0x'
identifier is a structure tag P1
A structure tag has been used in a context where
another kind of tag is expected, e.g. saying struct
fred where fred has previously been declared as union
fred.
identifier is a union tag P1
Similar to the above error
identifier is an enum tag P1
Similar to the above error
identifier: large offset CGEN
Z80 only: This identifier has a large offset from the
stack frame and thus access to it is inefficient. In a
function any arrays should be declared after any simple
variables
HI-TECH C USER'S MANUAL Page 91
identifier redeclared P1
The identifier has been redeclared with different
attributes
identifier redefined P1
An identifier has been defined twice
If-less else CPP
Check #if usage
If-less endif CPP
Check #if usage
illegal '#' directive P1
A # directive passed through to the first pass is unk-
nown. If this occurs with a #include it may be caused
by a previous include file not having a <CR><LF> or
newline on the last line.
Illegal character in preprocessor if CPP
Check for strange character
illegal character P1
A character unknown to the compiler has been encoun-
tered. The value given is the octal value of the char-
acter
illegal conversion between pointer types P1
The expression causes one pointer type to be converted
to another incompatible type
illegal conversion of integer to pointer P1
An integer is used where a pointer is expected
illegal conversion of pointer to integer P1
A pointer is used where an integer is expected
illegal conversion P1
The type conversion here is illegal
Illegal flag LINK
This option is illegal
illegal function qualifier(s) P1
A function cannot have 'const' qualification
illegal initialisation P1
The initialisation of this variable is illegal
Illegal number CPP
Check number syntax
illegal type for array dimension P1
An array dimension must be an integral quantity
illegal type for index expression P1
An array index must be a simple integral expression
Page 92 HI-TECH C USER'S MANUAL
illegal type for switch expression P1
The expression in a 'switch' must be integral
illegal use of void expression P1
Void expressions may not be used in any way
implicit conversion of float to integer P1
A floating point value has been converted to integer -
truncation may occur
implicit return at end of non-void function P1
A function with a non-void type has returned without a
return statement
implict signed to unsigned conversion P1
Unwanted sign extension may occur here. Add an explicit
typecast to force exactly the conversion you want
inappropriate break/continue P1
inappropriate 'else' P1
An 'else' has appeared without a matching 'if'
inconsistent storage class P1
Only one storage class may be specified in a declara-
tion
inconsistent type P1
Only one basic type may be specified in a declaration
initialisation illegal in arg list P1
You cannot initialise a function parameter
initialisation syntax P1
The syntax of this initialisation is illegal
initializer in 'extern' declaration P1
A declaration with the 'extern' keyword has an initial-
izer; this is not permitted as the extern declaration
reserves no storage
integer constant expected P1
An integer constant was expected here
integer expression required P1
An integral expression is required here
integral type required P1
An integral type is required here
large offset CGEN
Z80 only: This identifier has a large offset from the
stack frame and thus access to it is inefficient. In a
function any arrays should be declared after any simple
variables
HI-TECH C USER'S MANUAL Page 93
Line too long P1
The source line is too long, or does not have a
<CR><LF> or newline at the end
local psect conflicts with global psect of same name
LINK
A local psect cannot have the same name as a global
psect
logical type required P1
A logical type (i.e. an integral type) is required as
the subject of a conditional expression
lvalue required P1
An lvalue, i.e. something which can be assigned to, is
required after an '&' or on the left hand of an assign-
ment
macro recursion CPP
A preprocessor macro has attempted to expand itself.
This would create infinite recursion
member is not a member of the struct/union P1
This member is not in the structure or union with which
it is used
members cannot be functions P1
A member cannot be a function - it can be a pointer to
function
Missing arg to -u LINK
-u requires an argument
Missing arg to -w LINK
-w requires an argument
missing ) CPP
Put correct ) in expression
Missing number after % in -p option LINK
After % in a -p option there must be a number
Missing number after pragma 'pack' P1
The correct syntax is #pragma pack(n) where n is 1, 2
or 4.
module has code below file base LINK
A -C option was specified but the program has code
below the address specified as the base of the binary
file
multiply defined symbol LINK
A symbol is defined more than once
name is a union, struct or enum P1
A union, struct or enum tag has been re-used in a dif-
ferent context
Page 94 HI-TECH C USER'S MANUAL
No case labels CGEN
This switch has no case labels
no identifier in declaration P1
This declaration should have an identifier in it
No room CGEN
The code generator has run out of dynamic memory. You
will need to reduce the number of symbols and/or the
complexity of expressions
No source file CPP
Source file could not be found - check spelling, direc-
tory paths etc.
no space CPP
Reduce number/size of macro definitions
no start record: entry point defaults to zero LINK
No start address has been specified for the program;
the linker has set the start address to 0
Non-constant case label CGEN
This case label does not evaluate to an integral con-
stant
non-void function returns no value P1
A function which should return a value has a 'return'
statement with no value
not a variable identifier P1
The identifier is not a variable - it may be e.g. a
label or structure tag
not an argument P1
This identifier is not in the argument list for this
function
only functions may be qualified interrupt P1
The type qualifier 'interrupt' may be applied only to
functions, not variables.
only functions may be void P1
Only functions, not variables, may be declared void
only lvalues may be assigned to or modified P1
You have attempted to modify an expression which does
not identify a storage location
only register storage class allowed P1
A parameter may only be auto or register
operands of operator not same pointer type P1
The operands to the named operator in the expression
are both pointers but are not the same pointer type
HI-TECH C USER'S MANUAL Page 95
operands of operator not same type P1
The operands to the named operator in the expression
are incompatible types
pointer required P1
A pointer is required after a '*' (indirection) opera-
tor
popreg - bad reg CGEN
Internal error - contact HI-TECH
portion of expression has no effect CGEN
A portion of this expression has no effect on its value
and no side effects
probable missing '}' in previous block P1
A declaration has been encountered where an expression
was expected. The likely cause of this is that you have
omitted a closing '}' in the function above this point.
psect cannot be in classes a and b LINK
A psect can only be in one class
psect exceeds max size LINK
This psect is larger than a specified maximum size
psect is absolute LINK
This psect is absolute and cannot have a link address
specified in a -p option
Psect not loaded on 0xhexnum boundary LINK
This psect must be loaded on a specific boundary
Psect not relocated on 0xhexnum boundary LINK
This psect must be linked on a specific boundary
psect origin multiply defined LINK
This psect has its link address defined more than once
pushreg - bad reg CGEN
Internal error - contact HI-TECH
redundant & applied to array P1
An array type has an '&' operator applied to it. It has
been ignored since use of an array implicitly gives its
address
regused - bad arg to G CGEN
Internal error - contact HI-TECH
signatures do not matchLINK
An extern function has been declared with an incorrect
prototype. For example if an argument is declared as a
long in an extern declaration, but is really an int, a
signature mismatch will occur.
Page 96 HI-TECH C USER'S MANUAL
signed bitfields not supported P1
Only unsigned bitfields are supported
simple type required P1
An array or structure type cannot be used here
Sizeof yields 0 CGEN
The size of an object has evaluated to zero in a con-
text where this is illegal, e.g. incrementing a pointer
to a zero length object.
storage class illegal P1
A storage class may not be specified here
struct/union member expected P1
A structure or union member is required after a '. or
'->'
struct/union redefined P1
This structure or union has been defined twice
struct/union required P1
A structure or union identifier is required before a
'.'
Switch on long! CGEN
Switching on a long expression is not supported
symbol cannot be global LINK
Stack, filename or line number symbols cannot be global
Syntax error in checksum list LINK
The checksum list provided is invalid
token too long CPP
Shorten token (e.g. identifier)
too few arguments P1
The protype for this function lists more arguments than
have been supplied
too many arguments P1
More arguments have been supplied than listed in the
prototype for this function
Too many cases in switch CGEN,P1
There are too many cases in this switch
too many -D options CPP
Use fewer -D options
too many defines CPP
Reduce number of macro definitions
Too many errors CGEN
CGEN has given up because there were too many errors.
HI-TECH C USER'S MANUAL Page 97
too many formals CPP
Reduce number of parameters to this macro definition
Too many initializers CGEN
There are too many initializers for this object
Too many psects LINK
There are too many psects for the symbol table
Too many symbols LINK
There are too many symbols for the linker symbol table
too many -U options CPP
Use fewer -U options
too much defining CPP
Reduce number/size of macros
too much indirection P1
Too many '*'s in this declaration
too much pushback CPP
Simplify macro usage
type conflict P1
There is a conflict of types in this expression, e.g.
attempting to assign a structure to a simple type
type specifier reqd. for proto arg P1
A prototype argument must have a basic type
undefined control CPP
Check use of #
undefined enum tag P1
This enumerated type tag has not been defined
undefined identifier P1
This identifier has not been defined before use
undefined struct/union P1
The structure or union used has not been defined
undefined symbol LINK
A list of undefined symbols follows. If some of the
symbols should be in a library which was linked, it may
be caused by a library ordering problem. In this case
rebuild the library with the correct ordering or
specify the library more than once in the link command
unexpected EOF P1
End of file was encountered in the middle of a C con-
struct. This is commonly caused by omission of a clos-
ing '}' earlier in the program.
Unknown predicate CGEN
Internal error - contact HI-TECH
Page 98 HI-TECH C USER'S MANUAL
unknown psect LINK
The psect specifed in a -p option is not present in the
program. Check the spelling and check the case - upper
case does not match lower case
unreachable code P1
This section of code can never be executed as there is
no possible path to reach it
Unreasonable include nesting CPP
Reduce number of include files
Unreasonable matching depth CGEN
Internal error - contact HI-TECH
unterminated macro call CPP
Probably missing )
void function cannot return value P1
A function declared void cannot return a value
Write error (out of disk space?) LINK
Probably means the disk is full
HI-TECH C USER'S MANUAL Page 99
APPENDIX 2
Standard Library Functions
The functions accessible to user programs in the stan-
dard library libc.lib are listed below, by category with a
short comment, then alphabetically with a longer descrip-
tion. In the detailed description of each function, the
SYNOPSIS section describes the function in roughly the
manner in which the function would be declared in the source
file defining it. Where an include file is shown, this
implies that that include file must be included in any
source file using that function.
Where an include file is not provided, it will normally
be necessary for an extern declaration of the function to be
included in any source module using it, to ensure that the
type of the function is correct. For example, if the func-
tion lseek() was to be used, a declaration of the form
extern long lseek();
should be in either the source file itself or an include
file included in the source file. This ensures that the com-
piler knows that lseek() returns a long value and not the
default int.
Where reference is made to STDIO, this means the group
of functions under the heading STANDARD I/O below. These all
have one thing in common; they operate on pointers to a
defined data type called FILE. Such a pointer is often
referred to as a stream pointer. The concept of a stream is
central to these routines. Essentially a stream is a source
or sink of data bytes. To the operating system and library
routines this stream is featureless, i.e. no record struc-
ture is implied or assumed. Some routines do however recog-
nize end of line characters.
STANDARD I/O
fopen(name, mode) Open file for I/O
freopen(name, mode, stream) Re-open existing stream
fdopen(fd, mode) Associate a stream with a file
descriptor
fclose(stream) Close open file
fflush(stream) Flush buffered data
getc(stream) Read byte from stream
fgetc(stream) Same as getc
ungetc(c, stream) Push char back onto stream
putc(c, stream) Write byte to stream
fputc(c, stream) Same as putc()
getchar() Read byte from standard input
putchar(c) Write byte to standard output
getw(stream) Read word from stream
Page 100 HI-TECH C USER'S MANUAL
putw(w, stream) Write word to stream
gets(s) Read line from standard input
fgets(s, n, stream) Read string from stream
puts(s) Write string to standard output
fputs(s, stream) Write string to stream
fread(buf, size, cnt, stream) Binary read from stream
fwrite(buf, size, cnt, stream) Binary write to stream
fseek(stream, offs, wh) Random access positioning
ftell(stream) Current file read/write position
rewind(stream) Reposition file pointer to start
setvbuf(stream, buf, mode, size) Enable/disable buffering of stream
fprintf(stream, fmt, args) Formatted output on stream
printf(fmt, args) Formatted standard output
sprintf(buf, fmt, args) Formatted output to a string
vfprintf(stream, fmt, va_ptr) Formatted output on stream
vprintf(fmt, va_ptr) Formatted standard output
vsprintf(buf, fmt, va_ptr) Formatted output to a string
fscanf(stream, fmt, args) Formatted input from stream
scanf(fmt, args) Formatted standard input
sscanf(buf, fmt, va_ptr) Formatted input from a string
vfscanf(stream, fmt, va_ptr) Formatted input from stream
vscanf(fmt, args) Formatted standard input
vsscanf(buf, fmt, va_ptr) Formatted input from a string
feof(stream) True if stream at EOF
ferror(stream) True if error on stream
clrerr(stream) Reset error status on stream
fileno(stream) Return fd from stream
remove(name) Remove (delete) file
STRING HANDLING
atoi(s) Convert ASCII decimal to integer
atol(s) Convert ASCII decimal to long integer
atof(s) Convert ASCII decimal to float
xtoi(s) Convert ASCII hexadecimal to integer
memchr(s, c, n) Find char in memory block
memcmp(s1, s2, n) Compare n bytes of memory
memcpy(s1, s2, n) Copy n bytes from s2 to s1
memmove(s1, s2, n) Copy n bytes from s2 to s1
memset(s, c, n) Set n bytes at s to c
strcat(s1, s2) Append string 2 to string 1
strncat(s1, s2, n) Append at most n chars to string 1
strcmp(s1, s2) Compare strings
strncmp(s1, s2, n) Compare n bytes of strings
strcpy(s1, s2) Copy s2 to s1
strncpy(s1, s2, n) Copy at most n bytes of s2
strerror(errnum) Map errnum to an error message string
strlen(s) Length of string
strchr(s, c) Find char in string
strrchr(s, c) Find rightmost char in string
strspn(s1, s2) Length of s1 composed of chars from s2
strcspn(s1, s2) Length of s2 composed of chars not from s2
strstr(s1, s2) Locate the first occurence of s2 in s1
HI-TECH C USER'S MANUAL Page 101
LOW LEVEL I/O
open(name, mode) Open a file
close(fd) Close a file
creat(name) Create a file
dup(fd) Duplicate file descriptor
lseek(fd, offs, wh) Random access positioning
read(fd, buf, cnt) Read from file
rename(name1, name2) Rename file
unlink(name) Remove file from directory
write(fd, buf, cnt) Write to file
isatty(fd) True if fd refers to tty-like device
stat(name, buf) Get information about a file
chmod(name, mode) Set file attributes
CHARACTER TESTING
isalpha(c) True if c is a letter
isupper(c) Upper case letter
islower(c) Lower case letter
isdigit(c) Digit
isalnum(c) Alphnumeric character
isspace(c) Space, tab, newline, return or formfeed
ispunct(c) Punctuation character
isprint(c) Printable character
isgraph(c) Printable non-space character
iscntrl(c) Control character
isascii(c) Ascii character (0-127)
FLOATING POINT
cos(f) Cosine function
sin(f) Sine function
tan(f) Tangent function
acos(f) Arc cosine function
asin(f) Arc sine function
atan(f) Arc tangent function
exp(f) Exponential of f
log(f) Natural log of f
log10(f) Base 10 log of f
pow(x,y) X to the y'th power
sqrt(f) Square root
fabs(f) Floating absolute value
ceil(f) Smallest integral value >= f
floor(f) Largest integral value <= f
sinh(f) Hyperbolic sine
cosh(f) Hyperbolic cosine
tanh(f) Hyperbolic tangent
frexp(y, p) Split into mantissa and exponent
ldexp(y, i) Load new exponent
CONSOLE I/O
Page 102 HI-TECH C USER'S MANUAL
getch() Get single character
getche() Get single character with echo
putch(c) Put single character
ungetch(c) Push character back
kbhit() Test for key pressed
cgets(s) Get line from console
cputs(s) Put string to console
DATE AND TIME FUNCTIONS
time(p) Get current date/time
gmtime(p) Get broken down Universal time
localtime(p) Get broken down local time
asctime(t) Convert broken down time to ascii
ctime(p) Convert time to ascii
MISCELLANEOUS
execl(name, args) Execute another program
execv(name, argp) Execute another program
spawnl(name, arg, ...) Execute a subprogram
spawnv(name, argp) Execute a subprogram
system(s) Execute system command
atexit(func) Install func to be executed on termination
exit(status) Terminate execution
_exit(status) Terminate execution immediately
getuid() Get user id (CP/M)
setuid(uid) Set user id (CP/M)
chdir(s) Change directory (MS-DOS)
mkdir(s) Create directory (MS-DOS)
rmdir(s) Remove directory (MS-DOS)
getcwd(drive) Get current working directory (MS-DOS)
signal(sig, func) Set trap for interrupt condition
brk(addr) Set memory allocation
sbrk(incr) Adjust memory allocation
malloc(cnt) Dynamic memory allocation
free(ptr) Dynamic memory release
realloc(ptr, cnt) Dynamic memory reallocation
calloc(cnt, size) Dynamic memory allocation zeroed
perror(s) Print error message
qsort(base, nel, width, func) Quick sort
srand(seed) Initialize random number generator
rand() Get next random number
setjmp(buf) Setup for non-local goto
longjmp(buf, val) Non-local goto
_getargs(buf, name) Wild card expansion and i/o redirection
inp(port) Read port
outp(port, data) Write data to port
bdos(func, val) Perform bdos call (CP/M)
msdos(func, val, val, ...) Perform msdos call
msdoscx(func, val, val, ...) Alternate msdos call
intdos(ip, op) Execute DOS interrupt
HI-TECH C USER'S MANUAL Page 103
intdosx(ip, op, sp) Execute DOS interrupt
segread(sp) Get segment register values
int86(int, ip, op) Execute software interrupt
int86x(int, ip, op, sp) Execute software interrupt
bios(n, c) Call bios entry (CP/M)
ei() Enable interrupts
di() Disable interrupts
set_vector(vec, func) Set an interrupt vector
assert(e) Run time assertion
getenv(s) Get environment string (MS-DOS)
ACOS, ASIN, ATAN, ATAN2
SYNOPSIS
#include <math.h>
double acos(double f)
double asin(double f)
double atan(double f)
double atan2(double x, double y)
DESCRIPTION
These functions are the converse of the trignometric
functions cos, sin and tan. Acos and asin are undefined
for arguments whose absolute value is greater than 1.0.
The returned value is in radians, and always in the
range -pi/2 to +pi/2, except for cos(), which returns a
value in the range 0 to pi. Atan2() returns the
inverse tan of x/y but uses the signs of its arguments
to return a value in the range -pi to +pi.
SEE ALSO
sin, cos, tan
Page 104 HI-TECH C USER'S MANUAL
ATEXIT
SYNOPSIS
#include <stdlib.h>
int atexit(void (*func)(void));
DESCRIPTION
The atexit() function registers the function pointed to
by func, to be called without arguments at normal pro-
gram termination. Ateixt() returns zero if the regis-
tration succeeds, nonzero if it fails. On program ter-
mination, all functions registered by atexit() are
called, in the reverse order of their registration.
SEE ALSO
exit
ASCTIME
SYNOPSIS
#include <time.h>
char * asctime(time_t t)
DESCRIPTION
Asctime() takes the broken down time pointed to by its
argument, and returns a 26 character string describing
the current date and time in the format
Sun Sep 16 01:03:52 1973\n\0
Note the newline at the end of the string. The width of
each field in the string is fixed.
SEE ALSO
ctime, time, gmtime, localtime
HI-TECH C USER'S MANUAL Page 105
ASSERT
SYNOPSIS
#include <assert.h>
void assert(int e)
DESCRIPTION
This macro is used for debugging purposes; the basic
method of usage is to place assertions liberally
throughout your code at points where correct operation
of the code depends upon certain conditions being true
initially. An assert() may be used to ensure at run
time that that assumption holds. For example, the fol-
lowing statement asserts that the pointer tp is non-
null:
assert(tp);
If at run time the expression evaluates to false, the
program will abort with a message identifying the
source file and line number of the assertion, and the
expression used as an argument to it. A fuller discus-
sion of the uses of assert is impossible in limited
space, but it is closely linked to methods of proving
program correctness.
ATOF, ATOI, ATOL
SYNOPSIS
#include <math.h>
double atof(char * s)
int atoi(char * s)
#include <stdlib.h>
long atol(char * s)
DESCRIPTION
These routines convert a decimal number in the argument
string s into a double float, integer or long integer
respectively. Leading blanks are skipped over. In the
case of atof(), the number may be in scientific nota-
tion.
Page 106 HI-TECH C USER'S MANUAL
BDOS (CP/M only)
SYNOPSIS
#include <cpm.h>
char bdos(int func, int arg)
short bdoshl(int func, int arg)(CP/M-80 only)
DESCRIPTION
Bdos() calls the CP/M BDOS with func in register C (CL
for CP/M-86) and arg in register DE (DX). The return
value is the byte returned by the BDOS in register A
(AX). Bdoshl() is the same, except that the return
value is the value returned by the BDOS in HL. Con-
stant values for the various BDOS function values are
defined in cpm.h.
These functions should be avoided except in programs
which are not intended to be used on an operating sys-
tem other than CP/M. The standard I/O routines are to
be preferred, since they are portable.
SEE ALSO
bios, msdos
BIOS (CP/M only)
SYNOPSIS
#includ <cpm.h>
char bios(int n, int a1, int a2)
DESCRIPTION
This function will call the n'th bios entry point (cold
boot = 0, warm boot = 1, etc.) with register BC (CX)
set to the argument a1 and DE (DX) set to the argument
a2. The return value is the contents of register A (AX)
after the bios call. On CP/M-86, bdos function 50 is
used to perform the bios call. This function should
not be used unless unavoidable, since it is highly
non-portable. There is even no guarantee of portability
of bios calls between differing CP/M systems.
SEE ALSO
bdos
HI-TECH C USER'S MANUAL Page 107
CALLOC
SYNOPSIS
#include <stdlib.h>
char * calloc(size_t cnt, size_t size)
DESCRIPTION
Calloc() attempts to obtain a contiguous block of
dynamic memory which will hold cnt objects, each of
length size. The block is filled with zeroes. A
pointer to the block is returned, or 0 if the memory
could not be allocated.
SEE ALSO
brk, sbrk, malloc, free
CGETS, CPUTS
SYNOPSIS
#include <conio.h>
char * cgets(char * s)
void cputs(char * s)
DESCRIPTION
Cputs() will read one line of input from the console
into the buffer passed as an argument. It does so by
repeated calls to getche(). Cputs() writes its argu-
ment string to the console, outputting carriage returns
before each newline in the string. It calls putch()
repeatedly.
SEE ALSO
getch, getche, putch
Page 108 HI-TECH C USER'S MANUAL
CHDIR
SYNOPSIS
#include <sys.h>
int chdir(char * s)
DESCRIPTION
This function is availble only under MS-DOS. It changes
the current working directory to the path name supplied
as argument. This path name be be absolute, as in
A:\FRED, or relative, as in ..\SOURCES. A return value
of -1 indicates that the requested change could not be
performed.
SEE ALSO
mkdir, rmdir, getcwd
CHMOD
SYNOPSIS
#include <stat.h>
int chmod(char * name, int )
char * name;
int mode;
DESCRIPTION
This function changes the file attributes (or modes) of
the named file. The argument name may be any valid
file name. The mode argument may include all bits
defined in stat.h except those relating to the type of
the file, e.g. S_IFDIR. Note however that not all bits
may be changed under all operating systems, e.g. nei-
ther DOS nor CP/M permit a file to be made unreadable,
thus even if mode does not include S_IREAD the file
will still be readable (and stat() will still return
S_IREAD in flags).
SEE ALSO
stat, creat
HI-TECH C USER'S MANUAL Page 109
CLOSE
SYNOPSIS
#include <unixio.h>
int close(int fd)
DESCRIPTION
This routine closes the file associated with the file
descriptor fd, which will have been previously obtained
from a call to open(). Close() returns 0 for a success-
ful close, or -1 otherwise.
SEE ALSO
open, read, write, seek
CLRERR, CLREOF
SYNOPSIS
#include <stdio.h>
void clrerr(FILE * stream)
void clreof(FILE * stream)
DESCRIPTION
These are macros, defined in stdio.h, which reset the
error and end of file flags respectively for the speci-
fied stream. They should be used with care; the major
valid use is for clearing an EOF status on input from a
terminal-like device, where it may be valid to continue
to read after having seen an end-of-file indication.
SEE ALSO
fopen, fclose
Page 110 HI-TECH C USER'S MANUAL
COS
SYNOPSIS
#include <math.h>
double cos(double f)
DESCRIPTION
This function yields the cosine of its argument.
SEE ALSO
sin, tan, asin, acos, atan
COSH, SINH, TANH
SYNOPSIS
#include <math.h>
double cosh(double f)
double sinh(double f)
double tanh(double f)
DESCRIPTION
These functions implement the hyperbolic trig func-
tions.
HI-TECH C USER'S MANUAL Page 111
CREAT
SYNOPSIS
#include <stat.h>
int creat(char * name, int mode)
DESCRIPTION
This routine attempts to create the file named by name.
If the file exists and is writeable, it will be removed
and re-created. The return value is -1 if the create
failed, or a small non-negative number if it succeeded.
This number is a valuable token which must be used to
write to or close the file subsequently. Mode is used
to initialize the attributes of the created file. The
allowable bits are the same as for chmod(), but for
Unix compatibility it is recommended that a mode of
0666 or 0600 be used. Under CP/M the mode is ignored -
the only way to set a files attributes is via the
chmod() function.
SEE ALSO
open, close, read, write, seek, stat, chmod
CTIME
SYNOPSIS
#include <time.h>
char * ctime(time_t t)
DESCRIPTION
Ctime() converts the time in seconds pointed to by its
argument to a string of the same form as described for
asctime. Thus the following program prints the current
time and date:
#include <time.h>
main()
{
time_t t;
time(&t);
printf("%s", ctime(&t));
}
Page 112 HI-TECH C USER'S MANUAL
SEE ALSO
gmtime, localtime, asctime, time
DIV, LDIV
SYNOPSIS
#include <stdlib.h>
div_t div(int numer, int denom)
ldiv_t ldiv(long numer, long denom)
DESCRIPTION
The div() function computes the quotient and remainder
of the divison of numer by denom. The div() function
returns a structure of type div_t, containing both the
quotient and remainder. ldiv() is similar to div()
except it takes arguments of type long and returns a
structure of type ldiv_t. The types div_t and ldiv_t
are defined in <stdlib.h> as follows:
typedef struct {
intquot, rem;
} div_t;
typedef struct {
longquot, rem;
} ldiv_t;
HI-TECH C USER'S MANUAL Page 113
DI, EI
SYNOPSIS
void ei(void);
void di(void);
DESCRIPTION
Ei() and di() enable and disable interrupts respec-
tivly.
DUP
SYNOPSIS
#include <unixio.h>
int dup(int fd)
DESCRIPTION
Given a file descriptor, such as returned by open(),
this routine will return another file descriptor which
will refer to the same open file. -1 is returned if
the fd argument is a bad descriptor or does not refer
to an open file.
SEE ALSO
open, close, creat, read, write
Page 114 HI-TECH C USER'S MANUAL
EXECL, EXECV
SYNOPSIS
#include <sys.h>
int execl(char * name, pname, ...)
int execv(char * name, ppname)
DESCRIPTION
Execl() and execv() load and execute the program speci-
fied by the string name. Execl() takes the arguments
for the program from the zero-terminated list of string
arguments. Execv() is passed a pointer to an array of
strings. The array must be zero-terminated. If the
named program is found and can be read, the call does
not return. Thus any return from these routines may be
treated as an error.
SEE ALSO
spawnl, spawnv, system
EXIT
SYNOPSIS
#include <stdlib.h>
void exit(int status)
DESCRIPTION
This call will close all open files and exit from the
program. On CP/M, this means a return to CCP level.
Status will be stored in a known place for examination
by other programs. This is only useful if the program
executing was actually invoked by another program which
is trapping warm boots. The status value will be stored
on CP/M at 80H. This call will never return.
SEE ALSO
atexit
HI-TECH C USER'S MANUAL Page 115
_EXIT
SYNOPSIS
#include <stdlib.h>
void _exit(int status)
DESCRIPTION
This function will cause an immediate exit from the
program, without the normal flushing of stdio buffers
that is performed by exit().
SEE ALSO
exit
EXP, LOG, LOG10, POW
SYNOPSIS
#include <math.h>
double exp(double f)
double log(double f)
double log10(double f)
double pow(double x, y)
DESCRIPTION
Exp() returns the exponential function of its argument,
log() the natural logarithm of f, and log10() the loga-
rithm to base 10. Pow() returns the value of x raised
to the y'th power.
Page 116 HI-TECH C USER'S MANUAL
FABS, CEIL, FLOOR
SYNOPSIS
#include <math.h>
double fabs(double f)
double ceil(double f)
double floor(double f)
DESCRIPTION
These routines return respectively the absolute value
of f, the smallest integral value not less than f, and
the largest integral value not greater than f.
FCLOSE
SYNOPSIS
#include <stdio.h>
int fclose(FILE * stream)
DESCRIPTION
This routine closes the specified i/o stream. Stream
should be a token returned by a previous call to
fopen(). NULL is returned on a successful close, EOF
otherwise.
SEE ALSO
fopen, fread, fwrite
HI-TECH C USER'S MANUAL Page 117
FEOF, FERROR
SYNOPSIS
#include <stdio.h>
feof(FILE * stream)
ferror(FILE * stream)
DESCRIPTION
These macros test the status of the EOF and ERROR bits
respectively for the specified stream. Each will be
true if the corresponding flag is set. The macros are
defined in stdio.h. Stream must be a token returned by
a previous fopen() call.
SEE ALSO
fopen, fclose
FFLUSH
SYNOPSIS
#include <stdio.h>
int fflush(FILE * stream)
DESCRIPTION
Fflush() will output to the disk file or other device
currently open on the specified stream the contents of
the associated buffer. This is typically used for
flushing buffered standard output in interactive appli-
cations.
SEE ALSO
fopen, fclose
Page 118 HI-TECH C USER'S MANUAL
FGETC
SYNOPSIS
#include <stdio.h>
int fgetc(FILE * stream)
DESCRIPTION
Fgetc() returns the next character from the input
stream. If end-of-file is encountered EOF will be
returned instead. It is for this reason that the func-
tion is declared as int. The integer EOF is not a valid
byte, thus end-of-file is distinguishable from reading
a byte of all 1 bits from the file. Fgetc() is the
non-macro version of getc().
SEE ALSO
fopen, fclose, fputc, getc, putc
FGETS
SYNOPSIS
#include <stdio.h>
char * fgets(char * s, size_t n, char * stream)
DESCRIPTION
Fgets() places in the buffer s up to n-1 characters
from the input stream. If a newline is seen in the
input before the correct number of characters is read,
then fgets() will return immediately. The newline will
be left in the buffer. The buffer will be null ter-
minated in any case. A successful fgets() will return
its first argument; NULL is returned on end-of-file or
error.
HI-TECH C USER'S MANUAL Page 119
FILENO
SYNOPSIS
fileno(FILE * stream)
DESCRIPTION
Fileno() is a macro from stdio.h which yields the file
descriptor associated with stream. It is mainly used
when it is desired to perform some low-level operation
on a file opened as a stdio stream.
SEE ALSO
fopen, fclose, open, close
FOPEN
SYNOPSIS
#include <stdio.h>
FILE * fopen(char * name, char * mode);
DESCRIPTION
DESCRIPTION
Fopen() attempts to open file for reading or writing
(or both) according to the mode string supplied. The
mode string is interpreted as follows:
r The file is opend for reading if it exists. If the file
does not exist the call fails.
r+ If the file exists it is opened for reading and writ-
ing. If the file does not already exist the call fails.
w The file is created if it does not exist, or truncated
if it does. It is then opened for writing.
w+ The file is created if it does not already exist, or
truncated if it does. The file is opened for reading
and writing.
a The file is created if it does not already exist, and
opened for writing. All writes will be dynamically
forced to the end of file, thus this mode is known as
append mode.
a+ The file is created if it does not already exist, and
opened for reading and writing. All writes to the file
will be dynamically forced to the end of the file, i.e.
while any portion of the file may be read, all writes
Page 120 HI-TECH C USER'S MANUAL
will take place at the end of the file and will not
overwrite any existing data. Calling fseek() in an
attempt to write at any other place in the file will
not be effective.
The "b" modifier may be appended to any of the above
modes, e.g. "r+b" or "rb+" are equivalent. Adding the "b"
modifier will cause the file to be opened in binary rather
than ASCII mode. Opening in ASCII mode ensures that text
files are read in a manner compatible with the Unix-derived
conventions for C programs, i.e. that text files contain
lines delimited by newline characters. The special treat-
ment of read or written characters varies with the operating
system, but includes some or all of the following:
NEWLINE (LINE FEED)
Converted to carriage return, line feed on output.
RETURN
Ignored on input, inserted before NEWLINE on output.
CTRL-Z
Signals EOF on input, appended on fclose on output if
necessary on CP/M.
Opening a file in binary mode will allow each character
to be read just as written, but because the exact size
of a file is not known to CP/M, the file may contain
more bytes than were written to it. See open() for a
description of what constitutes a file name.
When using one of the read/write modes (with a '+'
character in the string), although they permits reading and
writing on the same stream, it is not possible to arbi-
trarily mix input and output calls to the same stream. At
any given time a stream opened with a "+" mode will be in
either an input or output state. The state may only be
changed when the associated buffer is empty, which is only
guaranteed immediately after a call to fflush() or one of
the file positioning functions fseek() or rewind(). The
buffer will also be empty after encountering EOF while read-
ing a binary stream, but it is recommended that an explicit
call to fflush() be used to ensure this situation. Thus
after reading from a stream you should call fflush() or
fseek() before attempting to write on that stream, and vice
versa.
SEE ALSO
fclose, fgetc, fputc, freopen
HI-TECH C USER'S MANUAL Page 121
FPRINTF
SYNOPSIS
#include <stdio.h>
fprintf(FILE * stream, char * fmt, ...);
vfprintf(FILE * stream, va_list va_arg);
DESCRIPTION
Fprintf() performs formatted printing on the specified
stream. Refer to printf() for the details of the avail-
able formats. Vfprintf() is similar to fprintf() but
takes a variable argument list pointer rather than a
list of arguments. See the description of va_start()
for more information on variable argument lists.
SEE ALSO
printf, fscanf, sscanf
FPUTC
SYNOPSIS
#include <stdio.h>
int fputc(int c, FILE * stream)
DESCRIPTION
The character c is written to the supplied stream. This
is the non-macro version of putc(). The character is
returned if it was successfully written, EOF is
returned otherwise. Note that "written to the stream"
may mean only placing the character in the buffer asso-
ciated with the stream.
SEE ALSO
putc, fgetc, fopen, fflush
Page 122 HI-TECH C USER'S MANUAL
FPUTS
SYNOPSIS
#include <stdio.h>
int fputs(char * s, FILE * stream)
DESCRIPTION
The null-terminated string s is written to the stream.
No newline is appended (cf. puts() ). The error return
is EOF.
SEE ALSO
puts, fgets, fopen, fclose
FREAD
SYNOPSIS
#include <stdio.h>
int fread(void * buf, size_t size, size_t cnt,
FILE * stream)
DESCRIPTION
Up to cnt objects, each of length size, are read into
memory at buf from the stream. The return value is the
number of objects read. If none is read, 0 will be
returned. Note that a return value less than cnt, but
greater than 0, may not represent an error (cf.
fwrite() ). No word alignment in the stream is assumed
or necessary. The read is done via successive getc()'s.
SEE ALSO
fwrite, fopen, fclose, getc
HI-TECH C USER'S MANUAL Page 123
FREE
SYNOPSIS
#include <stdlib.h>
void free(void * ptr)
DESCRIPTION
Free() deallocates the block of memory at ptr, which
must have been obtained from a call to malloc() or cal-
loc().
SEE ALSO
malloc, calloc
FREOPEN
SYNOPSIS
#include <stdio.h>
FILE * freopen(char * name, char * mode, FILE * stream)
DESCRIPTION
Freopen() closes the given stream (if open) then re-
opens the stream attached to the file described by
name. The mode of opening is given by mode. It either
returns the stream argument, if successful, or NULL if
not. See fopen() for more information.
SEE ALSO
fopen, fclose
Page 124 HI-TECH C USER'S MANUAL
FREXP, LDEXP
SYNOPSIS
#include <math.h>
double frexp(double f, int * p)
double ldexp(double f, int i)
DESCRIPTION
Frexp() breaks a floating point number into a normal-
ized fraction and an integral power of 2. The integer
is stored into the int object pointed to by p. Its
return value x is in the interval [0.5, 1.0) or zero,
and f equals x times 2 raised to the power stored in
*p. If f is zero, both parts of the result are zero.
Ldexp() performs the reverse operation; the integer i
is added to the exponent of the floating point f and
the resultant value returned.
FSCANF
SYNOPSIS
#include <stdio.h>
int fscanf(FILE * stream, char * fmt, ...)
DESCRIPTION
This routine performs formatted input from the speci-
fied stream. See scanf() for a full description of the
behaviour of the routine. Vfscanf() is similar to
fscanf() but takes a variable argument list pointer
rather than a list of arguments. See the description of
va_start() for more information on variable argument
lists.
SEE ALSO
scanf, sscanf, fopen, fclose
HI-TECH C USER'S MANUAL Page 125
FSEEK
SYNOPSIS
#include <stdio.h>
int fseek(FILE * stream, long offs, int wh)
DESCRIPTION
Fseek() positions the "file pointer" (i.e. a pointer to
the next character to be read or written) of the speci-
fied stream as follows:
_____________________________
|_wh|____resultant_location__|
| 0 | offs |
| 1 | offs+previous location|
| 2 | offs+length of file |
|___|________________________|
It should be noted that offs is a signed value. Thus
the 3 allowed modes give postioning relative to the
beginning of the file, the current file pointer and the
end of the file respectively. EOF is returned if the
positioning request could not be satisfied. Note how-
ever that positioning beyond the end of the file is
legal, but will result in an EOF indication if an
attempt is made to read data there. It is quite in
order to write data beyond the previous end of file.
Fseek() correctly accounts for any buffered data.
SEE ALSO
lseek, fopen, fclose
Page 126 HI-TECH C USER'S MANUAL
FTELL
SYNOPSIS
#include <stdio.h>
long ftell(FILE * stream)
DESCRIPTION
This function returns the current position of the con-
ceptual read/write pointer associated with stream.
This is the position relative to the beginning of the
file of the next byte to be read from or written to the
file.
SEE ALSO
fseek
FWRITE
SYNOPSIS
#include <stdio.h>
int fwrite(void * buf, size_t size, size_t cnt,
FILE * stream)
DESCRIPTION
Cnt objects of length size bytes will be written from
memory at buf, to the specified stream. The number of
whole objects written will be returned, or 0 if none
could be written. Any return value not equal to cnt
should be treated as an error (cf. fread() ).
SEE ALSO
fread, fopen, fclose
HI-TECH C USER'S MANUAL Page 127
_GETARGS
SYNOPSIS
#include <sys.h>
char ** _getargs(char * buf, char * name)
extern int _argc_;
DESCRIPTION
This routine performs I/O redirection (CP/M only) and
wild card expansion. Under MS-DOS I/O redirection is
performed by the operating system. It is called from
startup code to operate on the command line if the -R
option is used to the C command, but may also be called
by user-written code. If the buf argument is null, it
will read lines of text from standard input. If the
standard input is a terminal (usually the console) the
name argument will be written to the standard error
stream as a prompt. If the buf argument is not null, it
will be used as the source of the string to be pro-
cessed. The returned value is a pointer to an array of
strings, exactly as would be pointed to by the argv
argument to the main() function. The number of strings
in the array may be obtained from the global _argc_.
For example, a typical use of this function would be:
#include <sys.h>
main(argc, argv)
char ** argv;
{
extern char ** _getargs();
extern int _argc_;
if(argc == 1) {/* no arguments */
argv = _getargs(0, "myname");
argc = _argc_;
}
.
.
.
}
There will be one string in the array for each word in
the buffer processed. Quotes, either single (') or
double (") may be used to include white space in
"words". If any wild card characters (? or *) appear in
a non-quoted word, it will be expanded into a string of
words, one for each file matching the word. The usual
CP/M conventions are followed for this expansion. On
CP/M any occurence of the redirection characters > and
< outside quotes will be handled in the following
manner:
> name
will cause standard output to be redirected to the file
name.
Page 128 HI-TECH C USER'S MANUAL
< name
will cause standard input to be redirected from the
file name.
>> name
will cause standard output to append to file name.
White space is optional between the > or < character
and the file name, however it is an error for a
redirection character not to be followed by a file
name. It is also an error if a file cannot be opened
for input or created for output. An append redirection
(>>) will create the file if it does not exist. If the
source of text to be processed is standard input,
several lines may be supplied by ending each line
(except the last) with a backslash (\). This serves as
a continuation character. Note that the newline follow-
ing the backslash is ignored, and not treated as white
space.
GETC
SYNOPSIS
#include <stdio.h>
int getc(FILE * stream)
FILE * stream;
DESCRIPTION
One character is read from the specified stream and
returned. EOF will be returned on end-of-file or error.
This is the macro version of fgetc(), and is defined in
stdio.h.
HI-TECH C USER'S MANUAL Page 129
GETCH, GETCHE, UNGETCH, PUTCH
SYNOPSIS
#include <conio.h>
char getch(void)
char getche(void)
void putch(int c)
DESCRIPTION
Getch() reads a single character from the console key-
board and returns it without echoing. Getche() is
similar but does echo the character typed. Ungetch()
will push back one character such that the next call to
getch() or getche() will return that character.
Putch() outputs the character c to the console screen,
prepending a carriage return if the character is a new-
line.
SEE ALSO
cgets, cputs
GETCHAR
SYNOPSIS
#include <stdio.h>
int getchar(void)
DESCRIPTION
Getchar() is a getc(stdin) operation. It is a macro
defined in stdio.h. Note that under normal cir-
cumstances getchar() will NOT return unless a carriage
return has been typed on the console. To get a single
character immediately from the console, use the routine
getch().
SEE ALSO
getc, fgetc, freopen, fclose
Page 130 HI-TECH C USER'S MANUAL
GETCWD (MS-DOS only)
SYNOPSIS
#include <sys.h>
char * getcwd(int drive)
DESCRIPTION
Getcwd() returns the path name of the current working
directory on the specified drive, where drive == 0
represents the current drive, drive == 1 represents A:,
drive == 2 represents B: etc. The return value is a
pointer to a static area of memory which will be
overwritten on the next call to getcwd().
SEE ALSO
chdir
GETENV
SYNOPSIS
#include <stdlib.h>
char * getenv(char * s)
extern char ** environ;
DESCRIPTION
Getenv() will search the vector of environment strings
for one matching the argument supplied, and return the
value part of that environment string. For example, if
the environment contains the string
COMSPEC=A:\COMMAND.COM
then getenv("COMSPEC") will return A:\COMMAND.COM. The
global variable environ is a pointer to an array of
pointers to environment strings, terminated by a null
pointer. This array is initialized at startup time
under MS-DOS from the environment pointer supplied when
the program was executed. Under CP/M no such environ-
ment is supplied, so the first call to getenv() will
attempt to open a file in the current user number on
the current drive called ENVIRON. This file should con-
tain definitions for any environment variables desired
to be accessible to the program, e.g.
HITECH=0:C:
Each variable definition should be on a separate line,
consisting of the variable name (conventionally all in
upper case) followed without intervening white space by
HI-TECH C USER'S MANUAL Page 131
an equal sign ('=') then the value to be assigned to
that variable.
GETS
SYNOPSIS
#include <stdio.h>
char * gets(char * s)
DESCRIPTION
Gets() reads a line from standard input into the buffer
at s, deleting the newline (cf. fgets() ). The buffer
is null terminated. It returns its argument, or NULL on
end-of-file.
SEE ALSO
fgets, freopen
GETUID (CP/M only)
SYNOPSIS
#include <sys.h>
int getuid(void)
DESCRIPTION
Getuid() returns the current user number. On CP/M, the
current user number determines the user number associ-
ated with an opened or created file, unless overridden
by an explicit user number prefix in the file name.
SEE ALSO
setuid, open
Page 132 HI-TECH C USER'S MANUAL
GETW
SYNOPSIS
#include <stdio.h>
int getw(FILE * stream)
DESCRIPTION
Getw() returns one word (16 bits for the Z80 and 8086)
from the nominated stream. EOF is returned on end-of-
file, but since this is a perfectly good word, the
feof() macro should be used for testing for end-of-
file. When reading the word, no special alignment in
the file is necessary, as the read is done by two con-
secutive getc()'s. The byte ordering is however unde-
fined. The word read should in general have been writ-
ten by putw().
SEE ALSO
putw, getc, fopen, fclose
GMTIME, LOCALTIME
SYNOPSIS
#include <time.h>
struct tm * gmtime(time_t * t)
struct tm * localtime(time_t * t)
DESCRIPTION
These functions convert the time pointed to by t which
is in seconds since 00:00:00 on Jan 1, 1970, into a
broken down time stored in a structure as defined in
time.h. Gmtime() performs a straight conversion, while
localtime() takes into account the contents of the glo-
bal integer time_zone. This should contain the number
of minutes that the local time zone is WESTWARD of
Greenwich. Since there is no way under MS-DOS of actu-
ally pre-determining this value, by default localtime()
will return the same result as gmtime().
SEE ALSO
ctime, asctime, time
HI-TECH C USER'S MANUAL Page 133
INP, OUTP
SYNOPSIS
char inp(unsigned port)
void outp(unsigned, unsigned data)
DESCRIPTION
These routines read and write bytes to and from I/O
ports. Inp() returns the data byte read from the
specified port, and outp() outputs the data byte to the
specified port.
INT86, INT86X, INTDOS, INTDOSX
SYNOPSIS
#include <dos.h>
int int86(int intno, union REGS * inregs,
union REGS * outregs)
int int86x(int intno, union REGS inregs,
union REGS outregs, struct SREGS * segregs)
int intdos(union REGS * inregs, union REGS * outregs)
int intdosx(union REGS * inregs, union REGS * outregs,
struct SREGS * segregs)
DESCRIPTION
These functions allow calling of software interrupts
from C programs. Int86() and int86x() execute the
software interrupt specified by intno while intdos()
and intdosx() execute interrupt 21(hex), which is the
MS-DOS system call interrupt. The inregs pointer
should point to a union containing values for each of
the general purpose registers to be set when executing
the interrupt, and the values of the registers on
return are copied into the union pointed to by outregs.
The x versions of the calls also take a pointer to a
union defining the segment register values to be set on
execution of the interrupt, though only ES and DS are
actually set from this structure.
SEE ALSO
segread
Page 134 HI-TECH C USER'S MANUAL
ISALNUM, ISALPHA, ISDIGIT, ISLOWER et. al.
SYNOPSIS
#include <ctype.h>
isalnum(char c)
isalpha(char c)
isascii(char c)
iscntrl(char c)
isdigit(char c)
islower(char c)
isprint(char c)
isgraph(char c)
ispunct(char c)
isspace(char c)
isupper(char c)
char c;
DESCRIPTION
These macros, defined in ctype.h, test the supplied
character for membership in one of several overlapping
groups of characters. Note that all except isascii are
defined for c iff isascii(c) is true.
isalnum(c) c is alphanumeric
isalpha(c) c is in A-Z or a-z
isascii(c) c is a 7 bit ascii character
iscntrl(c) c is a control character
isdigit(c) c is a decimal digit
islower(c) c is in a-z
isprint(c) c is a printing char
isgraph(c) c is a non-space printable character
ispunct(c) c is not alphanumeric
isspace(c) c is a space, tab or newline
isupper(c) c is in A-Z
isxdigit(c) c is in 0-9 or a-f or A-F
SEE ALSO
toupper, tolower, toascii
HI-TECH C USER'S MANUAL Page 135
ISATTY
SYNOPSIS
#include <unixio.h>
int isatty(int fd)
DESCRIPTION
This tests the type of the file associated with fd. It
returns true if the file is attached to a tty-like dev-
ice. This would normally be used for testing if stan-
dard input is coming from a file or the console. For
testing STDIO streams, use isatty(fileno(stream)).
KBHIT
SYNOPSIS
#include <conio.h>
int kbhit(void)
DESCRIPTION
This function returns 1 if a character has been pressed
on the console keyboard, 0 otherwise. Normally the
character would then be read via getch().
SEE ALSO
getch, getche
Page 136 HI-TECH C USER'S MANUAL
LONGJMP
SYNOPSIS
#include <setjmp.h>
void longjmp(jmp_buf buf, int val)
DESCRIPTION
Longjmp(), in conjunction with setjmp(), provides a
mechanism for non-local gotos. To use this facility,
setjmp() should be called with a jmp_buf argument in
some outer level function. The call from setjmp() will
return 0. To return to this level of execution,
lonjmp() may be called with the same jmp_buf argument
from an inner level of execution. Note however that the
function which called setjmp() must still be active
when longjmp() is called. Breach of this rule will
cause disaster, due to the use of a stack containing
invalid data. The val argument to longjmp() will be the
value apparently returned from the setjmp(). This
should normally be non-zero, to distinguish it from the
genuine setjmp() call. For example:
#include <setjmp.h>
static jmp_buf jb_err;
main()
{
if(setjmp(jb_err)) {
printf("An error occured0);
exit(1);
}
a_func();
}
a_func()
{
if(do_whatever() != 0)
longjmp(jb_err, 1);
if(do_something_else() != 0)
longjmp(jb_err, 2);
}
The calls to longjmp() above will never return; rather
the call to setjmp() will appear to return, but with a
return value equal to the argument supplied to
longjmp().
SEE ALSO
setjmp
HI-TECH C USER'S MANUAL Page 137
LSEEK
SYNOPSIS
#include <unixio.h>
long lseek(int fd, long offs, int wh)
DESCRIPTION
This function operates in an analogous manner to
fseek(), however it does so on unbuffered low-level i/o
file descriptors, rather than on STDIO streams. It also
returns the resulting pointer location. Thus lseek(fd,
0L, 1) returns the current pointer location without
moving it. -1 is returned on error.
SEE ALSO
open, close, read, write
MALLOC
SYNOPSIS
#include <stdlib.h>
void * malloc(size_t cnt)
DESCRIPTION
Malloc() attempts to allocate cnt bytes of memory from
the "heap", the dynamic memory allocation area. If suc-
cessful, it returns a pointer to the block, otherwise 0
is returned. The memory so allocated may be freed with
free(), or changed in size via realloc(). Malloc()
calls sbrk() to obtain memory, and is in turn called by
calloc(). Malloc() does not clear the memory it
obtains.
SEE ALSO
calloc, free, realloc
Page 138 HI-TECH C USER'S MANUAL
MEMSET, MEMCPY, MEMCMP, MEMMOVE
SYNOPSIS
#include <string.h>
void memset(void s, char c, size_t n)
void * memcpy(void * d, void * s, size_t n)
int memcmp(void * s1, void * s2, size_t n)
void * memmove(void * s1, void * s2, size_t n)
void * memchr(void * s, int c, size_t n)
DESCRIPTION
Memset() initializes n bytes of memory starting at the
location pointed to by s with the character c. Memcpy()
copies n bytes of memory starting from the location
pointed to by s to the block of memory pointed to by d.
The result of copying overlapping blocks is undefined.
Memcmp() compares two blocks of memory, of length n,
and returns a signed value similar to strncmp(). Unlike
strncmp() the comparision does not stop on a null char-
acter. The ascii collating sequence is used for the
comparision, but the effect of including non-ascii
characters in the memory blocks on the sense of the
return value is indeterminate. Memmove() is similar to
memcpy() except copying of overlapping blocks is han-
dled correctly. The memchr() function locates the first
occurence of c (converted to unsigned char) in the ini-
tial n characters of the object pointed to by s.
SEE ALSO
strncpy, strncmp, strchr
HI-TECH C USER'S MANUAL Page 139
MKDIR, RMDIR
SYNOPSIS
#include <sys.h>
int mkdir(char * s)
int rmdir(char * s)
DESCRIPTION
These functions allow the creation (mkdir()) and dele-
tion (rmdir()) of sub-directories under the MS-DOS
operating system. The argument s may be an arbitrary
pathname, and the return value will be -1 if the crea-
tion or removal was unsuccessful.
SEE ALSO
chdir
MSDOS, MSDOSCX
SYNOPSIS
#include <dos.h>
long msdos(int ax, int dx, int cx,
int bx, int si, int di)
long msdoscx(int ax, int dx, int cx,
int bx, int si, int di)
DESCRIPTION
These functions allow direct access to MS-DOS system
calls. The arguments will be placed in the registers
implied by their names, while the return value will be
the contents of AX and DX (for msdos()) or the contents
of DX and CX (for msdoscx()). Only as many arguments
as necessary need be supplied, e.g. if only AH and DX
need have specified valued, then only 2 argument would
be required. The following piece of code outputs a
form-feed to the printer.
msdos(0x500, '\f');
Note that the system call number (in this case 5) must
be multiplied by 0x100 since MS-DOS expects the call
number in AH, the high byte of AX.
SEE ALSO
intdos, intdosx, int86, int86x
Page 140 HI-TECH C USER'S MANUAL
OPEN
SYNOPSIS
#include <unixio.h>
int open(char * name, int mode)
DESCRIPTION
Open() is the fundamental means of opening files for
reading and writing. The file specified by name is
sought, and if found is opened for reading, writing or
both. Mode is encoded as follows:
Mode Meaning
0 Open for reading only
1 Open for writing only
2 Open for both reading and writing
The file must already exist - if it does not, creat()
should be used to create it. On a successful open, a
file descriptor is returned. This is a non-negative
integer which may be used to refer to the open file
subsequently. If the open fails, -1 is returned. The
syntax of a CP/M filename is:
[uid:][drive:]name.type
where uid is a decimal number 0 to 15, drive is a
letter A to P or a to p, name is 1 to 8 characters and
type is 0 to 3 characters. Though there are few
inherent restrictions on the characters in the name and
type, it is recommended that they be restricted to the
alphanumerics and standard printing characters. Use of
strange characters may cause problems in accessing
and/or deleting the file.
One or both of uid: and drive: may be omitted; if both
are supplied, the uid: must come first. Note that the [
and ] are meta-symbols only. Some examples are:
fred.dat
file.c
0:xyz.com
0:a:file1.p
a:file2.
If the uid: is omitted, the file will be sought with
uid equal to the current user number, as returned by
getuid(). If drive: is omitted, the file will be sought
on the currently selected drive. The following special
file names are recognized:
HI-TECH C USER'S MANUAL Page 141
lst: Accesses the list device - write only
pun: Accesses the punch device - write only
rdr: Accesses the reader device - read only
con: Accesses the system console - read/write
File names may be in any case - they are converted to
upper case during processing of the name.
MS-DOS filenames may be any valid MS-DOS 2.xx filename,
e.g.
fred.nrk
A:\HITECH\STDIO.H
The special device names (e.g. CON, LST) are also
recognized. These do not require (and should not have)
a trailing colon.
SEE ALSO
close, fopen, fclose, read, write, creat
PERROR
SYNOPSIS
#include <stdio.h>
void perror(char * s)
DESCRIPTION
This routine will print on the stderr stream the argu-
ment s, followed by a descriptive message detailing the
last error returned from an open, close read or write
call. Unfortunately CP/M does not provide definitive
information relating to the error, except in the case
of a random read or write. Thus this routine is of lim-
ited usefulness under CP/M. MS-DOS provides much more
information however, and use of perror() after MS-DOS
file handling calls will certainly give useful diagnos-
tics.
SEE ALSO
open, close, read, write
Page 142 HI-TECH C USER'S MANUAL
PRINTF, VPRINTF
SYNOPSIS
#include <stdio.h>
int printf(char * fmt, ...)
int vprintf(char * fmt, va_list va_arg)
DESCRIPTION
Printf() is a formatted output routine, operating on
stdout. There are corresponding routines operating on a
given stream (fprintf()) or into a string buffer
(sprintf()). Printf() is passed a format string, fol-
lowed by a list of zero or more arguments. In the for-
mat string are conversion specifications, each of which
is used to print out one of the argument list values.
Each conversion specification is of the form %m.nc
where the percent symbol % introduces a conversion,
followed by an optional width specification m. n is an
optional precision specification (introduced by the
dot) and c is a letter specifying the type of the
conversion. A minus sign ('-') preceding m indicates
left rather than right adjustment of the converted
value in the field. Where the field width is larger
than required for the conversion, blank padding is per-
formed at the left or right as specified. Where right
adjustment of a numeric conversion is specified, and
the first digit of m is 0, then padding will be per-
formed with zeroes rather than blanks.
If the character * is used in place of a decimal con-
stant, e.g. in the format %*d, then one integer argu-
ment will be taken from the list to provide that value.
The types of conversion are:
f Floating point - m is the total width and n is the
number of digits after the decimal point. If n is
omitted it defaults to 6.
e Print the corresponding argument in scientific nota-
tion. Otherwise similar to f.
g Use e or f format, whichever gives maximum precision in
minimum width.
o x X u d
Integer conversion - in radices 8, 16, 10 and 10
respectively. The conversion is signed in the case of
d, unsigned otherwise. The precision value is the total
number of digits to print, and may be used to force
leading zeroes. E.g. %8.4x will print at least 4 hex
digits in an 8 wide field. Preceding the key letter
with an l indicates that the value argument is a long
integer or unsigned value. The letter X prints out
hexadecimal numbers using the upper case letters A-F
rather than a-f as would be printed when using x.
HI-TECH C USER'S MANUAL Page 143
s Print a string - the value argument is assumed to be a
character pointer. At most n characters from the string
will be printed, in a field m characters wide.
c The argument is assumed to be a single character and is
printed literally.
Any other characters used as conversion specifications
will be printed. Thus %% will produce a single percent
sign. Some examples:
printf("Total = %4d%%", 23)
yields 'Total =23%'
printf("Size is %lx" , size)
where size is a long, prints size
as hexadecimal.
printf("Name = %.8s", "a1234567890")
yields 'Name = a1234567'
printf("xx%*d", 3, 4)
yields 'xx 4'
Printf returns EOF on error, 0 otherwise. Vprintf() is
similar to printf() but takes a variable argument list
pointer rather than a list of arguments. See the
description of va_start() for more information on vari-
able argument lists.
SEE ALSO
fprintf, sprintf
Page 144 HI-TECH C USER'S MANUAL
PUTC
SYNOPSIS
#include <stdio.h>
int putc(int c, FILE * stream)
DESCRIPTION
Putc() is the macro version of fputc() and is defined
in stdio.h. See fputc() for a description of its
behaviour.
SEE ALSO
fputc, getc, fopen, fclose
PUTCHAR
SYNOPSIS
#include <stdio.h>
int putchar(int c)
DESCRIPTION
Putchar() is a putc() operation on stdout, defined in
stdio.h.
SEE ALSO
putc, getc, freopen, fclose
HI-TECH C USER'S MANUAL Page 145
PUTS
SYNOPSIS
#include <stdio.h>
int puts(char * s)
DESCRIPTION
Puts() writes the string s to the stdout stream,
appending a newline. The null terminating the string is
not copied. EOF is returned on error.
SEE ALSO
fputs, gets, freopen, fclose
PUTW
SYNOPSIS
#include <stdio.h>
int putw(int w, FILE * stream)
DESCRIPTION
Putw() copies the word w to the given stream. It
returns w, except on error, in which case EOF is
returned. Since this is a good integer, ferror() should
be used to check for errors.
SEE ALSO
getw, fopen, fclose
Page 146 HI-TECH C USER'S MANUAL
QSORT
SYNOPSIS
#include <stdlib.h>
void qsort(void * base, size_t nel,
size_t width, int (*func)())
DESCRIPTION
Qsort() is an implementation of the quicksort algo-
rithm. It sorts an array of nel items, each of length
width bytes, located contiguously in memory at base.
Func is a pointer to a function used by qsort() to com-
pare items. It calls func with pointers to two items to
be compared. If the first item is considered to be
greater than, equal to or less than the second then
func() should return a value greater than zero, equal
to zero or less than zero respectively.
static short array[100];
#define SIZE sizeof array/sizeof array[0]
a_func(p1, p2)
short * p1, * p2;
{
return *p1 - *p2;
}
sort_em()
{
qsort(array, SIZE,
sizeof array[0], a_func);
}
This will sort the array into ascending values. Note
the use of sizeof to make the code independent of the
size of a short, or the number of elements in the
array.
HI-TECH C USER'S MANUAL Page 147
RAND
SYNOPSIS
#include <stdlib.h>
int rand(void)
DESCRIPTION
Rand() is a pseudo-random number generator. It returns
an integer in the range 0 to 32767, which changes in a
pseudo-random fashion on each call.
SEE ALSO
srand
READ
SYNOPSIS
#include <unixio.h>
int read(int fd, void * buf, size_t cnt)
DESCRIPTION
Read() will read from the file associated with fd up to
cnt bytes into a buffer located at buf. It returns the
number of bytes actually read. A zero return indicates
end-of-file. A negative return indicates error. Fd
should have been obtained from a previous call to
open(). It is possible for read() to return less bytes
than requested, e.g. when reading from the console, in
which case read() will read one line of input.
SEE ALSO
open, close, write
Page 148 HI-TECH C USER'S MANUAL
REALLOC
SYNOPSIS
void * realloc(void * ptr, size_t cnt)
DESCRIPTION
Realloc() frees the block of memory at ptr, which
should have been obtained by a previous call to mal-
loc(), calloc() or realloc(), then attempts to allocate
cnt bytes of dynamic memory, and if successful copies
the contents of the block of memory located at ptr into
the new block. At most, realloc() will copy the number
of bytes which were in the old block, but if the new
block is smaller, will only copy cnt bytes. If the
block could not be allocated, 0 is returned.
SEE ALSO
malloc, calloc, realloc
REMOVE
SYNOPSIS
#include <stdio.h>
int remove(char * s)
DESCRIPTION
Remove() will attempt to remove the file named by the
argument s from the directory. A return value of -1
indicates that the attempt failed.
SEE ALSO
unlink
HI-TECH C USER'S MANUAL Page 149
RENAME
SYNOPSIS
#include <stdio.h>
int rename(char * name1, char * name2)
DESCRIPTION
The file named by name1 will be renamed to name2. -1
will be returned if the rename was not successful. Note
that renames across user numbers or drives are not per-
mitted.
SEE ALSO
open, close, unlink
REWIND
SYNOPSIS
#include <stdio.h>
int rewind(FILE * stream)
DESCRIPTION
This function will attempt to re-position the
read/write pointer of the nominated stream to the
beginning of the file. A return value of -1 indicates
that the attempt was not successful, perhaps because
the stream is associated with a non-random access file
such as a character device.
SEE ALSO
fseek, ftell
Page 150 HI-TECH C USER'S MANUAL
SBRK
SYNOPSIS
char * sbrk(int incr)
DESCRIPTION
Sbrk() increments the current highest memory location
allocated to the program by incr bytes. It returns a
pointer to the previous highest location. Thus sbrk(0)
returns a pointer to the current highest location,
without altering its value. If there is insufficient
memory to satisfy the request, -1 is returned.
SEE ALSO
brk, malloc, calloc, realloc, free
SCANF
SYNOPSIS
#include <stdio.h>
int scanf(char * fmt, ...)
int vscanf(char *, va_list ap);
DESCRIPTION
Scanf() performs formatted input ("de-editing") from
the stdin stream. Similar functions are available for
streams in general, and for strings. The function
vscanf() is similar, but takes a pointer to an argument
list rather than a series of additional arguments. This
pointer should have been initialized with va_start().
The input conversions are performed according to the
fmt string; in general a character in the format string
must match a character in the input; however a space
character in the format string will match zero or more
"white space" characters in the input, i.e. spaces,
tabs or newlines. A conversion specification takes the
form of the character %, optionally followed by an
assignment suppression character ('*'), optionally fol-
lowed by a numerical maximum field width, followed by a
conversion specification character. Each conversion
specification, unless it incorporates the assignment
suppression character, will assign a value to the vari-
able pointed at by the next argument. Thus if there are
two conversion specifications in the fmt string, there
should be two additional pointer arguments. The
conversion characters are as follows:
o x d
Skip white space, then convert a number in base 8, 16
or 10 radix respectively. If a field width was
HI-TECH C USER'S MANUAL Page 151
supplied, take at most that many characters from the
input. A leading minus sign will be recognized.
f Skip white space, then convert a floating number in
either conventional or scientific notation. The field
width applies as above.
s Skip white space, then copy a maximal length sequence
of non-white-space characters. The pointer argument
must be a pointer to char. The field width will limit
the number of characters copied. The resultant string
will be null-terminated.
c Copy the next character from the input. The pointer
argument is assumed to be a pointer to char. If a field
width is specified, then copy that many characters.
This differs from the s format in that white space does
not terminate the character sequence.
The conversion characters o, x, u, d and f may be pre-
ceded by an l to indicate that the corresponding
pointer argument is a pointer to long or double as
appropriate. A preceding h will indicate that the
pointer argument is a pointer to short rather than int.
Scanf() returns the number of successful conversions;
EOF is returned if end-of-file was seen before any
conversions were performed. Some examples are:
scanf("%d %s", &a, &s)
with input "12s"
will assign 12 to a, and "s" to s.
scanf("%4cd %lf", &c, &f)
with input " abcd -3.5"
will assign " abc" to c, and -3.5 to f.
SEE ALSO
fscanf, sscanf, printf, va_arg
Page 152 HI-TECH C USER'S MANUAL
SEGREAD
SYNOPSIS
#include <dos.h>
int segread(struct SREGS * segregs)
DESCRIPTION
Segread() copies the values of the segment registers
into the structure pointed to by segregs.
SEE ALSO
int86, int86x, intdos, intdosx
SETJMP
SYNOPSIS
#include <setjmp.h>
int setjmp(jmp_buf buf)
DESCRIPTION
Setjmp() is used with longjmp() for non-local gotos.
See longjmp() for further information.
SEE ALSO
longjmp
HI-TECH C USER'S MANUAL Page 153
SETUID (CP/M only)
SYNOPSIS
#include <sys.h>
void setuid(int uid)
DESCRIPTION
Setuid() will set the current user number to uid. Uid
should be a number in the range 0-15.
SEE ALSO
getuid
SETVBUF, SETBUF
SYNOPSIS
#include <stdio.h>
int setvbuf(FILE * stream, char * buf,
int mode, size_t size);
void setbuf(FILE * stream, char * buf)
DESCRIPTION
The setvbuf() function allows the buffering behaviour
of a STDIO stream to be altered. It supersedes the
function setbuf() which is retained for backwards com-
patibility. The arguments to setvbuf() are as follows:
stream designates the STDIO stream to be affected; buf
is a pointer to a buffer which will be used for all
subsequent I/O operations on this stream. If buf is
null, then the routine will allocate a buffer from the
heap if necessary, of size BUFSIZ as defined in
<stdio.h>. mode may take the values _IONBF, to turn
buffering off completely, _IOFBF, for full buffering,
or _IOLBF for line buffering. Full buffering means that
the associated buffer will only be flushed when full,
while line buffering means that the buffer will be
flushed at the end of each line or when input is
requested from another STDIO stream. size is the size
of the buffer supplied. For example:
setvbuf(stdout, my_buf, _IOLBF, sizeof my_buf);
If a buffer is supplied by the caller, that buffer will
remain associated with that stream even overfclose(),
fopen() calls until another setvbuf() changes it.
Page 154 HI-TECH C USER'S MANUAL
SEE ALSO
fopen, freopen, fclose
SET_VECTOR
SYNOPSIS
#include <intrpt.h>
typedef interrupt void (*isr)();
isr set_vector(isr * vector, isr func);
DESCRIPTION
This routine allows an interrupt vector to be initial-
ized. The first argument should be the address of the
interrupt vector (not the vector number but the actual
address) cast to a pointer to isr, which is a typedef'd
pointer to an interrupt function. The second argument
should be the function which you want the interrupt
vector to point to. This must be declared using the
interrupt type qualifier. The return value of
set_vector() is the previous contents of the vector.
SEE ALSO
di(), ei()
HI-TECH C USER'S MANUAL Page 155
SIGNAL
SYNOPSIS
#include <signal.h>
void (* signal)(int sig, void (*func)());
DESCRIPTION
Signal() provides a mechanism for catching control-C's
(ctrl-BREAK for MS-DOS) typed on the console during
I/O. Under CP/M the console is polled whenever an I/O
call is performed, while for MS-DOS the polling depends
on the setting of the BREAK command. If a control-C is
detected certain action will be performed. The default
action is to exit summarily; this may be modified with
signal(). The sig argument to signal may at the present
time be only SIGINT, signifying an interrupt condition.
The func argument may be one of SIG_DFL, representing
the default action, SIG_IGN, to ignore control-C's com-
pletely, or the address of a function which will be
called with one argument, the number of the signal
caught, when a control-C is seen. As the only signal
supported is SIGINT, this will always be the value of
the argument to the called function.
SEE ALSO
exit
SIN
SYNOPSIS
#include <math.h>
double sin(double f);
DESCRIPTION
This function returns the sine function of its argu-
ment.
SEE ALSO
cos, tan, asin, acos, atan
Page 156 HI-TECH C USER'S MANUAL
SPAWNL, SPAWNV, SPAWNVE
SYNOPSIS
int spawnl(char * n, char * argv0, ...);
int spawnv(cahr * n, char ** v)
int spawnve(char * n, char ** v, char ** e)
DESCRIPTION
These functions will load and execute a sub-program,
named by the argument n. The calling conventions are
similar to the functions execl() and execv(), the
difference being that the spawn functions return to the
calling program after termination of the sub-program,
while the exec functions return only if the program
could not be executed. Spawnve() takes an environment
list in the same format as the argument list which will
be supplied to the executed program as its environment.
SEE ALSO
execl, execv
SPRINTF
SYNOPSIS
#include <stdio.h>
int sprintf(char * buf, char * fmt, ...);
int vsprintf(char * buf, char * fmt, va_list ap);
DESCRIPTION
Sprintf() operates in a similar fashion to printf(),
except that instead of placing the converted output on
the stdout stream, the characters are placed in the
buffer at buf. The resultant string will be null-
terminated, and the number of characters in the buffer
will be returned. Vsprintf takes an argument pointer
rather than a list of arguments.
SEE ALSO
printf, fprintf, sscanf
HI-TECH C USER'S MANUAL Page 157
SQRT
SYNOPSIS
#include <math.h>
double sqrt(double f)
DESCRIPTION
Sqrt() implements a square root function using Newton's
approximation.
SEE ALSO
exp
SSCANF
SYNOPSIS
#include <stdio.h>
int sscanf(char * buf, char * fmt, ...);
int vsscanf(char * buf, char * fmt, va_list ap);
DESCRIPTION
Sscanf() operates in a similar manner to scanf(),
except that instead of the conversions being taken from
stdin, they are taken from the string at buf.
SEE ALSO
scanf, fscanf, sprintf
Page 158 HI-TECH C USER'S MANUAL
SRAND
SYNOPSIS
#include <stdlib.h>
void srand(int seed)
DESCRIPTION
Srand() initializes the random number generator
accessed by rand() with the given seed. This provides a
mechanism for varying the starting point of the
pseudo-random sequence yielded by rand(). On the z80, a
good place to get a truly random seed is from the
refresh register. Otherwise timing a response from the
console will do.
SEE ALSO
rand
STAT
SYNOPSIS
#include <stat.h>
int stat(char * name, struct stat * statbuf)
DESCRIPTION
This routine returns information about the file by
name. The information returned is operating system
dependent, but may include file attributes (e.g. read
only), file size in bytes, and file modification and/or
access times. The argument name should be the name of
the file, and may include path names under DOS, user
numbers under CP/M, etc. The argument statbuf should
be the address of a structure as defined in stat.h
which will be filled in with the information about the
file. The structure of struct stat is as follows:
struct stat
{
short st_mode; /* flags */
long st_atime; /* access time */
long st_mtime; /* modification time */
long st_size; /* file size */
};
The access and modification times (under DOS these
are both set to the modification time) are in
seconds since 00:00:00 Jan 1 1970. The function
ctime() may be used to convert this to a readable
HI-TECH C USER'S MANUAL Page 159
value. The file size is self explanatory. The
flag bits are as follows:
Flag Meaning
____________________________________
S_IFMT mask for file type
S_IFDIR file is a directory
S_IFREG file is a regular file
S_IREAD file is readable
S_IWRITE file is writeable
S_IEXEC file is executable
S_HIDDEN file is hidden
S_SYSTEM file is marked system
S_ARCHIVE file has been written to
Stat returns 0 on success, -1 on failure, e.g. if
the file could not be found.
SEE ALSO
ctime, creat, chmod
STRCAT, STRCMP, STRCPY, STRLEN et. al.
SYNOPSIS
#include <string.h>
char * strcat(char * s1, char * s2);
int strcmp(char * s1, char * s2);
char * strcpy(char * s1, char * s2);
int strlen(char * s);
char * strncat(char * s1, char * s2, size_t n);
int strncmp(char * s1, char * s2, size_t n);
char * strncpy(char * s1, char * s2, size_t n);
DESCRIPTION
These functions provide operations on null-terminated
strings. Strcat() appends the string s2 to the end of
the string s1. The string at s1 will be null ter-
minated. Needless to say the buffer at s1 must be big
enough. Strcmp() compares the two strings and returns a
number greater than 0, 0 or a number less than 0
according to whether s1 is greater than, equal to or
less than s2. The comparision is via the ascii collat-
ing order, with the first character the most signifi-
cant. Strcpy() copies s2 into the buffer at s1, null
terminating it. Strlen() returns the length of s1, not
including the terminating null. Strncat(), strncmp()
and strncpy() will catenate, compare and copy s2 and s1
in the same manner as their similarly named counter-
parts above, but involving at most n characters. For
strncpy(), the resulting string may not be null ter-
minated.
Page 160 HI-TECH C USER'S MANUAL
STRCHR, STRRCHR
SYNOPSIS
#include <string.h>
char * strchr(char * s, int c)
char * strrchr(char * s, int c)
DESCRIPTION
These functions locate an instance of the character c
in the string s. In the case of strchr() a pointer will
be returned to the first instance of the character
found be searching from the beginning of the string,
while strrchr() searches backwards from the end of the
string. A null pointer is returned if the character
does not exist in the string.
SEE ALSO
SYSTEM
SYNOPSIS
#include <sys.h>
int system(char * s)
DESCRIPTION
When executed under MS-DOS system() will pass the argu-
ment string to the command processor, located via the
environment string COMSPEC, for execution. The exit
status of the command processor will be returned from
the call to system(). For example, to set the baud
rate on the serial port on an MS-DOS machine:
system("MODE COM1:96,N,8,1,P");
This function will not work on CP/M-86 since it does
not have an invokable command interpreter. Under Con-
current CP/M the CLI system call is used.
SEE ALSO
spawnl, spawnv
HI-TECH C USER'S MANUAL Page 161
TAN
SYNOPSIS
#include <math.h>
double tan(double f);
DESCRIPTION
This is the tangent function.
SEE ALSO
sin, cos, asin, acos, atan
TIME
SYNOPSIS
#include <time.h>
time_t time(time_t * t)
DESCRIPTION
This function returns the current time in seconds since
00:00:00 on Jan 1, 1970. If the argument t is non-
null, the same value is stored into the object pointed
to by t. The accuracy of this function is naturally
dependent on the operating system having the correct
time. This function does not work under CP/M-86 or CP/M
2.2 but does work under Concurrent-CP/M and CP/M+.
SEE ALSO
ctime, gmtime, localtime, asctime
Page 162 HI-TECH C USER'S MANUAL
TOUPPER, TOLOWER, TOASCII
SYNOPSIS
#include <ctype.h>
char toupper(int c);
char tolower(int c);
char toascii(int c);
char c;
DESCRIPTION
Toupper() converts its lower case alphabetic argument
to upper case, tolower() performs the reverse conver-
sion, and toascii() returns a result that is guaranteed
in the range 0-0177. Toupper() and tolower return their
arguments if it is not an alphabetic character.
SEE ALSO
islower, isupper, isascii et. al.
UNGETC
SYNOPSIS
#include <stdio.h>
int ungetc(int c, FILE * stream)
DESCRIPTION
Ungetc() will attempt to push back the character c onto
the named stream, such that a subsequent getc() opera-
tion will return the character. At most one level of
pushback will be allowed, and if the stream is not buf-
fered, even this may not be possible. EOF is returned
if the ungetc() could not be performed.
SEE ALSO
getc
HI-TECH C USER'S MANUAL Page 163
UNLINK
SYNOPSIS
int unlink(char * name)
DESCRIPTION
Unlink() will remove (delete) the named file, that is
erase the file from its directory. See open() for a
description of the file name construction. Zero will
be returned if successful, -1 if the file did not exist
or it could not be removed.
SEE ALSO
open, close, rename, remove
VA_START, VA_ARG, VA_END
SYNOPSIS
#include <stdarg.h>
void va_start(va_list ap, parmN);
type va_arg(ap, type);
void va_end(va_list ap);
DESCRIPTION
These macros are provided to give access in a portable
way to parameters to a function represented in a proto-
type by the ellipsis symbol (...), where type and
number of arguments supplied to the function are not
known at compile time. The rightmost parameter to the
function (shown as parmN) plays an important role in
these macros, as it is the starting point for access to
further parameters. In a function taking variable
numbers of arguments, a variable of type va_list should
be declared, then the macro va_start invoked with that
variable and the name of parmN. This will initialize
the variable to allow subsequent calls of the macro
va_arg to access successive parameters. Each call to
va_arg requires two arguments; the variable previously
defined and a type name which is the type that the next
parameter is expected to be. Note that any arguments
thus accessed will have been widened by the default
conventions to int, unsigned int or double. For exam-
ple if a character argument has been passed, it should
be accessed by va_arg(ap, int) since the char will have
been widened to int. An example is given below of a
function taking one integer parameter, followed by a
number of other parameters. In this example the func-
tion expects the subsequent parameters to be pointers
to char, but note that the compiler is not aware of
this, and it is the programmers responsibility to
Page 164 HI-TECH C USER'S MANUAL
ensure that correct arguments are supplied.
#include <stdarg.h>
prf(int n, ...)
{
va_list ap;
va_start(ap, n);
while(n--)
puts(va_arg(ap, char *));
va_end(ap);
}
WRITE
SYNOPSIS
#include <unixio.h>
int write(int fd, void * buf, size_t cnt)
DESCRIPTION
Write() will write from the buffer at buf up to cnt
bytes to the file associated with the file descriptor
fd. The number of bytes actually written will be
returned. EOF or a value less than cnt will be returned
on error. In any case, any return value not equal to
cnt should be treated as an error (cf. read() ).
SEE ALSO
open, close, read
HI-TECH C USER'S MANUAL Page 165
INDEX
8086 70 CP/M 26,106,131,155
absolute value 116 CP/M-80 compiler 2
acos() 103 cputs() 107
address creat() 111
link 73 creating a library 76
load 73 CREF 83
ANSI Standard 13,17 cross compilers 3
array cross reference 36,83
dimension 16 ctime() 111
index 16 ctrl-Z 26,120
size 16 date and time 104
ASCII 26 debugging 10,105
asctime() 104 device name as file 23
asin() 103 device
assembler as file 141
in C programs 20 di() 113
assert() 105 directory 108,139
atan() 103 current 130
atan2() 103 disk changing on floppy disk
Atari ST 3 systems 3
atexit() 104 disk space 33
atof() 105 div() 112
atoi() 105 div_t 112
atol() 105 dup() 113
bdos() 106 editor 3,33
binary output file 8 ei() 113
bios() 106 entering long commands 7
braces Enumerated Types 16
omission of 16 environment 130
byte ordering 21 error message:
C command 3,7 Can't generate code 33
C reference books 2 Error closing file 33
calloc() 107 No room 33
carriage return 26,120 out of memory 33
ceil() 116 Undefined symbol 33
cgets() 107 Write error 33
change file attributes 108 error messages 23,33
character testing 134 format of 23
chdir() 108 LIBR 78
checksum 79,80 list of 23,85
chmod() 108 redirection of 23
class name 70 execl() 114
close() 109 executing a sub-program 156
clreof() 109 executing system commands
clrerr() 109 160
command line 7,12,77,160 execution profiling 10
Compatibility 25 execv() 114
compiler driver 3 exit() 114
Compiler Structure 5 exp() 115
console I/O 107,129,135 exponentional functions 115
control-C handling 155 Extern Declarations 30
converting ascii to binary fabs() 116
105 fclose() 116
cos() 110 feof() 117
cosh() 110 ferror() 117
Page 166 HI-TECH C USER'S MANUAL
fflush() 117 getw() 132
fgetc() 118 global variables 30
fgets() 118 gmtime() 132
FILE 99 hex output file 8
file descriptor 27,111,119 I/O redirection 127
duplicating 113 I/O
FILE pointer 27 ASCII 26
file Binary 26
access time 158 standard 25,99
attributes 108,158 in-line assembler 20
closing a 109,116 Initialization Syntax 16
creating a 111 initializer 16
deleting a 148,163 inp() 133
flushing buffer to a 117 int86() 133
information about a 158 int86x() 133
modification time 158 intdos() 133
opening a 119,123,140 intdosx() 133
random access to a Intel hex format 79
125,137 interrupt 133
reading from a 122,147 interrupt handling 155
renaming a 149 interrupt vector
size 158 setting 154
type of a 135 isalnul() 134
writing to a 126,164 isalnum() 134
fileno() 119 isalpha() 134
floating point isascii() 134
library 27 isatty() 135
options required to use iscntrl() 134
4 isdigit() 134
floor() 116 isgraph() 134
fopen() 26,119 islower() 134
formatted input 124,150 ispunct() 134
formatted printing 121,142 isspace() 134
fprintf() 121 isupper() 134
fputc() 121 kbhit() 135
fputs() 122 Kernighan and Ritchie 2,16
fread() 122 large model 70,80
free() 123 ldexp() 124
freopen() 123 ldiv() 112
frexp() 124 LIBR 75
fscanf() 124 librarian 75
fseek() 125 libraries 7
ftell() 126 library manager 75
function parameter 163 library ordering 77
function library
declaration 17 creating 76
large 33 floating point 33
parameters 17 ordering 33
prototype 17,163 line number symbols 10
fwrite() 126 linker 69
getc() 128 LINT 16
getch() 129 localtime 132
getchar() 25,129 log() 115
getche() 129 log10() 115
getcwd() 130 logarithmic functions 115
getenv() 130 long 30
gets() 131 longjmp() 136
getuid() 131 lseek() 137
HI-TECH C USER'S MANUAL Page 167
Machine Dependencies 21 pack pragma 20
macros parameter
predefined 21 type 17
malloc() 137 perror() 141
Member Names 13,29 portable code 21
memcmp() 138 pow() 115
memcpy() 138 pragma 20,21
memory allocation printf 33
107,148,150 printf() 142
releasing 123 program execution 156
memory model 31 psect
memory requirements 2 linking 69
memset() 138 local 70
mkdir() 139 putc() 144
Motorola hex format 80 putch() 129
MS-DOS 108,133,139,155 putchar() 144
msdos() 139 puts() 145
msdoscx() 139 putw() 145
multiple definitions 30 qsort() 146
newline 26 rand() 147
Newton's approximation 157 random numbers 147,158
non-local goto 136,152 read() 147
objtohex 72,79 realloc() 148
open() 140 relocation 69
Operating Details 7 remove() 148
options 7 rename() 149
-1 10 return 26,120
-11 11 rewind() 149
-2 11 rmdir() 139
-6301 11 S format hex 80
-A 8 sbrk() 150
-B 9 scanf 33
-C 7 scanf() 150
-CPM 7 segment registers 152
-CR 7 segread() 152
-D 8 self relocation 72
-E 10 setbuf() 153
-F 8 setjmp() 152
-G 10 setuid() 153
-H 10 setvbuf() 153
-I 8 set_vector() 154
-LF 4,27,33 shift
-M 8 signed 14
-O 8 unsigned 14
-Ooutfile 8 short 21,30
-P 10 signal() 155
-R 8 sin() 155
-S 7 sinh() 110
-U 8 size of data types 21
-V 3,8 sorting 146
-W 10 source file naming 3
-X 8 source level debugging 10
-Z 10 spawnl() 156
linker 71 spawnv() 156
outp() 133 spawnve() 156
pack 21 Specific Features 13
sprintf() 156
sqrt() 157
Page 168 HI-TECH C USER'S MANUAL
square root function 157 Unsigned Types 14
srand() 158 user ID 131,153
sscanf() 157 V3.09 2
Standard Libraries 25 va_arg 18,163
Standard Library Functions va_end 163
99 va_start 163
stat() 158 void 18
stdarg.h 18,163 Pointer to 18
STDIO 25,27,99 warning level 10
storage allocator 18 warning messages
strcat() 159 suppressing 10
strchr() 160 wild card expansion 127
strcmp() 159 Wordstar 33
strcpy() 159 write() 164
stream 27,99 Z180 MMU 68
string manipulation 159 Bank Base Register 68
strlen() 159 BBR 68
strncat() 159 CBAR 68
strncmp() 159 CBR 68
strncpy() 159 Common Base Register 68
strrchr() 160 Common/Bank Area Regis-
Structure Operations 15 ter 68
structure packing 20 Z180 Registers 68
structures ASCI 68
as function argument 15 Bank Base Register 68
assignment 15 BBR 68
functions returning 15 BCR0H 68
Stylistic Considerations 29 BCR0L 68
symbol file 10,80 BCR1H 68
symbols BCR1L 68
cross reference 83 CBAR 68
global 70,76 CBR 68
System Requirements 2 CNTLA0 68
system() 160 CNTLA1 68
tan() 161 CNTLB0 68
tanh() 110 CNTLB1 68
temporary files 4 CNTR 68
text editor 3 Common Base Register 68
time and date 104 Common/Bank Area Regis-
time() 161 ter 68
toascii() 162 CSI/0 68
tolower() 162 DAR0B 68
toupper() 162 DAR0H 68
trigonometric functions DAR0L 68
103,110 DCNTL 68
hyperbolic 110 DMA 68
Type Checking 13 DMA Byte Count 68
type qualifiers 19 DMA Desitination Address
typecast 13 68
typecasting 18 DMA Mode Register 68
ungetc() 162 DMA Source Address 68
ungetch() 129 DMA Status Register 68
Unix DMODE 68
C compiler 16 DSTAT 68
V7 25 FRC 68
unlink() 163 Free Running Counter 68
unsigned 23 IAR1H 68
unsigned char 21 IAR1L 68
HI-TECH C USER'S MANUAL Page 169
ICR 68 INC 55
IL 68 IND 55
Interrupt Vector Regis- INDR 56
ter 68 INI 56
ITC 68 INIR 56
MAR1B 68 JP 56
MAR1H 68 JR 56
MAR1L 68 LD 56,57,58,59
MMU 68 LDD 59
OMCR 68 LDDR 59
RCR 68 LDI 59
Refresh Control Register LDIR 59
68 MLT 59
RLDR0H 68 NEG 59
RLDR0L 68 NOP 59
RLDR1H 68 OR 59,60
RLDR1L 68 OTDM 61
SAR0B 68 OTDMR 60
SAR0H 68 OTDR 60
SAR0L 68 OTIM 61
STAT0 68 OTIMR 60
STAT1 68 OTIR 60
TCR 68 OUT 60
TDR0 68 OUT0 60
TDR1 68 OUTD 60
TIMER 0 68 OUTI 61
TIMER 1 68 POP 61
TMDR0H 68 PUSH 61
TMDR0L 68 RES 61,62,63
TMDR1H 68 RET 63
TMDR1L 68 RETI 63
TRDR 68 RETN 63
TSR0 68 RL 63
TSR1 68 RLA 63
Z80 Instructions 50 RLC 63
ADC 51 RLCA 63
ADD 51 RLD 63
AND 51 RR 63,64
BIT 52,53 RRA 64
CALL 53 RRC 64
CCF 53 RRCA 64
CP 53,54 RRD 64
CPD 54 RST 64
CPDR 54 SBC 64
CPI 54 SCF 64
CPIR 54 SET 64,65,66
CPL 54 SLA 66
DAA 54 SLP 66
DEC 54 SRA 66
DI 54 SRL 67
DJNZ 54 SUB 67
EI 54 TST 67
EX 55 TSTIO 67
EXX 55 XOR 67
HALT 55 Z80 pseudo ops
IM 55 IRP 47
IN 55 IRPC 47
IN0 55 ZAS directives 48
Page 170 HI-TECH C USER'S MANUAL
title 48 operators 38
ZAS options program sections 39
-J 35 PSECT 43
-L 36 psects 39,43
-N 35 pseudo ops 40
-O 36 relocatable object code
-U 35 39
-W 36 temporary labels 37
ZAS psect flags Z180 35
ABS 43 Zilog 35
GLOBAL 43 _exit() 115
LOCAL 43 _getargs() 127
OVRLD 43
PURE 43
ZAS pseudo ops 40
COND 42
DB 40
DEFB 40
DEFF 41
DEFL 41
DEFM 42
DEFS 41
DEFW 41
ELSE 42
END 42
ENDC 42
ENDM 44
EQU 41
GLOBAL 43
IF 42
LOCAL 45
MACRO 44
ORG 44
PSECT 43
REPT 46
ZAS
64180 35
arithmetic overflow 35
binary constants 37
character constants 38
condition codes 48
conditional assembly 42
constants 37
directives 48
extended condition codes
48
external symbols 35
floating point constants
38
hexadecimal constants 37
jump optimization 35
jumps 35
labels 36
listing 36
macros 44
mnemonics 35
octal constants 37
opcode constants 38