Pacman
Pacman
Complete this card and return it to HI-TECH Software to ensure that you will
receive technical support and access to updates. Please use block letters!
1
Your name: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
I hereby agree to the terms and conditions of the licence agreement for this software
Signed: 8 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Please help us to help you by answering the following questions. We will use
this information to improve our products.
Please tick the operating Please indicate programming If you program embedded
systems you use: languages you use systems, please list the
processors you use
q MS-DOS q C ________________
q Windows 3.1 or 3.11 or WfWg q C++ ________________
q Windows ‘95 q Objective-C ________________
q Windows NT q Eiffel ________________
q OS/2 q Pascal ________________
________________
q Unix (specify platform) q Modula-2
________________
________________ q Modula-3
________________
q Simula
q Other (please specify) ________________
________________ q Smalltalk ________________
q Forth
q Assembler Thank you!
q Other (please specify)
________________
Tape here
Please
attach
correct
postage
HI-TECH Software
PO Box 103
ALDERLEY QLD 4051
AUSTRALIA
1
Introduction 1
Using PPD 3
Runtime Organization 4
Error Messages A
Library Functions B
1
YOU SHOULD CAREFULLY READ THE FOLLOWING BEFORE INSTALLING OR USING THIS SOFTWARE PACK-
AGE. IF YOU DO NOT ACCEPT THE TERMS AND CONDITIONS BELOW YOU SHOULD IMMEDIATELY RETURN
THE ENTIRE PACKAGE TO YOUR SUPPLIER AND YOUR MONEY WILL BE REFUNDED. USE OF THE SOFT-
WARE INDICATES YOUR ACCEPTANCE OF THESE CONDITIONS.
To ensure that you receive the benefit of the warranty described below, you should complete and sign the accompanying regis- 1
tration card and return it to HI-TECH Software immediately.
HI-TECH Software, a division of Gretetoy Pty. Ltd., of 12 Blackwood St., Mitchelton QLD 4053 Australia, provides this software
package for use on the following terms and conditions:
This software package is fully copyrighted by HI-TECH Software and remains the property of HI-TECH Software at all times.
You may:
m Use this software package on a single computer system. You may transfer this package from one computer system to another provided
you only use it on one computer system at a time.
m Make copies of diskettes supplied with the software package for backup purposes provided all copies are labelled with the name of
the software package and carry HI-TECH Software’s copyright notice.
m Use the software package to create your own software programs. Provided such programs do not contain any part of this software
package other than extracts from any object libraries included then these programs will remain your property and will not be covered
by this agreement.
m Transfer the software package and this licence to a third party provided that the third party agrees to the terms and conditions of this
licence, and that all copies of the software package are transferred to the third party or destroyed. The third party must advise HI-TECH
Software that they have accepted the terms and conditions of this licence.
You may NOT:
m Sell, lend, give away or in any way transfer copies of this software package to any other person or entity except as provided above,
nor allow any other person to make copies of this software package.
m Incorporate any portion of this software package in your own programs, except for the incorporation in executable form only of
extracts from any object libraries.
m Use this package to develop life-support applications or any application where failure of the application could result in death or injury
to any person. Should you use this software to develop any such application, you agree to take all responsibility for any such failures,
and indemnify HI-TECH Software against any and all claims arising from any such failures.
TERM
This licence is effective until terminated. You may terminate it by returning to HI-TECH Software or destroying all copies of the soft-
ware package. It will also terminate if you fail to comply with any of the above conditions.
WARRANTY
HI-TECH Software warrants that it has the right to grant you this licence and that the software package is not subject to copyright to
which HI-TECH Software is not entitled. Certain State and Federal laws may provide for warranties additional to the above.
1 LIMITATION OF LIABILITY
This software package has been supplied in good faith and is believed to be of the highest quality. Due
to the nature of the software development process, it is possible that there are hidden defects in the
software which may affect its use, or the operation of any software or device developed with this pack-
age. You accept all responsibility for determining whether this package is suitable for your applica-
tion, and for ensuring the correct operation of your application software and hardware. HI-TECH
Software’s sole and maximum liability for any defects in this package is limited to the amount you
have paid for the licence to use this software. HI-TECH Software will not be liable for any consequen-
tial damages under any circumstances, unless such exclusion is forbidden by law.
Trade Marks
The following are trade marks of HI-TECH Software:
Other trade marks and registered trade marks used in this document are the property of their respec-
tive owners.
Technical Support
For technical support on this software product contact your reseller. HI-TECH Software may be con-
tacted as follows, but note that HI-TECH Software will not necessarily provide technical support un-
less you have a current technical support agreement in place.
HI-TECH Software
a division of Gretetoy Pty. Ltd.
PO Box 103, Alderley
QLD 4051 Australia
1
Contents
1 - Introduction
1.1 The Pacific C Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
1.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .1
1.2.1 INSTALL Program . . . . . . . . . . . . . . . . . . . . . . . . . . .1 1
1.2.1.1 Installation Steps . . . . . . . . . . . . . . . . . . . . . . . . . .1
1.2.1.2 Custom Installation . . . . . . . . . . . . . . . . . . . . . . . .2
1.2.1.3 Serial Number and Installation Key . . . . . . . . . . . . . . . .2
1.2.1.4 Accessing the Compiler . . . . . . . . . . . . . . . . . . . . . .3
2 - Quick Start Guide
2.1 Getting started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5
2.2 A Sample Program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5
2.3 Using PPD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .5
2.4 Using PACC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .6
3 - Using PPD
3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7
3.1.1 Typographic Conventions . . . . . . . . . . . . . . . . . . . . . . . .7
3.1.2 Starting PPD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .7
3.2 The HI-TECH Windows User Interface . . . . . . . . . . . . . . . . . . . .8
3.2.1 Hardware Requirements . . . . . . . . . . . . . . . . . . . . . . . . .8
3.2.2 Pull-down Menus . . . . . . . . . . . . . . . . . . . . . . . . . . . .9
3.2.2.1 Keyboard Menu Selection . . . . . . . . . . . . . . . . . . . . 10
3.2.2.2 Mouse Menu Selection . . . . . . . . . . . . . . . . . . . . . . 10
3.2.2.3 Menu Hot Keys . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.3 Selecting Windows . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2.4 Moving and Resizing Windows . . . . . . . . . . . . . . . . . . . . 11
3.2.5 Buttons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2.6 The Setup Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.3 Tutorial: Creating and Compiling a C Program . . . . . . . . . . . . . . . 14
3.4 The PPD Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4.1 Status Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4.2 Keyboard Commands . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.3 Block Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.4 Clipboard Editing . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Pacific C Compiler i
Pacific C Compiler
ii
Contents
4.8.4 Link Addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.8.5 Load Addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.8.6 Linking and the -P option . . . . . . . . . . . . . . . . . . . . . . . 50 1
5 - 8086 Assembler Reference Manual
5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.2 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.2.1 -Q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.2.2 -U . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
5.2.3 -Ofile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.4 -Llist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.5 -Wwidth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.6 -X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.7 -E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.8 -M . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.9 -1,-2,-3,-4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
5.2.10 -N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2.11 -I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2.12 -S . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2.13 -C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.3 The Assembly Language . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.3.1 Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.3.1.1 Temporary Labels . . . . . . . . . . . . . . . . . . . . . . . . 58
5.3.2 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.3.2.1 Character Constants . . . . . . . . . . . . . . . . . . . . . . . 59
5.3.2.2 Floating Constants . . . . . . . . . . . . . . . . . . . . . . . . 59
5.3.3 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.3.3.1 Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.3.3.2 Relocatability . . . . . . . . . . . . . . . . . . . . . . . . . . 59
5.3.4 Pseudo-ops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.3.4.1 .BYTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.3.4.2 .WORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
5.3.4.3 .DWORD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
1 5.3.4.4 .FLOAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3.4.5 .BLKB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3.4.6 EQU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3.4.7 SET . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3.4.8 .END . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3.4.9 IF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.3.4.10 .ENDIF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.3.4.11 .ENDM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.3.4.12 .PSECT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.3.4.13 .GLOBL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.3.4.14 .LOC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
5.3.4.15 .MACRO and .ENDM . . . . . . . . . . . . . . . . . . . . . 65
5.3.4.16 .LOCAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
5.3.4.17 .REPT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.3.4.18 .IRP and .IRPC . . . . . . . . . . . . . . . . . . . . . . . . . 67
5.3.4.19 Macro Invocations . . . . . . . . . . . . . . . . . . . . . . . 68
5.3.4.20 .TITLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.3.4.21 .SUBTTL . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.3.4.22 .PAGE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.3.4.23 .INCLUDE . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
5.3.4.24 .LIST . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.3.5 Addressing Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.3.5.1 Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.3.5.2 Immediate . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
5.3.5.3 Direct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.3.5.4 Register indirect . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.3.5.5 Indexed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
5.3.5.6 String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
iv
Contents
5.3.5.7 I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
5.3.5.8 Segment prefixes . . . . . . . . . . . . . . . . . . . . . . . . . 71
5.3.5.9 Jump . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 1
5.3.6 80386 Addressing Modes . . . . . . . . . . . . . . . . . . . . . . . 71
5.3.6.1 Segment Registers . . . . . . . . . . . . . . . . . . . . . . . . 71
5.3.6.2 String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.3.6.3 Single register . . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.3.6.4 Double indexed . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.3.6.5 Scaled index . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
5.4 Diagnostics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
6 - Lucifer - A Source Level Debugger
6.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.2 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6.3 Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
6.3.1 The A Command: set command line arguments . . . . . . . . . . . . 78
6.3.2 The B Command: set or display breakpoints . . . . . . . . . . . . . 79
6.3.3 The D Command: display memory contents . . . . . . . . . . . . . 79
6.3.4 The E Command: examine C source code . . . . . . . . . . . . . . . 79
6.3.5 The G Command: commence execution . . . . . . . . . . . . . . . . 80
6.3.6 The I Command: toggle instruction trace mode . . . . . . . . . . . . 80
6.3.7 The Q Command: exit to DOS . . . . . . . . . . . . . . . . . . . . 81
6.3.8 The R Command: remove breakpoints . . . . . . . . . . . . . . . . 81
6.3.9 The S Command: step one C line . . . . . . . . . . . . . . . . . . . 81
6.3.10 The T Command: trace one instruction . . . . . . . . . . . . . . . 82
6.3.11 The U Command: disassemble . . . . . . . . . . . . . . . . . . . . 82
6.3.12 The X Command: examine or change registers . . . . . . . . . . . 83
6.3.13 The @ Command: display memory as a C type . . . . . . . . . . . 83
6.3.14 The ^ Command: print a stack trace . . . . . . . . . . . . . . . . . 84
6.3.15 The $ Command: reset to initial configuration . . . . . . . . . . . . 85
6.3.16 The . Command: set a breakpoint and go . . . . . . . . . . . . . . 85
6.3.17 The ; Command: display from a source line . . . . . . . . . . . . . 85
Pacific C Compiler v
Pacific C Compiler
vi
Contents
8.7.1 Numbers in linker options . . . . . . . . . . . . . . . . . . . . . 101
8.7.2 -8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
8.7.3 -Aclass=low-high,... . . . . . . . . . . . . . . . . . . . . . . . . . 101 1
8.7.4 -Cpsect=class . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
8.7.5 -Dsymfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
8.7.6 -F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.7.7 -Gspec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.7.8 -Hsymfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.7.9 -I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8.7.10 -L . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
8.7.11 -LM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
8.7.12 -Mmapfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
8.7.13 -N . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
8.7.14 -Ooutfile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
8.7.15 -Pspec . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
8.7.16 -Spsect=max . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.7.17 -Usymbol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.7.18 -Vavmap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.7.19 -Wnum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.7.20 -X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.7.21 -Z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
8.8 Invoking the Linker . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
9 - Librarian Reference Manual
9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
9.2 Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
9.2.1 Creating a library . . . . . . . . . . . . . . . . . . . . . . . . . . 109
9.2.2 Updating a library . . . . . . . . . . . . . . . . . . . . . . . . . . 110
9.2.3 Deleting library modules . . . . . . . . . . . . . . . . . . . . . . 110
9.2.4 Extracting a module . . . . . . . . . . . . . . . . . . . . . . . . . 110
9.2.5 Listing a library . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
9.3 Library ordering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
9.4 Creating libraries from PPD . . . . . . . . . . . . . . . . . . . . . . . . 111
1
Appendix A - Error Messages . . . . . . . . . . . . . . . . . . . . . . . . . 113
Appendix B - Library Functions . . . . . . . . . . . . . . . . . . . . . . . . 151
viii
Chapter 1
1
Introduction
1.1 The Pacific C Compiler
This manual covers the Pacific C compiler for MS-DOS from HI-TECH Software. In this manual you
will find information on installing, using and customising the compiler.
Pacific C requires an 80286 processor with at least 512K of free conventional memory, and a hard disk,
It will also run on 80386 and 80486 processors. MS-DOS 3.1 or later is required, we recommend MS-DOS
3.3 or later, or DRDOS 6.0 or later. We strongly recommend you have at least 1MB of free XMS memory
(from HIMEM.SYS). A mouse is not required, but is strongly recommended
1.2 Installation
Pacific C is supplied on one or more 3.5" or 5.25" diskettes. The contents of the disks are listed in a file
called PACKING.LST on disk 1. To install the compiler, you must use the INSTALL program on disk
1. This is located in the root directory of disk 1. Place disk 1 in either floppy drive, then type A:INSTALL
or B:INSTALL as appropriate. The INSTALL program will then present a series of messages and ask
for various information as it proceeds. You may need to check your environment variables (use the SET
command) in case you have an environment variable called TEMP set. If this variable is set, its value
should a directory path. The full path must exist and designate a directory in which temporary files can
be created.
1.2.1 INSTALL Program
The INSTALL program uses several on-screen windows. There is a message window, in which it displays
messages and prompts. There is also a one-line status window in which INSTALL says what it is currently
doing. Other windows will pop up from time to time. A dialog or alert window will pop up when
INSTALL wants user action, or when any kind of error occurs, and will offer the opportunity to continue,
retry (if appropriate) or terminate. If you select TERMINATE, the installation will be incomplete. A
sliding bar will indicate the approximate degree of completion of the installation.
1.2.1.1 Installation Steps
When INSTALL prompts for action, you may either press ENTER to continue, ESCAPE to terminate,
or use a mouse if you have one to select the buttons displayed in the dialog window. To use a mouse,
move the cursor into the desired button, then press and release the left mouse button.
Pacific C Compiler 1
Chapter 1 - Introduction
1 Initially INSTALL will simply advise it is about to install a HI-TECH Software package. Select
CONTINUE or press ENTER. You will then be asked to choose between a full, no questions asked
installation, or a custom installation in which you may choose not to install optional parts of the compiler.
The custom installation will also allow you to specify the directories in which the compiler is installed
1.2.1.2 Custom Installation
If you selected a custom installation, INSTALL then asks you a series of questions about directory paths
for installation of the compiler. At each one it will display a default path and ask you to press ENTER
to confirm that path, or enter a new path then press ENTER. Again you may select TERMINATE if
you do not want to continue. Note that INSTALL will create any directory necessary, except that it will
NOT create intermediate directories, e.g. it will create the directory C:\COMPILE\HITECH if it does
not exist, but it will not create the COMPILE directory in this case. It must already exist.
INSTALL also asks for a temporary file directory. This is a directory in which the compiler will place
temporary files, and should be a RAM disk if you have one (but ensure the RAM disk is reasonably large
- at least several hundred Kbytes). Otherwise it may be a directory on your hard disk or simply blank. If
it is blank the compiler will create temporary files in the working directory.
Next INSTALL asks a series of questions about installation of optional parts of the compiler. For each
part you may answer yes (ENTER) or no (F10) or use the mouse to click the appropriate button.
1.2.1.3 Serial Number and Installation Key
After these questions have been answered, or immediately if you selected a full installation, INSTALL
will ask you to enter the serial number and installation key. You will also be asked to enter your name
and your company’s name (the company name is optional). INSTALL will serialise the installed compiler
with this information. The serial number and installation key are found on the reverse of the manual title
page. The serial number and key must be entered correctly or the installation will not proceed.
After this INSTALL proceeds to copy (decompressing as it goes) the files that are contained in the basic
compiler and the optional parts. Each file being copied will be displayed in the status window. If
INSTALL discovers it is copying a file that already exists, i.e. it is going to overwrite a file, it will pop
up a dialog window asking if you want to overwrite the file. If you answer YES the first time this occurs,
you will be asked if you want to be prompted about any other overwritten files. Answering NO will cause
install to silently overwrite any other files that already exist. This would be in order if you were reinstalling
or installing an updated version.
During the copying process, INSTALL may bring up a window in the middle of the screen containing
informative text from a file on the distribution disk. This will contain information about the compiler and
other HI-TECH Software packages. While reading this information, you may use the up and down arrow
keys and the Page-up and Page-down keys to scroll the text.
2
Installation
INSTALL will bring up a dialog window whenever you need to change disks. When this occurs, place
the requested disk in the floppy drive and press ENTER. On completion of the installation, it will if
1
necessary edit your AUTOEXEC.BAT and CONFIG.SYS files. When it does so, it will bring up two
edit windows containing the new and old versions of the file. You may scroll the windows and compare
to see what changes have been made, and edit the new version if you desire. When done, press F1 or
click in the DONE button in the status window. Pressing ESC or clicking in the ABORT window will
prevent INSTALL from updating the file. This step will not occur if your AUTOEXEC.BAT does not
need modification.
After this INSTALL will display some messages, then advise you to press ENTER to read the release
notes for the compiler. This will load the file READ.ME (which will also be copied onto your hard disk)
in the screen window and allow you to read it. Pressing ENTER again will exit to DOS.
At this stage you may need to reboot to allow the changes to AUTOEXEC.BAT to take effect. INSTALL
will have told you to do this if it is necessary. The installation is now complete.
1.2.1.4 Accessing the Compiler
The installation process will include in your PATH environment variable the directory containing the
compiler executable programs. However, it is possible that some other programs already installed on your
system have the same name as one of the compiler programs. The most common of these is LINK. To
overcome this you may need to re-organise your PATH environment variable.
The compiler drivers are PACC.EXE (command line version) and PPD.EXE (integrated version). These
are basically the only commands you need to access the compiler, but you may also want to run other
utilities directly.
Pacific C Compiler 3
Chapter 1 - Introduction
4
Chapter 2
main()
{
printf(“Hello, world!\n”);
}
Pacific C Compiler 5
Chapter 2 - Quick Start Guide
q Press F7 to run the program. PPD will revert to a DOS text screen and run your compiled program.
You will see the words “Hello, world!” appear, followed by “Press any key to return...”. If you then
press a key, you will be returned to PPD. To exit PPD, press ALT-Q.
6
Chapter 3
Using PPD
3.1 Introduction
This chapter covers PPD, the Pacific C Programmer’s Development system integrated environment.It
assumes that you already have an installed Pacific C compiler, if you haven’t installed your compiler go 3
to chapter 1, INTRODUCTION, and follow the installation instructions there.
3.1.1 Typographic Conventions
Throughout this chapter, we will adopt the convention that any text which you need to type will be printed
in bold type. The computer’s prompts and responses will be printed in constant spaced type.
Particularly useful points and new terms will be illustrated using italicised type. With a window based
program like PPD, some concepts are difficult to convey in print and will be introduced using short
tutorials and sample screen displays.
3.1.2 Starting PPD
To start PPD, simply type PPD at the DOS prompt and, after a brief period of disk activity you will be
presented with a screen similar to the one shown in figure 3-1.
The initial PPD screen is broken up into three windows which, from the top, contain the menu bar, the
PPD text editor and the message window. Other windows may appear when certain menu items are
selected, however the editing screen is what you will use most of the time.
PPD uses the HI-TECH Windows user interface to provide a text screen based user interface with multiple
overlapping windows and pull down menus. Later in this chapter are described the user interface features
which are common to all HI-TECH Windows applications.
PPD can optionally take a single command line argument which is either the name of a text file, or the
name of a project file. (Project files are discussed in a later section of this chapter). If the argument has
an extension .PRJ, PPD will attempt to load a project file of that name. File names with any other extension
will be treated as text files and loaded by the editor. If an argument without an extension is given, PPD
will first attempt to load a .PRJ file, then a .C file. For example, if the current directory contains a file
called X.C and PPD is invoked with the command PPD X, it will first attempt to load X.PRJ and when
that fails, will load X.C into the editor. If no source file is loaded into the editor, an empty file with name
“untitled” will be started.
Pacific C Compiler 7
Chapter 3 - Using PPD
8
The HI-TECH Windows User Interface
PPD is executed, or with a /screen:xx option as described below. Problems may be experienced
with some poorly written VGA utilities which initialize the hardware to a higher resolution mode but
leave the BIOS data area in low memory set to the values for an 80 x 25 display.
It is also possible to have PPD set the screen display mode on EGA and VGA displays to show more than
25 lines. The option /SCREEN:nn where nn is one of 25, 28, 43 or 50 will cause PPD to set the display
to that number of lines, or as close as possible. EGA displays support only 25 and 43 line text screens,
while VGA supports 28 and 50 lines as well.
The display will be restored to the previous mode after PPD exits. The selected number of lines will be 3
saved in PPD.INI and used for subsequent invocations of PPD unless overridden by another /SCREEN
option.
PPD will recognize and use any mouse driver which supports the standard INT 33H interface. Almost
all modern mouse drivers support the standard device driver interface, however some older mouse drivers
are missing a number of the driver status calls. If you are using such a mouse driver, PPD will still work
with the mouse, but the Mouse Setup dialogue in the <<>> menu will not work.
3.2.2 Pull-down Menus
HI-TECH Windows includes a system of pull-down menus which are based around a menu bar across
the top of the screen. The menu bar will be broken into a series of words or symbols, each of which is
the title of a single pull-down menu.
The menu system can by used by keyboard, with the mouse, or with a combination of mouse and keyboard
actions. The keyboard and mouse actions listed in table 3-1 are supported:
Pacific C Compiler 9
Chapter 3 - Using PPD
10
The HI-TECH Windows User Interface
1 * Pressing the left button in a window frame has a completely different effect, as discussed later in this chapter.
Pacific C Compiler 11
Chapter 3 - Using PPD
Key Meaning
alt-O Open editor file
alt-N Clear editor file
alt-S Save editor file
alt-A Save editor file with new name
3 alt-Q Quit to DOS
alt-F Open File menu
alt-E Open Edit menu
alt-P Open project file
alt-I Open Compile menu
alt-M Open Make menu
alt-R Open Run menu
alt-H Open Help menu
alt-U Open Utility menu
alt-W Warning level dialog
alt-Z Optimisation menu
alt-D DOS command
alt-J Run COMMAND.COM
alt-T Open Options menu
alt-L Download code via Lucifer
alt-B Run Lucifer debugger
F3 Compile and link single file
shift-F3 Compile to object file
ctrl-F3 Compile to assembler code
F5 Make target program
ctrl-F5 Re-make all objects and target program
shift-F5 Re-link target program
alt-P Load project file
shift-F7 User defined command 1
shift-F8 User defined command 2
shift-F9 User defined command 3
shift-F10 User defined command 4
F2 Search in edit window
12
The HI-TECH Windows User Interface
Key Meaning
shift-F2 Search again, forward
ctrl-F2 Search again, backward
alt-X Cut to clipboard
alt-C Copy to clipboard
alt-V Paste from clipboard
alt-G Goto line number
alt-T Set tab size 3
bottom edge the pointer will change to a vertical arrow and it will only be possible to move the window
vertically. If a window is grabbed near the middle of the left or right edge the pointer will change to a
horizontal arrow and it will only be possible to move the window horizontally.
If a window has a scroll bar in its frame, pressing the left mouse button in the scroll bar will not move
the window, but will instead activate the scroll bar, sending scroll messages to the application. If you
want to move a window which has a frame scroll bar, just select a different part of the frame.
Windows can be resized using the right mouse button. Any visible window can be resized by pressing
the right mouse button on its bottom or left frame, dragging the frame to a new boundary and releasing
the button. If a window is grabbed near its lower right corner the pointer will change to a diamond and
it will be possible to resize the window in any direction. If the frame is grabbed anywhere else on the
bottom edge, it will only be possible to resize vertically, likewise if the window is grabbed anywhere else
on the right edge it will only be possible to resize horizontally. If the right button is pressed anywhere in
the top or left edges nothing will happen.
It is also possible to zoom a window to its maximum size. The front most window can be zoomed by
pressing shift-(keypad)+, if it is zoomed again it will revert to its former size. In either the zoomed or
unzoomed state the window can be moved and resized, thus zoom effectively toggles between two user
defined sizes. A window can also be zoomed by clicking the right mouse button in its content region.
3.2.5 Buttons
Some windows contain buttons which can be used to select particular actions immediately. Buttons are
like menu items which are always visible and selectable. A button can be selected either by clicking the
left mouse button on it or by using its key equivalent. The key equivalent to a button will either be
displayed as part of the button, or as part of a help message somewhere else in the window. For example,
the PPD error window ( ) contains a number of buttons, to select EXPLAIN you would either click the
left mouse button on it or press F1.
Pacific C Compiler 13
Chapter 3 - Using PPD
Key Action
left arrow Move window to left
right arrow Move window to right
up arrow Move window upwards
14
Tutorial: Creating and Compiling a C Program
You will be presented with the PPD startup screen as discussed before. At this stage the editor is ready
to accept whatever text you type. A flashing block cursor should be visible in the top left corner of the
edit window. You are now ready to enter your first C program using PPD, which will naturally be the
infamous “hello world” program.
Type the following text, pressing enter once at the end of each line. Blank lines may be added by pressing
enter without typing any text.
#include <stdio.h>
3
/* infamous hello world program ! */
main()
{
printf(“Hello, world”)
}
Note that a semicolon has been deliberately omitted from the end of the cputs() statement in order to
demonstrate PPD’s error handling facilities. shows the screen as it should appear after entry of the “hello
world” program.
We now have a C program (complete with one error!) entered and almost ready for compilation, all we
need to do is save it to a disk file and then invoke the compiler. In order to save your source code to disk,
you will need to select the Save item from the File menu (figure 3-3 ).
If you do not have a mouse, follow these steps: 1) Open the menu system by pressing alt-Space. 2) Move
to the Edit menu using the right arrow key. 3) Move down to the Save item using the down arrow key.
4) When the Save item is highlighted, select it by pressing the Enter key.
If you are using the mouse, follow these steps: 1) Open the File menu by moving the pointer to the word
File in the menu bar and pressing the left button. 2) Highlight the Save item by dragging the mouse
downwards with the left button held down, until the Save item is highlighted. 3) When the Save item is
highlighted, select it by releasing the left button.
When the File menu was open, you may have noticed that the Save item included the text alt-S ( figure
3-3) at the right edge of the menu. This indicates that the save command can also be accessed directly
using the hot-key command alt-S. A number of the most commonly used menu commands have hot-key
equivalents which will either be alt-alphanumeric sequences or function keys.
After Save has been selected, you should be presented with a dialogue (figure 3-4) prompting you for
the file name. If PPD needs more information, such as a file name, before it is able to act on a command,
it will always prompt you with a standard dialogue like the one below.
Pacific C Compiler 15
Chapter 3 - Using PPD
The dialogue is broken up into an edit line where you can enter the filename to be used, and a number of
buttons which may be used to perform various actions within the dialogue. A button may be selected
either by clicking the left mouse button with the pointer positioned on it, or by using its key equivalent.
The text in the edit line may be edited using the standard editing keys: left arrow, right arrow,
backspace,del and ins. Ins toggles the line editor between insert and overwrite mode.
In this case, we wish to save our C program to a file called “hello.c”. Type hello.c and then press Enter.
There should be a brief period of disk activity and then PPD will respond with Saved hello.c in the message
window.
We are now ready to actually compile the program. To compile and link in a single step, select the
Compile and link item from the Compile menu, using the pull down menu system as before. Note that
Compile and link has key F3 assigned to it, in future you may wish to save time by using this key. After
selecting Compile and link, you should see messages from the various compiler passes (starting with
CPP) appearing in the message window.
16
Tutorial: Creating and Compiling a C Program
This time, the compiler will not run to completion because we deliberately omitted a semicolon on the
end of a line, in order to see how PPD handles compiler errors. After a couple of seconds of disk activity
as the CPP and P1 phases of the compiler run, you should hear a “splat” noise and the message window
will be replaced by a window containing a number of buttons and the message “; expected”, as shown in
figure 3-5.
The text in the frame of the error window details the number of compiler errors generated, and which
phase of the compiler generated them. Most errors will come from P1.EXE and CGEN.EXE*, CPP.EXE
and LINK.EXE can also return errors. In this case, the error window frame contains the message 1 error,
0 warnings from p1.exe indicating that pass 1 of the compiler found 1 fatal error. It is possible to configure
PPD so that non-fatal warnings will not stop compilation. If only warnings are returned, an additional
button will appear, labelled CONTINUE. Selecting this button (or F4) will resume the compilation.
Pacific C Compiler 17
Chapter 3 - Using PPD
In this case, the error message ;expected will be highlighted and the cursor will have been placed
on the start of the line after the printf() statement, which is where the error was first detected. The error
window contains a number of buttons, which allow you to select which error you wish to handle, clear
the error status display, or obtain an explanation of the currently highlighted error. In order to obtain an
explanation of the error message, either select the EXPLAIN button with a mouse click, or press F1.
The error explanation for the missing semicolon doesn’t give much more information than we already
had, however the explanations for some of the more unusual errors produced by the compiler can be very
helpful. All errors produced by the pre-processor (CPP), pass 1 (P1), code generator (CGxx), assembler
(ASxx) and linker (LINK) are handled. You may dismiss the error explanation by selecting the HIDE
button (press Escape or use the mouse).
18
Tutorial: Creating and Compiling a C Program
In this instance PPD has analyzed the error, and is prepared to fix the error itself. This is indicated by the
presence of the FIX button in the bottom right hand corner of the error window. If PPD is unable to
analyze the error, it will not show the FIX button. Clicking on the FIX button, or pressing F6 will fix the
error by adding a semicolon to the end of the previous line. A “bip-bip” sound will be generated, and if
there was more than one error line in the error window, PPD would move to the next error.
To manually correct the error, move the cursor to the end of the printf() statement and add the missing
semicolon. If you have a mouse, simply click the left button on the position to which you want to move
the cursor. If you are using the keyboard, move the cursor with the arrow keys. Once the missing
semicolon has been added, you are ready to attempt another compilation.
This time, we will “short circuit” the edit-save-compile cycle by pressing F3 to invoke the “Compile and
link” menu item. PPD will automatically save the modified file to a temporary file, then compile it. The
message window will then display the commands issued to each compiler phase in turn. If all goes well,
you will hear a tone and see the message Compilation successful.
Pacific C Compiler 19
Chapter 3 - Using PPD
To run the program, now open the Run menu, and select the item “Run HELLO.EXE”, or simply press
F7. PPD will disappear, and the program will run in the DOS screen. The message “Hello, world” will
appear, followed by “Press any key to continue”. If you press a key, you will be returned to PPD.
This tutorial has presented a simple overview of single file edit/compile/execute development. PPD is
also capable of supporting multi-file projects (including mixed C and assembly language sources) using
the project facility. The remainder of this chapter presents a detailed reference for the PPD menu system,
editor and project facility.
3
3.4 The PPD Editor
PPD has a built in text editor designed for the creation and modification of program text. The editor is
loosely based on WordStar with a few minor differences and some enhancements for mouse based
operation. If you are familiar with WordStar or any similar editor you should be able to use the PPD
editor without further instruction. PPD also supports the standard PC keys, and thus should be readily
usable by anyone familiar with typical MS-DOS or Microsoft Windows editors.
The PPD editor is based in its own window, known as the edit window. The edit window is broken up
into three areas, the frame, the content region and the status line.
The frame indicates the boundary between the edit window and the other windows on the desktop. The
name of the current edit file is displayed in the top left corner of the frame. If a newly created file is being
edited, the file name will be set to “untitled”. The frame can be manipulated using the mouse, allowing
the window to be moved around the desktop and re-sized.
The content region, which forms the largest portion of the window, contains the text being edited. When
the edit window is active, the content region will contain a cursor indicating the current insertion point.
The text in the content region can be manipulated using keyboard commands alone, or a combination of
keyboard commands and mouse actions. The mouse can be used to position the cursor, scroll the text and
select blocks for clipboard operations.
3.4.1 Status Line
The bottom line of the edit window is the status line, containing the following information about the file
being edited: Line n/m shows the current line number, counting from the start of the file, and the total
number of lines in the file. Col n Shows the number of the column containing the cursor, counting from
the left edge of the window. If the status line includes the text ^K after the Col entry, it indicates that the
editor is waiting for the second character of a WordStar ctrl-K command. See the “Editor Keyboard
Commands” section for a list of the valid ctrl-K commands. If the status line includes the text ^Q after
the Col entry, the editor is waiting for the second character of a WordStar ctrl-Q command. See the
“Editor Keyboard Commands” section for a list of the valid ctrl-Q commands. Insert Indicates
whether text typed on the keyboard will be inserted at the cursor position. Using the insert mode toggle
20
The PPD Editor
command (the Ins key on the keypad, or ctrl-V), the mode can be toggled between Insert and
Overwrite. In overwrite mode, text entered on the keyboard will overwrite characters under the cursor,
instead of inserting them before the cursor.
Indent Indicates that the editor is in auto indent mode. Auto indent mode is toggled using the ctrl-Q
I key sequence. By default, auto indent mode is enabled. When auto indent mode is enabled, every time
a new line is added the cursor will be aligned under the first non-space character in the preceding line. If
the file being edited is a C file, the editor will default to C mode. In this mode, when an opening brace
(‘{‘) is typed, the next line will be indented one tab stop. In addition, it will automatically align a closing 3
brace (‘}’) with the first non-blank character on the line containing the corresponding opening brace.
This makes the auto indent mode ideal for entering C code.
The SEARCH button may be used to initiate a search operation in the editor. To select SEARCH, click
the left mouse button anywhere on the text of the button. The search facility may also be activated using
the F2 key and the WordStar ctrl-Q F sequence. The NEXT button is only present if there has already
been a search operation. It searches forwards for the next occurrence of the search text. NEXT may also
be selected using shift-F2 or ctrl-L. The LAST button is used to search for the previous occurrence of
the search text. This button is only present if there has already been a search operation. The key equivalents
for LAST are ctrl-F2 and ctrl-P.
3.4.2 Keyboard Commands
The editor accepts a number of keyboard commands, broken up into the following categories: Cursor
movement commands, Insert/delete commands, Search commands, Block and Clipboard operations and
File commands. Each of these categories contains a number of logically related commands. Some of the
cursor movement commands and block selection operations can also be performed with the mouse.
Table 3-4 provides an overview of the available keyboard commands and their key mappings. A number
of the commands have multiple key mappings, some also have an equivalent menu item.
The Zoom command, ctrl-Q Z, is used to toggle the editor between windowed and full-screen mode. In
full screen mode, the PPD menu bar may still be accessed either by pressing the ALT key or by using the
middle button on a three button mouse.
3.4.3 Block Commands
In addition to the movement and editing command listed in the “Editor Keyboard Commands” table, the
PPD editor also supports WordStar style block operations and mouse driven cut/copy/paste clipboard
operations. The clipboard is implemented as a secondary editor window, allowing text to be directly
entered and edited in the clipboard. The WordStar style block operations may be freely mixed with mouse
driven clipboard and cut/copy/paste operations.
The block operations are based on the ctrl-K and ctrl-Q key sequences which are familiar to anyone who
has used a WordStar compatible editor.
Pacific C Compiler 21
Chapter 3 - Using PPD
Table 3-5 lists the WordStar compatible block operations which are available.
The block operations behave in the usual manner for WordStar type editors with a number of minor
differences. “Backwards” blocks, with the block end before the block start, are supported and behave
exactly like a normal block selection. If no block is selected, a single line block may be selected by keying
block-start (ctrl-K B) or block-end (ctrl-K K). If a block is already present, any block start or end
operation has the effect of changing the block bounds.
Begin Block ctrl-K B
3 The key sequence ctrl-K B selects the current line as the start of a block. If a block is already present,
the block start marker will be shifted to the current line. If no block is present, a single line block will be
selected at the current line.
End Block ctrl-K K
The key sequence ctrl-K K selects the current line as the end of a block. If a block is already present, the
block end marker will be shifted to the current line. If no block is present, a single line block will be
selected at the current line.
Go To Block Start ctrl-Q B
If a block is present, the key sequence ctrl-Q B moves the cursor to the line containing the block start
marker.
Go To Block End ctrl-Q K
If a block is present, the key sequence ctrl-Q K moves the cursor to the line containing the block end
marker.
Block Hide Toggle ctrl-K H
The block hide/display toggle, ctrl-K H is used to hide or display the current block selection. Blocks
may only be manipulated with cut, copy, move and delete operations when displayed. The bounds of
hidden blocks are maintained through all editing operations so a block may be selected, hidden and
re-displayed after other editing operations have been performed. Note that some block and clipboard
operations change the block selection, making it impossible to re display a previously hidden block.
Copy Block ctrl-K C
The ctrl-K C command inserts a copy of the current block selection before the line which contains the
cursor. A copy of the block will also be placed in the clipboard. This operation is equivalent to a clipboard
Copy operation followed by a clipboard Paste operation.
Move Block ctrl-K V
The ctrl-K V command inserts the current block before the line which contains the cursor, then deletes
the original copy of the block. That is, the block is moved to a new position just before the current line.
A copy of the block will also be placed in the clipboard. This operation is equivalent to a clipboard Cut
operation followed by a clipboard Paste operation.
Delete Block ctrl-K Y
The ctrl-K Y command deletes the current block. A copy of the block will also be placed in the clipboard.
This operation may be undone using the clipboard Paste command. This operation is equivalent to the
clipboard Cut command.
22
The PPD Editor
Pacific C Compiler 23
Chapter 3 - Using PPD
24
PPD Menus
Pacific C Compiler 25
Chapter 3 - Using PPD
2 The ballistic threshold of a mouse is the speed beyond which the response of the pointer to further movement
becomes exponential. Some primitive mouse drivers do not support this feature.
26
PPD Menus
Pacific C Compiler 27
Chapter 3 - Using PPD
28
PPD Menus
Copy alt-C
The Copy option copies the current selection to the clipboard without altering or deleting the selection.
The previous contents of the clipboard are lost.
Paste alt-V
The Paste option inserts the contents of the clipboard into the editor before the current line. The contents
of the clipboard are not altered.
Hide
The Hide option toggles the current selection between the hidden and displayed state. This option is
equivalent to the WordStar ctrl-K H command.
3
Delete selection
This menu option deletes the current selection without copying it to the clipboard. Delete selection should
not be confused with Cut as it cannot be reversed and no copy of the deleted text is kept. Use this option
if you wish to delete a block of text without altering the contents of the clipboard.
Show clipboard
This menu options hides or displays the clipboard editor window. If the clipboard window is visible, it
is hidden. If the clipboard window is hidden it will be displayed and selected as the current window. The
clipboard window behaves like a normal editor window in most respects except that no block operations
may be used. This option has no key equivalent.
Clear clipboard
This option clears the contents of the clipboard, and cannot be undone. If a large selection is placed in
the clipboard, you should use this option to make extra memory available to the editor after you have
completed your clipboard operations.
Go to line ... alt-G
The Go to line command allows you to go directly to any line within the current edit file. You will be
presented with a dialogue prompting you for the line number. The title of the dialogue will tell you the
allowable range of line numbers in your source file.
Set tab size ... alt-T
This command is used to set the size of tab stops within the editor. The default tab size is 8, values from
1 to 16 may be used. For normal C source code 4 is another good value. The tab size will be stored as
part of your project if you are using the Make facility.
Indent
Selecting this item will indent by one tab stop the currently highlighted block, or the current line if there
is no block selected.
Outdent
This is the reverse operation to Indent. It removes one tab from the beginning of each line in the currently
selected block, or current line if there is no block.
Pacific C Compiler 29
Chapter 3 - Using PPD
Comment/Uncomment
This item will insert or remove C++ style comment leaders (//) from the beginning of each line in the
current block, or the current line. This has the effect of commenting out those lines of code so that they
will not be compiled. If a line is already commented in this manner, the comment leader will be removed.
C colour coding
If this option is selected, the editor will display C syntax elements in specified colours. This is especially
useful for finding missing closing comment indicators, etc. Turn this option off when editing a non-C
file that you do not want to be displayed in colour.
3.5.4 Options Menu
The Options menu contains commands which allow selection of compiler options, memory models, and
target processor. Selections made in this menu will be stored in a project file, if one is being used. The
Options menu is shown in figure 3-8.
30
PPD Menus
Pacific C Compiler 31
Chapter 3 - Using PPD
32
PPD Menus
Pacific C Compiler 33
Chapter 3 - Using PPD
34
PPD Menus
Should PPD produce the error “Nothing to make” this indicates that you have not entered any files in the
Source file list...
Re-make ctrl-F5
The Re-make command forces recompilation of all source files in the current project. This command is
equivalent to deleting all .OBJ files and then selecting Make.
Re-link shift-F5
The Re-link command relinks the current project. Any .OBJ files which are missing or not up to date will
be regenerated.
3
Load project file ... alt-P
This command loads a pre-defined project file. The user is presented with a file selection dialogue
allowing a .PRJ file to be selected and loaded. If this command is selected when the current project has
been modified but not saved, the user will be given a chance to save the project or abort the command.
After loading a project file, the message window title will be changed to display the project file name.
Start new project ...
This command allows the user to start a new project. All current project information is cleared and all
items in the Make menu are enabled. The user will be given a chance to save any current project and will
then be prompted for the new project’s name.
Following entry of the new name PPD will present several dialogues to allow you to configure the project.
These dialogues will allow you to select processor type and memory model, output file type, optimization
settings and memory addresses. You will still need to enter source file names in the Source file list.
Save project
This item saves the current project to a file.
Rename project...
This will allow you to specify a new name for the project. The next time the project is saved it will be
saved to the new file name. The existing project file will not be affected (if it has already been saved).
Output file name ...
This command allows the user to select the name of the compiler output file. This name is automatically
setup when a project is created. For example if a project called PROG1 is created and a .EXE file is being
generated, the output file name will be automatically set to PROG1.EXE.
Map file name ...
This command allows the user to enable generation of a symbol map for the current project, and specify
the name of the map. If a mark character appears against this item, map file generation has been selected.
The default name of the map file is generated from the project name, e.g. PROG1.MAP
Pacific C Compiler 35
Chapter 3 - Using PPD
36
PPD Menus
Pacific C Compiler 37
Chapter 3 - Using PPD
Run PROG.EXE. F7
This option runs a compiled program. It is disabled until a program has been compiled, and is updated
to reflect the program name. When selected, PPD will swap itself out of memory and run the program,
with no command line arguments.
Run PROG.EXE with arguments... ctrl-F7
If the program requires arguments, use this option instead. It will prompt with a dialogue box to allow
command line arguments to be supplied for the program.
DOS command ... alt-D
This option allows a DOS command to be executed exactly like it had been entered at the COM-
MAND.COM prompt. This command could be an internal DOS command like DIR, or the name of a
program to be executed. If you want to escape to the DOS command processor, use the DOS Shell
command as below. Warning: do not use this option to load TSR programs. This command will be retained
in the initialization file.
38
PPD Menus
Pacific C Compiler 39
Chapter 3 - Using PPD
e.g. *.c would match all files with file type of .c in the current directory. There is also a check box to
select case-sensitivity in the string search - unless this is checked upper and lower case are not
distinguished in the search.
You can also choose to search the set of files listed in your Source file list in the current project. A radio
button allows you to choose this option, in which case the file list is hidden.
After entering the string and selecting the files, press Enter or click the OK button, and PPD will search
3 the files. The results will be displayed in a small windows at the bottom right of the screen. This consists
of one line per match, with a file name and line number. To go to a particular match, double click on the
entry. Note that the window is small, and there are likely to be additional entries not initially visible - use
the scroll bar at the right to scroll up and down.
To perform another search, you can simply click the Search button in the window - selecting the
Utility/String search menu command again will hide the search results window. You can also hide it by
clicking the close widget in the top left of its frame. The usual methods of resizing and moving the window
work.
Memory Usage Map
This menu option displays a window which contains a detailed memory usage map of the last program
which was compiled. The actual contents of this window will vary between different target processors.
See the processor specific section of the compiler manual for more details about the memory usage map
window.
The memory usage map window may be closed by clicking the mouse on the close box in the top left
corner of the frame, or by pressing ESC while the memory map is the front most window.
Calculator
This command selects the HI-TECH Software programmer’s calculator. This is a multi-display integer
calculator capable of performing calculations in bases 2 (binary), 8 (octal), 10 (decimal) and 16
(hexadecimal). The results of each calculation are displayed in all four bases simultaneously. Operation
is just like a “real” calculator - just press the buttons! If you have a mouse you can click on the buttons
on screen, or just use the keyboard. The large buttons to the right of the display allow you to select which
radix is used for numeric entry.
The calculator window can be moved at will, and thus can be left on screen while the editor is in use. The
calculator window may be closed by clicking the OFF button in the bottom right corner, by clicking the
close box in the top left corner of the frame, or by pressing ESC while the calculator is the front most
window.
Ascii Table
This option selects a window which contains an ASCII look up table. The ASCII table window contains
four buttons which allow you to close the window and select display of the table in octal, decimal or
hexadecimal.
40
PPD Menus
The ASCII table window may be closed by clicking the CLOSE button in the bottom left corner, by
clicking the close box in the top left corner of the frame, or by pressing ESC while the ASCII table is the
front most window.
Define user commands...
In the Utility menu are four user-definable commands. This item will invoke a dialogue box which will
allow you to define those commands. By default the commands are dimmed (not selectable) but will be
enabled when a command is defined. Each command is in the form of a DOS command, with macro
substitutions available. The macros available are listed in table 3-6.
Each user-defined command has a hot key associated. They are shift F7 through shift F10, for commands
1 to 4. When a user command is executed, the current edit file, if changed, will be saved to a temporary
file, and the $(EDIT) macro will reflect the saved temp file name, rather than the original name. On return,
if the temp file has changed it will be reloaded into the editor. This allows an external editor to be readily
integrated into PPD.
Pacific C Compiler 41
Chapter 3 - Using PPD
42
Runtime Organization
The runtime environment of Pacific C is quite straightforward; this is to a large degree due to the C
language itself. C does not rely on a large runtime support module, rather there are a few library routines
which are basic to the language, while all other runtime support is via specific library packages, e.g. the
STDIO library.
Pacific C Compiler 43
Chapter 4 - Runtime Organization
push bp
mov bp,sp
sub sp,#10
push si
push di
This will allocate 10 bytes of stack space for local variables. The stack frame after this code will look
something like figure 4-1.
All references to the local data or parameters are made via bp. The first argument is located at 8[bp] for
the small memory model, and at 10[bp] for the large memory model. Each parameter occupies at least 2
4 bytes. If a char is passed as an argument, it is expanded to int length.
44
Prototyped Function Arguments
Pacific C Compiler 45
Chapter 4 - Runtime Organization
q When a function is called from C code, the registers bp, si and di must be preserved. If they are to
be used, they should be saved on the stack and restored before returning. All other registers may be
destroyed. Similarly, when calling a C function, an assembler routine should expect only those
registers to be unmodified.
q All C external names have an underscore prepended. Any assembler symbol to be referenced from
C must start with an underscore, which should be omitted when using the name in C code.
q Return values are in ax for words, and ax and dx for long words, with the high word in dx. Byte
returns are in al but sign or zero extended as appropriate into ah. Floating point functions take
arguments on the stack, but return values in DX and AX (32 bit floats), BX, CX, DX and AX (64
bit floats). The registers are listed in descending order of significance, i.e. AX will have the least
4 significant bits.
4.6.1 Assembler Interface Example
The following piece of code illustrates a function to be called from C (small memory model only) which
allows access to memory outside the programs allocated memory. The function is called peek(), and
takes two arguments, representing the segment and offset parts of the address to be examined.
; peek(seg, offs)
; returns the byte at the
; specified physical address
.psect _TEXT
.globl _peek
_peek:
push bp
mov bp,sp
mov es,4[bp] ;get segment
mov bx,6[bp] ;offset part
mov al,es:[bx] ;get the byte
mov ah,#0 ;zero hi byte
pop bp
ret ;finito
This function would be edited into a file called PEEK.AS. This may then be linked into a C program, e.g.
by the command line
PACC -V MAIN.C PEEK.AS
If this function was prototyped, the argument passing would differ. For example:
46
Linkage to Assembler
.psect _TEXT
.globl _peek
_peek:
mov es,dx ;segment part
mov bx,ax ;offset part
mov al,es:[bx]
mov ah,#0
ret
4
Note how much simpler the passing of arguments in DX and AX makes the code. But remember that this
is only done if the function is prototyped.
4.6.2 Signatures
Because the differing calling conventions make it possible for a function to be called with incorrect calling
sequences, the compiler and linker implement a feature called signatures. This is a means of allowing
the linker to check that the declarations of a function are all consistent. The compiler automatically
generates a signature for a function whenever it is called or defined. If you write an assembler language
function you may opt to provide a signature to check that you are using it correctly when calling it. To
get the correct signature, place a definition of the function in a sample C file, compile to assembler and
copy the signature. E.g.
unsigned int
peek(unsigned seg, unsigned offs)
{
return 0;
}
When compiled to assembler (using the -S option to C.EXE or the “Compile to .AS” menu selection of
HPD) you will get a line in the .AS file of the form:
.signat _peek,8250
Simply copy this line into your assembler file. This will allow the linker to check this against the compiler
generated signatures from references to this function. Note that this does not guarantee you have written
code that correctly accesses the arguments, etc. This is still up to you to ensure.
Pacific C Compiler 47
Chapter 4 - Runtime Organization
48
Linking 8086 Programs
to read the following discussion several times and try examples before becoming comfortable with using
the linker directly. In most cases you will not need to use the linker directly, as the C.EXE and HPD.EXE
drivers will automatically run the linker with correct options.
4.8.1 Terms 4
Two terms are used to describe sections of memory, and it is important to understand the distinction. A
psect is a section of memory treated by the linker as a contiguous block. When linking 8086 programs a
psect will not normally exceed 64k in size. A segment is a block of memory up to 64k in size addressed
(or pointed to) by a segment register. Locations within the segment are addressed by offsets from the
segment register. The contents of the segment register is referred to as the segment address of the segment,
and is equal to the physical memory address of the segment divided by 16. Since the segment address
must be an integer, this implies that all segments must begin on a 16 byte boundary in physical memory.
In normal use one or more psects will be addressed within one segment.
4.8.2 Link and Load Addresses
The HI-TECH linker deals with two types of addresses called link and load addresses. The manner in
which these addresses are specified for a psect is detailed in the linker section, but it is necessary to discuss
how the two types of addresses fit into the 8086 run-time model.
4.8.3 Segmentation
The 8086 has a segmented architecture, where all addresses are represented as 16 bit offsets from segment
registers. The segment registers are each 16 bits but are left shifted 4 bits before use and can thus address
1 megabyte of memory. Every memory reference involves a physical memory address calculated by
adding to the shifted segment address a 16 bit offset derived from the instruction operand. Thus the 8086
requires addresses to be split into segment parts and offset parts. These correspond to load and link
addresses respectively.
4.8.4 Link Addresses
The link address of a psect is to the linker the address that will be used in all normal relocation calculations,
i.e. if a relocation requires that the base address of a psect be added to a memory location then it will be
the link address of that psect that will be added. Similarly if relocation by an external symbol is required,
Pacific C Compiler 49
Chapter 4 - Runtime Organization
it will be performed by adding to the memory location the base address of the psect in which the external
symbol is defined plus the offset of that symbol from the base of the psect. These calculations correspond
to calculating offset addresses for the 8086 instructions.
4.8.5 Load Addresses
The load address of a psect is to the linker the physical address of the psect, i.e. its actual location in the
excutable image file. At the time an excutable program is loaded into memory by an operating system
its physical location in memory will be determined by the operating system, but the relative position of
data in the file will be maintained. We will discuss later what action is required to compensate for the
fact that the linker cannot know where in memory the program will execute. As far as the linker is
concerned the physical address of a psect is its address relative to the beginning of the executable file.
4
Load addresses are thus the basis of the segment part of 8086 addresses; however they are not the same,
since load addresses, like all addresses handled by the linker, are linear 32 bit values, while the segment
part of an address is only the top 16 bits of a 20 bit value. Thus to convert a load address to a segment
address the linker must right shift it 4 bits, or divide it by 16. 16 happens to be the relocatability quantum
of 8086 psects, and it is via the reloc=16 flag on a .psect directive that the linker knows to divide by 16
to convert a load address to a segment address. For this reason it is important to have a reloc=16 flag on
all initial psect definitions (it is only necessary to do this in one module for each global psect).
4.8.6 Linking and the -P option
When linking an 8086 program it is very important to understand what arguments should be given to the
linkers -P option in order to correctly link the program.
A small model 8086 program has two segments; the code (or text) segment and the data segment. The
code segment is addressed by the CS register, while the data segment is addressed by the DS register.
The SS register is also set to point to the data segment (i.e. has the same value as the DS register) since
the stack is a part of the data segment. The psects that make up a small model program are each placed
into one of the two segments. The C compiler uses 3 psects for small model programs. These are the
_TEXT psect, which is placed into the code segment, and the data and bss psects, which are both placed
in the data segment (the data psect comes before the bss psect).
The offset addresses of each segment begin at 0, since the segment register associated with each segment
points to the base of that segment. Thus the link addresses of the _TEXT and data psects will both be 0,
since each starts at the beginning of their segments. The link address of the bss psect will be equal to the
size of the data psect, rounded up to a 16 byte multiple.
The load addresses of each psect must, however, be different, since it would be impossible (or at least
useless) for the _TEXT and data psects to occupy the same physical memory (or file) space. This is the
reason for allowing the specification of link and load addresses separately. While two psects may have
50
Linking 8086 Programs
overlapping link addresses their load addresses must be disjoint. The diagram in figure 4-4 illustrates the
arrangement of addresses for a program with a _TEXT psect 1234(hex) bytes long, a data psect 453(hex)
bytes long, and a bss psect 105(hex) bytes long.
The values inside the boxes represent offset addresses. When linking this program the C compiler will
supply a -P option like this:
-P_TEXT=0,text,data=0/,bss
This sets up the psect link and load addresses as follows: the _TEXT psect is given a link address of 0.
Since its load address is unspecified it defaults to the same as the link address. The text psect is
semantically equivalent to the _TEXT psect and is included here for backwards compatibility with older
Pacific C compilers. It has no ‘=’ sign so it is concatenated for both link and load addresses with _TEXT.
In practice the text psect will always be empty.
The data psect has its link address set to 0 (remember the link address appears immediately after the ‘=’
sign). Following the link address is a ‘/’ character which introduces a load address, however the load
address is omitted. This indicates to the linker that the load address should follow on from the previous
psects load address, i.e. that the data psect should immediately follow the text psect in physical memory.
The bss psect has no link or load address specified, so it is concatenated with data. Thus this achieves
the layout shown in fig. 2. Note that as far as the linker is concerned the program is to be loaded in memory
Pacific C Compiler 51
Chapter 4 - Runtime Organization
at physical 0. If it is to be run under MS-DOS then it will of course be loaded somewhere else. This does
not matter in the case of the small model program as all addresses within the program are offset addresses,
derived from link addresses.
A large model program has more than two segments: it has the same data segment as a small model
program, but a separate stack segment and multiple code segments. One of the code segments corresponds
to the small model code segment in that it contains the _TEXT and text psects but there are additional
code segments each containing one local psect named ltext. There is one of these ltext psects for each C
source module. A typical large model program might be laid out as in figure 4-5.
While the CS register is shown as pointing to the base of the _TEXT psect, during execution it will point
to the base of other code segments when they are executing. This is achieved via the far (or inter-segment)
call and return instructions used in large model programs. The DS register always points to the data
52
Absolute Variables
segment, and the SS register always points to the stack segment. If the amount of memory available for
the stack and data segments combined is less than 64K then the SS register will be set to the base of the
data segment. In this case the stack pointer SP will be initialized with a value less than 64K. The -P option
to the linker to achieve this layout would be:
-P_TEXT=0,text,CODE=0/,data=0/,bss,stack=0/
Compare this with the -P option for the small model and note the addition of the CODE class-name and
the stack psect. The CODE class embraces all the ltext psects, and allows all the ltext psects to be referred
to by one entry in the -P option list. The zero link address and concatenated load address given after
CODE is applied to each ltext psect in turn. The stack psect is also given a link address of 0 and a load
address concatenated with bss. It will be noticed that all psects are concatenated with the previous for 4
load address. This is of course required to ensure that all psects occupy disjoint physical memory.
Since the large model does embed segment addresses in the code, it is necessary for any such addresses
to be relocated (or fixed up) when MS-DOS loads the program into memory. MS-DOS is quite happy to
perform the fixups, but it must be given the information on what addresses to fixup. This is achieved by
the C compiler in a two step process. The linker has a -LM option which directs the linker to retain in
the output file information about what addresses were subjected to a segment relocation. This information
is then used by objtohex to build a list of addresses in segment:offset form which is then placed into the
.EXE file In the .EXE file the addresses are placed in the .EXE header. MS-DOS goes through this list
after loading the program and adjusts the memory locations specified. Each word location has the
programs base segment address added to it.
Pacific C Compiler 53
Chapter 4 - Runtime Organization
54
8086 Assembler Reference
Manual
5.1 Introduction
The assembler incorporated in the Pacific C compiler system is a full-featured relocating macro
assembler. The syntax of the language accepted is not the same as the Intel (or Microsoft) assembler, but
the opcode mnemonics are largely compatible. A discussion of the differences in detail follows later.
AS86 is an optimizing assembler; it will produce the smallest possible code for given input by producing
short jumps and using short addressing forms wherever possible. This feature does require, however, that
more than two passes are made over the source code. This results in slower assembly times but an option 5
is provided (-Q) which will perform a quick assembly, using only two passes, and insert no-ops wherever
necessary to compensate for optimizations performed on the second pass which were not done on the
first pass (e.g. short branches forward).
5.2 Usage
The assembler is named AS86, and is invoked as follows:
AS86 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:
5.2.1 -Q
The -Q option provides a quick assembly, as discussed above.
5.2.2 -U
Treat undefined symbols as external. The -U option will suppress error messages relating to undefined
symbols. 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.
Pacific C Compiler 55
Chapter 5 - 8086 Assembler Reference Manual
5.2.3 -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
AS86 file1.as file2.as
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:
AS86 -Ox.obj file1.as
will place the object code in x.obj.
5.2.4 -Llist
Place an assembly listing in list, or on standard output if list is null.
5
5.2.5 -Wwidth
The listing is to be formatted for a printer of given width. The default width is 80 columns if the listing
is going to a device (e.g. a printer) or 132 columns if going to a file.
5.2.6 -X
Do not include local symbols in the output file. This reduces the size of the object file. Local symbols
are not used by the linker and are of use only for debugging.
5.2.7 -E
Suppress the listing of errors on the console. Error codes will still be included in the listing.
5.2.8 -M
Generate Intel compatible object code rather than HI-TECH Software proprietary object code. The object
module thus generated will be able to be linked with the MS-DOS linker or another linker accepting
standard Intel object code format, but not the HI-TECH linker.
5.2.9 -1,-2,-3,-4
Permit the assembly of the extra instructions supported by the the 80186, 286, 386 or 486 processors. If
an instruction is encountered that is not supported by the selected processor, an error will occur. This
facility is also available with the .186, .286, .386 and .486 directives.
56
The Assembly Language
5.2.10 -N
Suppress checking for arithmetic overflow. The assembler performs arithmetic internally in 32 bits but
reports overflows out of the lower 16 bits. The -N option suppresses this checking.
5.2.11 -I
Force listing of include files, even if .nolist directives are encountered.
5.2.12 -S
Suppress error messages which would be generated through initializing a byte memory location with a
quantity which will not fit in 8 bits.
5.2.13 -C
Generate cross reference information. The raw cross reference data will be written to a file derived from
the name of the first source file, with the suffix .crf. The cross reference generator CREF must then be
used to produce the actual cross reference listing. 5
5.3 The Assembly Language
The assembly langugage follows the Intel mnemonics, with the following differences:
q The opcode forms such as movsb and movsw are not provided; to indicate the operand size where
it is not otherwise defined the additional operands byte or word should be used, e.g. movs word
instead of movsw.
q Since no provision is made for declaring labels or functions as far or near, additional forms of the
jmp, call and ret opcodes are provided to indicate inter-segment control transfers. These are formed
by adding an f suffix to the opcode, e.g. callf.
q Additional opcodes are provided which allow long conditional branches to be indicated. These
opcodes are formed by substituting the j in a branch opcode with br, e.g. brnz. This will assemble
to a short branch if possible, otherwise to a short branch of the opposite condition around a long
unconditional jump.
5.3.1 Symbols
The symbols (labels) accepted by the assembler may be of any length, and all characters are significant.
The characters used to form a symbol may be chosen from the upper and lower case alphabetics, the digits
0-9, and the special symbols underscore (‘_’), dollar (‘$’) and question mark (‘?’). The first character
may not be numeric. Upper and lower case are distinct. Note that there is no distinction between labels
appearing in code or in data; there is no concept of a variable with attributes. The following are all legal
and distinct symbols.
Pacific C Compiler 57
Chapter 5 - 8086 Assembler Reference Manual
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.
See the discussion of addressing modes below for differences in referencing symbols, compared with the
Intel or Microsoft assemblers.
5.3.1.1 Temporary Labels
The assembler implements a system of temporary labels, useful for use within a localized section of
5 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: ;referenced elsewhere
mov cl,#10
1: dec bx
jnz 2f ;branch forward
mov bx,#8
loop 1b ;loop back to 1:
jmp 1f ;branch forward
58
The Assembly Language
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.
5.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 set listed in table 5-1.
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:.
5.3.2.1 Character Constants 5
A character constant is a single character enclosed in single quotes (‘).
5.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 .FLOAT
pseudo-op.
5.3.3 Expressions
Expressions are constructed from symbols, constants and operators.
5.3.3.1 Operators
The operators shown in table 2-2 may be used in expressions.
5.3.3.2 Relocatability
AS86 produces object code which is relocatable; this means that it is not necessary to specify at assembly
time where the code is to be located in memory. It is possible to do so, however the preferred approach
is to use relocatable 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 code below will load some executable instructions into the psect named text, and
some data bytes into the data psect.
.psect text, global
Pacific C Compiler 59
Chapter 5 - 8086 Assembler Reference Manual
Operator Meaning
& Bitwise AND
* Multiplication
+ Addition
- Subtraction
.and. Bitwise AND
.eq. Equality test
.gt. Signed greater than
.high. Hi byte of operand
.low. Low byte of operand
5 .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
.seg. The segment part of an address
seg Same as .seg.
call putit
mov bx,#anotherstring
60
The Assembly Language
.psect text
putit:
mov al,[bx]
or al,al
bz 1f
call outchar
inc bx
jmp putit
1: ret
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 “mov bx,#another-
string” will fall through to the label “putit:” during execution. The actual location in memory of the two 5
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, i.e. 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 absolute (see the .PSECT pseudo-op description below). Any labels declared in an absolute
psect will be absolute, i.e. their address will be determined by the assembler.
5.3.4 Pseudo-ops
The pseudo-ops are described below.
5.3.4.1 .BYTE
This pseudo-op should be followed by a comma-separated list of expressions, which will be assembled
into sequential byte locations. Each expression must have a value between -128 and 255 inclusive, or can
be a multi-character constant. Example:
.BYTE 10, 20, ‘axl’, 0FFH
5.3.4.2 .WORD
This operates in a similar fashion to .BYTE, except that it assembles expressions into words, which may
range -32767 to 65535, and character strings are not acceptable. Example:
.WORD -1, 3664H, ‘A’, 3777Q
5.3.4.3 .DWORD
The .DWORD pseudo-op is similar to .WORD, but assembles double word quantities (32 bits).
Pacific C Compiler 61
Chapter 5 - 8086 Assembler Reference Manual
5.3.4.4 .FLOAT
This pseudo-op will initialize a memory location to the binary representation of the floating point number
given as an argument. The default conversion is to a 4 byte floating number, but the variant .FLOAT8
will convert to an 8 byte number. Example:
.FLOAT 23.12e4
5.3.4.5 .BLKB
This pseudo-op reserves memory locations without initializing them. Its operand is an absolute expres-
sion, representing the number of bytes to be reserved. This expression is added to the current location
counter. Note however that locations reserved by .BLKB may be initialized to zero by the linker if the
reserved locations are in the middle of the program. Example:
.BLKB 20h ; reserve 16 bytes of memory
5 5.3.4.6 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
5.3.4.7 SET
This is identical to EQU except that it may redefine existing symbols. Example:
SIZE set 48
5.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.
Only one start address may be defined per program, and the linker will complain if there are more.
Example:
.END somelabel
5.3.4.9 IF
Conditional assembly is introduced by the .IF pseudo-op. The operand to .IF must be an absolute
expression. If its value is false (i.e. zero) the code following the .IF up to the corresponding .ENDIF
pseudo-op will not be assembled. .IF/.ENDIF pairs may be nested. Example:
62
The Assembly Language
.IF Debug
call trace ;trace execution
.ENDIF
5.3.4.10 .ENDIF
See .IF.
5.3.4.11 .ENDM
See .MACRO.
5.3.4.12 .PSECT
This pseudo-op allows specification of relocatable program sections. Its arguments are a psect name,
optionally followed by a list of psect flags. The psect name is a symbol 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: 5
5.3.4.12.1 ABS
Psect is absolute
5.3.4.12.2 GLOBAL
Psect is global
5.3.4.12.3 LOCAL
Psect is not global
5.3.4.12.4 OVRLD
Psect is to be overlapped by linker
5.3.4.12.5 PURE
Psect is to be read-only
5.3.4.12.6 SIZE
Allows max size of the psect to be set, e.g. SIZE=65535
5.3.4.12.7 RELOC
Allows relocation granularity of the psect to be set, e.g. for the 8086 since all segments must start on a
16 byte boundary, most psects will have a RELOC=16 flag.
Pacific C Compiler 63
Chapter 5 - 8086 Assembler Reference Manual
5.3.4.12.8 CLASS
Allows local psects to have a class-name associated with them, for use in -P options to the linker. E.g.
CLASS=txtgrp
5.3.4.12.9 STACKSEG
This flag is effective only when generating Intel object code and is used to let the linker know that this
psect is to be a stack segment. The MS-DOS linker will set the initial stack segment value to the base of
this psect.
5.3.4.12.10 USE32
This psect flag informs the assembler that code in this psect will be executed in an 80386/486 segment
with the D bit set, and thus the default operand and address size will be 32 bits. By default the assembler
assumes 16 bit operands and addressing. This flag may be used only if a .386 or .486 directive or a -3 or
-4 option has been used.
5
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 operating system to enforce the requirement.
The ABS flag makes a psect absolute. The psect will be loaded at zero. Examples:
.PSECT text, global, pure
.PSECT data, global
.PSECT vectors, ovrld, reloc=100h
.PSECT ltext, local, class=txtgrp,reloc=16,size=65535
5.3.4.12.11 .GROUP
This pseudo-op is used only with the -M option, i.e. when generating Intel compatible object code. It
allows the naming of a group and associate psects. The significance of a group is that the MS-DOS linker
will ensure that all members of a group are located within the same 64K segment. Even more important
is that all addressing within segments in that group will be calculated with the group as the reference
frame, rather than the psect itself. This is necessary with the Intel object code relocation scheme to ensure
correct relocation. Example:
64
The Assembly Language
.GROUPDGROUP,data,bss
5.3.4.13 .GLOBL
The directive .GLOBL 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:
.GLOBL label1, putchar, _printf
5.3.4.14 .LOC
An .LOC pseudo-op sets the the location counter in the current psect to its operand, which must be an
absolute expression. This directive does not change the current psect. To generate absolute code, you
must use a .PSECT directive, specifiying ABS,OVRLD. Example:
.LOC 100H
5.3.4.15 .MACRO and .ENDM 5
These directives provide for the definition of macros. The MACRO directive should be preceded by the
macro name and followed by a comma-separated list of formal parameters. When the macro is used, the
macro name should be used in the same manner as a machine opcode, followed by a list of arguments to
be substituted for the formal parameters. For example:
copy loc1,loc2
; expands to:
mov ax,loc1
mov loc2,ax
copy loc1,loc2,x_
; expands to:
mov ax,loc1_x
Pacific C Compiler 65
Chapter 5 - 8086 Assembler Reference Manual
mov loc2_x,ax
Points to note in the above example: in the first expansion the third argument was unspecified, so nothing
was substituted for it; the & character is used to permit the concatenation of macro parameters with other
text, but is removed in the actual expansion; this enabled the _x argument to the third parameter in the
second expansion to form part of the operands.
The NUL operator may be used within a macro to test a macro argument. A comment may be suppressed
within the expansion of a macro (thus saving space in the macro storage) by opening the comment with
a double semicolon (;;).
5.3.4.16 .LOCAL
The LOCAL directive allows unique labels to be defined for each expansion of a given macro. Any
5 symbols listed after the LOCAL directive will have a unique assembler-generated symbol substituted for
them when the macro is expanded. For example:
xxx .MACRO src,dst,cnt
.LOCAL back
mov cx,#cnt
mov ah,#0
back: mov al,[src]
mov [dst],ax
inc src
add dst,#2
loop back
.ENDM
xxx si,di,23
; expands to
mov cx,#23
mov ah,#0
??0001: mov al,[si]
mov [di],ax
inc si
add di,#2
loop ??0001
66
The Assembly Language
5.3.4.17 .REPT
The .REPT directive temporarily defines an unnamed macro then expands it a number of times as
determined by its argument. For example:
.REPT 3
movs word
.ENDM
; expands to
movs word
movs word
movs word
; expands to
mov ax,lab1
stos word
mov ax,lab2
stos word
mov ax,#23
stos word
.IRPC arg,1982
imul ax,#10
add ax,#arg
.ENDM
Pacific C Compiler 67
Chapter 5 - 8086 Assembler Reference Manual
; expands to
imul ax,#10
add ax,#1
imul ax,#10
add ax,#9
imul ax,#10
add ax,#8
imul ax,#10
add ax,#2
68
The Assembly Language
will cause the text of macrodefs.i to be included in the assembly at the point at which the directive
appears. The .INCLUDE directive will not be listed.
5.3.4.24 .LIST
This directive and the corresponding .NOLIST turn listing on and off respectively. Note that if these
directives are used in a macro or include file, the previous listing state will be restored on exit from the
macro or include file. This allows the selective listing or otherwise of macros. For example:
fred .MACRO
.NOLIST
;This line will not appear in the listing file.
.ENDM
5.3.5.2 Immediate
Immediate addressing is indicated by a ‘#’ character. This also applies to int instructions. Examples:
int #0E0h
mov al,#2
mov si,#alabel
If you are used to the Intel or Microsoft assemblers then it is important to understand the difference in
the way immediate addressing is handled. In the Microsoft style of assembler immediate addressing is
assumed when a constant (e.g. 345) or a label (i.e. a label in code, as opposed to a label identifying data,
which is treated as a variable) is referenced. When a variable is referenced then direct addressing is
assumed. Thus the assembler (and the programmer) must know what kind of operand is being addressed
to decide whether immediate or direct addressing is to be used. To force immediate addressing with a
variable the operator offset must be used.
Pacific C Compiler 69
Chapter 5 - 8086 Assembler Reference Manual
The HI-TECH assembler always uses direct addressing when a label or constant is referenced unless the
‘#’ character is present. In this case immediate addressing is always used.
5.3.5.3 Direct
Direct addressing requires simply the address expression of the target. A byte or word operand may be
required, as with other memory addressing modes, where the operand size is not otherwise determinable.
Examples:
inc fred
mov cs:alabel+4,#5,byte
mov ax,some_address
mov 10,cs
5.3.5.5 Indexed
Indexed addressing in general, including indexing from the registers bp, bx, si and di requires the one or
two register names, each enclosed in square brackets, to be preceded by an offset. The usual restrictions
on which registers may be used in a double indexed mode apply. The order of the registers is not important.
Examples:
mov al,10[bx]
mov an_offset[bp][si],#23h,word
mov [si][bx],dx
Note here that the Microsoft assembler requires constant offsets to be inside the square brackets, e.g.
[si+10], while variable names should be outside the brackets, e.g. fred[si]. The HI-TECH assembler
always expects to see offset expressions outside the brackets (it is normal for the offset expression to
precede the brackets, but not essential), e.g. 10[si] or fred[si].
5.3.5.6 String
String instructions require a byte or word operand to permit the assembler to determine the size of the
data to be moved. No other operands are acceptable to the string instructions, however if a segment
override is required, it can be added. Examples:
70
The Assembly Language
5.3.5.7 I/O
I/O addressing is treated in the same manner as direct addressing, or register indirect addressing (for dx
only). Examples:
in al,a_port
out [dx],ax
Pacific C Compiler 71
Chapter 5 - 8086 Assembler Reference Manual
lfs eax,10[esp]
mov ax,gs:[bx][di]
5.3.6.2 String
The string instructions take the same form as on the 8086, except that 32 bit quantities may also be moved
using the dword operand. Segment overrides are used in the normal manner. Example:
cmps byte
stos dword
movs word,gs:
5.4 Diagnostics
An error message will be written on the standard error stream for each error encountered in the assembly.
This message 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 following
listing presents the error messages in alphabetical order with an explanation of each.
32 bit addressing illegal
32 bit addressing (i.e. using 32 bit registers in an index expression) is illegal unless generating 386 or
486 code. Use a .386 or .486 directive at the beginning of the file.
80186 instruction/addressing mode
An instruction or addressing mode not supported by the 8088/8086 was encountered. Use a .186, .286.
.386 or .486 directive to allow these.
80286 instruction
An instruction peculiar to the 80286 encountered. Use a .286. .386 or .486 directive to allow these.
72
Diagnostics
Pacific C Compiler 73
Chapter 5 - 8086 Assembler Reference Manual
74
Diagnostics
operand error
The operand to this opcode is invalid. Check you Z80 reference manual.
operand size undefined
undefined operand size
The size of the operand to this instruction was not defined. Use “,byte” or “,word”, or “,dword” as
appropriate.
page width must be >= 41
The listing page widthe must be at least 41 characters. Any less will not allow a properly formatted listing
to be produced.
phase error
phase error in macro args
The assembler has detected a difference in the definition of a symbol on the first and a subsequent pass.
pop immediate illegal
It is not possible to pop into an immediate value.
psect * in more than one group
This psect has been defined to be in more than one group. 5
psect may not be local and global
A psect may not be declared to be local if it has already been declared to be (default) global.
psect reloc redefined
The relocatability of this psect has been defined differently in two or more places.
psect selector redefined
The selector associated with this psect has been defined differently in two or more places.
psect size redefined
The maximum size of this psect has been defined differently in two or more places.
radix value out of range
The value given for the current radix is out of range. It must be between 2 and 16.
relocation error
It is not possible to add together two relocatable quantities. A constant may be added to a relocatable
value, and two relocatable addresses in the same psect may be subtracted. An absolute value must be
used in various places where the assembler must know a value at assembly time.
remsym error
Internal error.
rept argument must be >= 0
The argument to a “REPT” directive must be greater than zero.
scale value invalid
The scale value in the operand is invalid. It may only be 1, 2, 4 or 8.
scale value must be a constant
The scale value in an operand must be an absolute constant.
Pacific C Compiler 75
Chapter 5 - 8086 Assembler Reference Manual
size error
You have attempted to store a value in a space that is too small, e.g. trying to initialize a byte location
with an address that is 16 bits.
syntax error
A syntax error has been detexted. This could be caused a number of things.
too many errors
There were too many errors to continue.
too many macro parameters
There are too many macro parameters on this macro definition.
too many symbols
There are too many symbols to fit into the symbol table.
too many temporary labels
too may symbols
There are too many symbols for the assemblers symbol table. Reduce the number of symbols in your
5 program.
undefined symbol *
The named symbol is not defined, and has not been specified “GLOBAL”.
undefined temporary label
A temporary label has been referenced that is not defined. Note that a temporary label must have a number
>= 0.
unknown directive
This directive is not known to the assembler.
write error on object file
An error was reported when the assembler was attempting to write an object file. This probably means
there is not enough disk space.
76
Lucifer - A Source Level
Debugger
6.1 Introduction
Lucifer is a source level debugger for use with the Pacific C compiler for the 8086 family. This version
of Lucifer is capable of operating with 8086 family chips up to and including the 80286, it will work
correctly in real mode on an 80386 or 80486 but does not handle the 80386 instruction set.
Lucifer provides a debugging environment which allows source code display, symbolic disassembly,
memory dumps, instruction single stepping and tracing, breakpoints, and many other functions.
Lucifer is provided with the standard version of Pacific C for debugging DOS executable programs. With
the ROM development edition of Pacific C you also get a remote version of Lucifer for debugging in a
target system, connected via a serial link to your PC. When using PPD, the appropriate debugger will be
selected depending on what kind of executable program you are generating. See the chapter “ROM
Development with Pacific C” for more information on remote debugging.
6
6.2 Usage
To use Lucifer you should compile your program with a -G option. This will produce a symbol file with
line number and filename symbols included. If you use a -H option you will get a symbol file but without
the filename and line number symbols. If using PPD, select the Source Level Debug Info menu entry
from the Options menu. From within PPD you can also invoke Lucifer from the Run menu, rather than
using the command line as described below.
To compile a program “TEST.C” for use with the debugger, use the command:
PACC -GTEST.SYM TEST.C
Then invoke Lucifer as follows:
LUCIFER TEST.EXE TEST.SYM [arguments]
Lucifer will display a signon message, then attempt to load the specified executable and symbol files. It
then prints a colon prompt ‘:’ and waits for commands. For a list of commands, type the command ?.
Note that all commands should be in lower case. Symbols should be entered in exactly the same case as
they were defined. Any command line arguments typed after the name of the symbol file are passed
through to the user program as argv[1], etc. Where an expression is required, it may be of the form:
Pacific C Compiler 77
Chapter 6 - Lucifer - A Source Level Debugger
symbol_name
symbol+hexnum
symbol-hexnum
$hexnum:[$hexnum]
:linenumber
i.e. a symbol name (e.g. main), a symbol name plus a hex offset (e.g. afunc+1a), a symbol minus a hex
offset, a hex number preceded by a dollar sign, or a line number preceded by a colon.
Symbol references and line numbers always resolve to full 32 bit addresses (segment:offset). Non
symbolic addresses may be entered by specifying either a segment:offset pair or just the offset. If only
an offset is given, the segment value defaults to the last segment accessed, unless the offset specified is
one of the pointer registers ip, sp or bp, in which case the segment value is taken from the appropriate
segment register (cs for ip, ss for sp and bp). In all cases except line numbers, a constant may be added
or subtracted from the offset part of the address. Note that address arithmetic never changes the segment
value, wrapping around within the segment if overflow or underflow occurs.
6 More examples:
In the b (breakpoint) command any decimal number will be interpreted as a line number by default, while
in the u (unassemble) command any number will be intepreted as a hex number representing an address
by default. These assumptions can always be overridden by using the colon or dollar prefixes.
When entering a symbol, it is not necessary to type the underscore prepended by the C compiler, however
when printing out symbols the debugger will always print the underscore. Any register name may also
be used where a symbol is expected.
6.3 Commands
6.3.1 The A Command: set command line arguments
The a command is used to set the command line arguments. When the user program is run, argc is set
to the number of arguments typed, argv[1] is set to the first argument typed, argv[1] to the second, and
so on. argv[0] is always a NULL pointer.
78
Commands
Pacific C Compiler 79
Chapter 6 - Lucifer - A Source Level Debugger
: s
result = 20
Stepped to
10:}
:
: s
_main+4D PUSH _result
_main+51 MOV DX,#0083
_main+54 PUSH DX
_main+55 CALL _printf
result = 20
_main+58 ADD SP,#04,WORD
Stepped to
10:}
80
Commands
: s
Pacific C Compiler 81
Chapter 6 - Lucifer - A Source Level Debugger
Stepped to
7: scanf(“%d”,&value);
: s
Target wants input: 7
Stepped to
8: result = (value << 1) + 6;
: s
Stepped to
9: printf(“result = %d\\n”,result);
: s
result = 20
Stepped to
10:}
:
6
6.3.10 The T Command: trace one instruction
The t command is used to trace one machine instruction on the target. The current value of PC (the
program counter) is used as the address of the instruction to be executed. After the instruction has been
executed, the next instruction and the contents of all registers will be displayed.
6.3.11 The U Command: disassemble
The u command disassembles object code from the target system’s memory. If an expression is supplied,
the disassembly commences from the address supplied. If an address is not supplied, the disassembly
commences from the instruction where the last disassembly ended. The disassembler automatically
converts addresses in the object code to symbols if the symbol table for the program being disassembled
is available. If the source code for a C program being disassembled is available, the C lines corresponding
to each group of instructions are also displayed. Note: any values specified will be interpreted as absolute
addresses by default, if you want to specify a line number, prefix it with a colon.
: u :10
10: answer += (value + 7) << 1;
_main+1B MOV DX,_value
_main+1F ADD DX,#07,WORD
_main+22 SHL DX,#1
_main+24 ADD _answer,DX
11: printf(“answer = %d\\n”, answer);
82
Commands
where t is the type of the variable to be displayed, m consists of zero or more modifiers which effect the
way the type is displayed, i consists of zero or more indirection operators ‘*’, and expr is the address of
the variable to be displayed.
‘t’ Type Modifiers
c char u = unsigned, x = hex, o = octal
d double none
f float none
fp far pointer none
i int u = unsigned, x = hex, o = octal
Pacific C Compiler 83
Chapter 6 - Lucifer - A Source Level Debugger
@lx longvar
@c f*cptr
@iu **ihandle
6
After displaying the variable, the current address is advanced by the size of the type displayed, making
it possible to step through arrays by repeatedly pressing return. On-line help for the @ command may
be obtained by entering ?@ at the ‘:’ prompt.
6.3.14 The ^ Command: print a stack trace
The ^ command is used to display a trace of the currently active functions by back-tracking frame pointers
and return addresses up the user program’s stack.
The name, frame pointer, and caller of each currently active function will be displayed.
: ^
BP = FF6E f2() called by “tst.c”, line 24
BP = FF76 f1() called by “tst.c”, line 45
BP = FF82 main() called by start+CC
BP = 0000 start()
:
84
Commands
The stack trace displayed above means that at line 45 in “tst.c”, main() called f1(), which in turn called
f2(). start() is the C runtime startoff module.
6.3.15 The $ Command: reset to initial configuration
The $ command is used to reset Lucifer to its’ initial configuration, ready to execute the user program
from the start. Note: it is not always safe to use this command, especially with programs which use
dynamically allocated memory. If in doubt, exit and re-load Lucifer from DOS.
6.3.16 The . Command: set a breakpoint and go
The . command is used to set a temporary breakpoint and resume execution from the current value of PC
(the program counter). Execution continues until any breakpoint is reached, or the user interrupts with
control-C, then the temporary breakpoint is removed. Note: the temporary breakpoint is removed even
if execution stops at a different breakpoint or is interrupted. If no breakpoint address is specified, the .
command will display a list of active breakpoints.
6.3.17 The ; Command: display from a source line
The ; command is used to display 10 lines of source code from a specified position in a source file. If
the line number is omitted, the last page of source code displayed will be re-displayed. Example:
: ; 4
6
4:
5: main()
6: {
7: scanf(“%d”,&value);
8: result = (value << 1) + 6;
9: printf(“result = %d\\n”,result);
10:}
Pacific C Compiler 85
Chapter 6 - Lucifer - A Source Level Debugger
6
6.3.21 The ! Command: execute a DOS command
The ! command is used to execute an operating system shell command line without exiting from Lucifer.
Any text typed after the ! is passed through to the shell without modification.
6.3.22 Other Commands
In addition to the commands listed above, Lucifer will interpret any valid decimal number typed as a
source line number and attempt to display the C source code for that line.
Pressing return without entering a command will result in re-execution of the previous command if the
previous command was @, d,e, s, t, u. In all cases the command resumes where the previous one left
off. For example, if the previous command was d 2000, pressing return will have the same effect as the
command d 2010.
86
Chapter 7
Pacific C Compiler 88
Chapter 7 - ROM Development with Pacific C
In an embedded system where the code is stored in a ROM (Read Only Memory) DOS is not available,
and the int #21 calls that the DOS library routines would make are not available. There are two
implications of this;
q No file I/O is available, due to lack of an operating system and filesystem;
q A .EXE file will not run, due to the DOS calls it makes
In order to generate programs that will run in a target system where the only resources available are the
bare hardware, the Pacific C ROMDEV system includes an alternate set of library routines and run-time
startup routines that provide a full set of non-I/O routines and a limited set of character I/O routines,
relying only on available hardware. The basic I/O routines like printf()are supported by small
routines that use a serial port or other hardware to put and get characters.
The linker also produces output files in different formats; rather than a .EXE file an embedded program
will usually be presented in its final (executable) form as a HEX or raw binary file. A binary file consists
only of an image of the bytes to be programmed into the EPROM; a HEX file can take a variety of formats,
but contains both the program bytes, plus addressing information. In either case the program is absolute,
i.e. it has been linked for and can run only at a specific physical address, unlike a .EXE program which
has a header containing information on addresses that need fixing-up after loading, enabling it to be
loaded and run at any address.
89
What You Need to Know
The initialisation sequence is a very important piece, or set, of information that you will require. Some
target systems will have a trivial initialization sequence - for example an 8088 with hardwired address
decoders will reset in a state where it can run code immediately. However other systems will require a
precise sequence of operations to be performed, often in a minimum number of bytes or cycles, before
the configuration is set up to access available memory properly. The arcane nature of these initialization
sequences and the requirement that they be executed in a precise manner, often leads to them being
referred to as incantations. Get the spell wrong and your target system will remain an inanimate lump of
plastic and silicon.
Fortunately, if you are using an 80C188EB in the very common configuration of a single block of ROM
enabled by the Upper Chip Select, and a single block of RAM enabled by the Lower Chip Select, Pacific
C provides a canned solution to the initialization problem. By selecting the appropriate options in the
Memory Model and Chip Type dialog box in PPD, a standard initialization routine will be linked in to
your program which will set the chip select registers to the right values. If you are using another setup,
you will need to determine the initialization sequence yourself. Use the 80C188EB code, in the file
pwrupeb.as, as a starting point, and modify it accordingly.
The I/O ports available in your particular target system will vary widely, depending on which chip you
are using and what additional hardware your board has. The 80C188EB has a standard on-board set of
I/O ports, including parallel I/O, serial I/O and timers, but other processors, such as the 8088, have no
on-board I/O and so you will need to know what peripheral chips are used and what I/O ports they
implement.
In addition to knowing what the I/O ports are, and what addresses they are mapped to, you will need to 7
have both knowledge and understanding of how to program the I/O ports to achieve the functions you
want with your embedded system. This kind of information is beyond the scope of this manual and
depends on both experience and close study of manufacturer’s data books, as well as the design of your
system.
Once the program is compiled, you will have to transfer the disk file representing your program into an
EPROM, or download it into an EPROM emulator, or use a remote debugger if you already have this set
up. If you’re lucky, you will have purchased a board that comes supplied with a target ROM implementing
our remote debugger, LUCIFER. In this case you can download directly from PPD. Otherwise you will
have to follow whatever steps are required for your particular setup. This also is beyond the scope of this
manual.
Pacific C Compiler 90
Chapter 7 - ROM Development with Pacific C
#include <80c188eb.h>
/*
* Demo program for the 80C188EB. This program
7 * flashes a LED attached to bit 3 of port 1.
*/
main()
{
int i;
91
First Steps
This particular program is written for an 80C188EB with a LED connected to bit 3 of port 1. It programs
the port pin to be an output, and toggles it repeatedly with a delay. Like all good embedded programs, it
never exits, but sits in an infinite loop. If you are using a JED PC-540 board, there is conveniently a LED
driver connected to that pin, and brought out to the I/O connector. See the JED documentation for more
details.
If you are using different hardware, you will need to modify the program accordingly. The source code
is shown in figure -. This is also in the file LED.C in the LUCIFER directory, within the Pacific C
installation directory.
7.4.1 Entering the Program
To enter this program, change into the LUCIFER directory, and start PPD with the argument LED -
simply type:
PPD LED<Enter>
Unless you have previously created a LED.PRJ file, PPD will start up and load the file LED.C, but will
not load a project file. If you need to change the LED.C file, make the changes now. Then select New
Project from the Make menu. PPD will prompt you for a project file name, with the default being
LED.PRJ. Press <Enter> to accept this default. PPD will now prompt you with a series of dialogs to
allow you to specify necessary information. The first dialog, shown in figure -, allows selection of ROM
code rather than DOS code. Select ROM code with the mouse, or press M and then press Enter or click
the OK button.
7
Pacific C Compiler 92
Chapter 7 - ROM Development with Pacific C
If you are not using an 80C188EB and you need a powerup routine to initialise the processor, see the
discussion below on user-defined powerup sequences. Figure - shows the dialog after selecting 80188
code with the EB powerup. Now press Enter to step to the next dialog.
93
First Steps
Pacific C Compiler 94
Chapter 7 - ROM Development with Pacific C
If you are going to execute the code under Lucifer or another debugger, the memory addresses you set
will be different. In this case you will set both the ROM and RAM addresses to values within the RAM
in your target system that is available for running programs under Lucifer. For this example proram it
should be adequate to set RAM address to 400h (above the interrupt vectors), RAM size to 400h, and
ROM address to 800h (equal to the sum of the RAM address and RAM size). If Lucifer is pre-imple-
mented on your target system, it should have information about what memory is available, or if you have
implemented it yourself you will know what addresses you can use. More information about implement-
ing Lucifer follows later in this chapter.
After completing the entry of the memory addresses, press Enter to proceed to the Optimization dialog.
7.4.5 Selecting Optimizations
When compiling it is possible to select from a set of available optimizations. These are discussed earlier
in this manual, and for ROM code are no different to those used with DOS code. For this demonstration
you may select all or none of the available choices, or any combination of them.
95
First Steps
Now press Escape or click in the menu bar, or click the Done button and you will return to the normal
mode of operation.
7.4.7 Making the Program
Press the F5 key, or select the Make menu then the Make menu entry. PPD will evaluate the dependencies
of the source file list, i.e. it will compare the modification times of the source files with the modification
times of the corresponding object files, and determine if the source files need recompiling. In this instance
there is only one source file, and it has not yet been compiled, so the object file will not exist. If the object
file did exist and was newer, PPD would then check any #include files used by the source file. If any of
these was newer, the source file would be recompiled anyway. Similarly, after checking the source files,
the object files and libraries will be checked against the HEX or binary file, to determine if a re-link is
necessary. Again, in this instance, the fact that no object file exists will guarantee a re-link.
During the compilation and linking phases PPD will display completion bars, as you will have seen
during DOS compilations. At the end of the link phase, a completion message will be presented as
shown in figure -.
.You will notice that there are two CODE areas reported - one is the main body of the program, the other
is the power-on reset vector area at FFFF0. The Utility/Memory usage map menu entry will give a
slightly more comprehensive report of the same information. The addresses of these code areas should
agree with the values you gave in the ROM and RAM addresses dialog.
Pacific C Compiler 96
Chapter 7 - ROM Development with Pacific C
If you have a Lucifer target ROM in your system, you should have connected the serial port on your target
system to either COM1 or COM2 on your PC. You will need to know what baud rate the Lucifer target
is set up to use (some implemenations will auto-detect the baud rate). Select the Run menu, then the
Download LED.HEX menu item. The act of making the program will have enabled this menu selection
You will then be presented with a dialog box asking you to choose a COM port and baud rate. Make the
appropriate selections, the press Enter. The COM port and baud rate will be saved in the project file.
Lucifer will then be invoked, and it will attempt communication with the target system. If your target
system is working, and you have correctly connected the communications cable, and you have got the
baud rate correct, it will announce itself then download the program. Type g then Enter to start it running.
The LED should flash!
97
Debugging with Lucifer
The 80C188EB target program is TARGETEB.C. There is a project file for this, TARGETEB.PRJ, so
you can simply run type ‘PPD TARGETEB’ and it will load the project file - or use the ALT-P command
from within PPD to load a new project. You may need to edit TARGETEB.C to set the baud rate - it
includes a #error directive to force you to edit it, and has comments to indicate what needs changing.
Then make the HEX or binary file, and program it into an EPROM. Plug this into your target board, and
use the same serial connection you used for testing LUCTEST. From within PPD, select the Run/Debug
using... menu item - it’s not important at this stage what symbol file you have. Set the baud rate when
requested to 38400, then you should get the Lucifer sign on and a message “Target identifies as...”. This
means that the Lucifer debugger on your PC is communicating with the target system.
If it doesn’t work, it is likely to be due to incorrect serial connections or programming, incorrect memory
addresses, or EPROM programming errors (including programming the code into the wrong part of the
EPROM).
To run Lucifer from the command line, you can invoke it as
LUC86 -S38400 -PCOM1
Subsititute the appropriate baud rate and com port if required. The defaults for baud rate and com port
are 19200 and COM1. The 188EB target is set up for 38400 baud, which gives faster downloading, but
if you invoke Lucifer without a -S38400, it will not talk to the target board.
Pacific C Compiler 98
Chapter 7 - ROM Development with Pacific C
99
Introduction
Chapter 8
Linker Reference
Manual
8.1 Introduction
Pacific 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 compiled separately and finally
all the object files linked together into a single executable program.
The assembler is described in its own chapter. This chapter describes the theory behind and the usage of
the linker.Note however that in most instances it will not be necessary to use the linker directly, as the
compiler drivers (PPD or command line) will automatically invoke the linker wil all necessary arguments.
Using the linker directly is not simple, and should be attempted only by those with a sound knowledge
of the compiler and linking in general.
If it is absolutely necessary to use the linker directly, the best way to start is to copy the linker arguments
constructed by the compiler driver, and modify them as appropriate. This will ensure that the necessary
startup module and arguments are present.
Note also that the linker supplied with Pacific C is generic to a wide variety of compilers for several
different processors. Not all features described in this chapter are applicatble toall compilers.
101
Operation
or binary file etc.). In the case of the 8086 processor, the link address roughly corresponds to the offset
within a segment, while the load address corresponds to the physical address of a segment. The segment
address is the load address divided by 16.
Other examples of link and load addresses being different are; an initalized data psect that is copied from
ROM to RAM at startup, so that it may be modified at run time; a banked text psect that is mapped from
a physical (== load) address to a virtual (== link) address at run time.
The exact manner in which link and load addresses are used depends very much on the particular compiler
and memory model being used.
8.7 Operation
A command to the linker takes the following form:
HLINK1 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 listed in table 8-1 and discussed in the following paragraphs.
8.7.1 Numbers in linker options
Several linker options require memory addresses or sizes to be specified. The syntax for all these is similar.
By default, the number will be interpreted as a decimal value. To force interpretation as a hex number,
a trailing ‘H’ should be added, e.g. 765FH will be treated as a hex number.
8.7.2 -8
When linking 8086 programs, it is convenient to have addresses in the link map appear as segmented
addresses, e.g. 007F:1234 represents a segment number of 7F and an offset of 1234. 8
8.7.3 -Aclass=low-high,...
Normally psects are linked according to the information given to a -P option (see below) but sometimes
it is desired to have a psect or class linked into more than one non-contiguous address range. This option
allows a number of address ranges to be specified for a class. For example:
-ACODE=1020h-7FFEh,8000h-BFFEh
Option Effect
-8 Use 8086 style segment:offset address form
-Apsect=low-high,... Specify address ranges for a psect
-Cpsect=class Specify a class name for a global psect
-Cbaseaddr Produce binary output file based at baseaddr
-Dsymfile Produce old-style symbol file
-F Produce .OBJ file with only symbol records
-Gspec Specify calculation for segment selectors
-Hsymfile Generate symbol file
-I Ignore undefined symbols
-L Preserve relocation items in .OBJ file
-LM Preserve segment relocation items in .OBJ file
-N Sort symbol table in map file by address order
-Mmapfile Generate a link map in the named file
-Ooutfile Specify name of output file
-Pspec Specify psect addresses and ordering
-Spsect=max Specify maximum address for a psect
-Usymbol Pre-enter symbol in table as undefined
-Vavmap Use file avmap to generate an Avocet format symbol file
-Wwarnlev Set warning level (-10 to 10)
specifies that the class CODE is to be linked into the given address ranges. Note that a contribution to a
psect from one module cannot be split, but the linker will attempt to pack each block from each module
into the address ranges, starting with the first specified.
8.7.4 -Cpsect=class
This option will allow a psect to be associated with a specific class. Normally this is not required on the
command line since classes are specified in object files.
8.7.5 -Dsymfile
Use this option to produce an old-style symbol file. An old-style symbol file is an ASCII file, where each
line has the link address of the the symbol followed by the symbol name.
103
Operation
8.7.6 -F
Normally the linker will produce an object file that contains both program code and data bytes, and symbol
information. Sometimes it is desired to produce a symbol-only object file that can be used again in a
subsequent linker run to supply symbol values. The -F option will suppress data and code bytes from the
output file, leaving only the symbol records.
8.7.7 -Gspec
When linking programs using segmented, or bankswitched psects, there are two ways the linker can assign
segment addresses, or selectors, to each segment. A segment is defined as a contiguous group of psects
where each psect in sequence has both its link and load address concatenated with the previous psect in
the group. The segment address or selector for the segment is the value derived when a segment type
relocation is processed by the linker (see the description of the object code format in appendix ).
By default the segment selector will be generated by dividing the base load address of the segment by
the relocation quantum of the segment, which is based on the RELOC= value given to psects at the
assembler level. This is appropriate for 8086 real mode code, but not for protected mode or some
bankswitched arrangements. In this instance the -G option is used to specify a method for calculating the
segment selector. The argument to -G is a string similar to:
A/10h-4h
where A represents the load address of the segment and represents division. This means “Take the load
address of the psect, divide by 10 hex, then subtract 4". This form can be modified by substituting N for
A, X for / (to represent multiplication), and adding rather than subtracting a constant. The token N is
replaced by the ordinal number of the segment, which is allocated by the linker. For example:
N*8+4
8
means “take the segment number, multiply by 8 then add 4". The result is the segment selector. This
particular example would allocate segment selectors in the sequence 4, 12, 20, ... for the number of
segments defined. This would be appropriate when compiling for 80286 protected mode, where these
selectors would represent LDT entries.
8.7.8 -Hsymfile
This option will instruct the linker to generate a symbol file (in “new” HI-TECH format - see appendix
“File Formats”). The optional argument symfile specifies a file to receive the symbol file. The default file
name is l.sym.
8.7.9 -I
Usually failure to resolve a reference to an undefined symbol is a fatal error. Use of this option will cause
undefined symbols to be treated as warnings instead.
8.7.10 -L
When the linker produces an output file it does not usually preserve any relocation information, since the
file is now absolute. In some circumstances a further “relocation” of the program will be done at load
time, e.g. when runnig a .EXE file under DOS or a .PRG file under TOS. This requires that some
information about what addresses require relocation is preserved in the object (and subsequently the
executable) file. The -L option will generate in the output file one null relocation record for each relocation
record in the input.
8.7.11 -LM
Similar to the above option, this preserves relocation records in the output file, but only segment
relocations. This is used particularly for generating .EXE files to run under DOS.
8.7.12 -Mmapfile
This causes the linker to generate a link map in the named file, or on the standard output if the file name
is omitted. The format of the map file is illustrated by the example in figure 8-1.
The sections in the map file are as follows; first is a copy of the command line used to invoke the linker.
This is followed by the version number of the object code in the first file linked, and the machine type.
Then are listed all object files that were linked, along with their psect information. Libraries are listed,
with each module within the library. The TOTALS section summarizes the psects from the object files.
The SEGMENTS section summarizes major memory groupings. This will typically show RAM and ROM
usage. The segment names are derived from the name of the first psect in the segment.
Lastly (not shown in the example) is a symbol table, where each global symbol is listed with its associated
psect and link address.
8 8.7.13 -N
By default the symbol table in the link map will be sorted by name. This option will cause it to be sorted
numerically, based on the value of the symbol.
8.7.14 -Ooutfile
This option allows specification of an output file name for the linker. The default output file name is
L.OBJ. Use of this option will override the default.
8.7.15 -Pspec
Psects are linked together and assigned addresses based on information in supplied to the linker via -P
options. The argument to the -P option consists basically of comma separated sequences thus:
-Ppsect=lnkaddr/ldaddr,psect=lnkaddr/ldaddr, ...
105
Operation
C:\HT-Z80\LIB\z80-sc.lib
powerup.obj vectors 71 71 1
CLASS DATA
bss 8000 8000 24
There are several variations, but essentially each psect is listed with its desired link and load addresses.
The link and load addresses are either numbers as described above, or the names of other psects or classes,
or special tokens. If a link address is omitted, the psect’s link address will be derived from the top of the
previous psect, e.g.
-Ptext=100h,data,bss
In this example the text psect is linked at 100 hex (its load address defaults to the same). The data psect
will be linked (and loaded) at an address which is 100 hex plus the length of the text psect, rounded up
as necessary if the data psect has a RELOC= value associated with it. Similarly, the bss psect will
concatenate with the data psect.
If the load address is omitted entirely, it defaults to the same as the link address. If the slash (/) character
is supplied, but no address is supplied after it, the load address will concatenate with the previous psect,
e.g.
-Ptext=0,data=0/,bss
will cause both text and data to have a link address of zero, text will have a load address of 0, and data
will have a load address starting after the end of text. The bss psect will concatenate with data for both
link and load addresses.
The load address may be replaced with a dot (.) character. This tells the linker to set the load address of
this psect to the same as its link address. The link or load address may also be the name of another (already
linked) psect. This will explicitly concatenate the current psect with the previously specified psect, e.g.
-Ptext=0,data=8000h/,bss/. -Pnvram=bss,heap
This example shows text at zero, data linked at 8000h but loaded after text, bss is linked and loaded at
8 8000h plus the size of data, and nvram and heap are concatenated with bss. Note here the use of two -P
options. Multiple -P options are processed in order.
If -A options have been used to specify address ranges for a class then this class name may be used in
place of a link or load address, and space will be found in one of the address ranges. For example:
-ACODE=8000h-BFFEh,E000h-FFFEh
-Pdata=C000h/CODE
This will link data at C000h, but find space to load it in the address ranges associated with CODE. If no
sufficiently large space is available, an error will result. Note that in this case the data psect will still be
assembled into one contiguous block, whereas other psects in the class CODE will be distributed into the
address ranges wherever they will fit. This means that if there are two or more psects in class CODE,
they may be intermixed in the address ranges.
107
Invoking the Linker
8.7.16 -Spsect=max
A psect may have a maximum address associated with it. This is normally set in assembler code (with a
SIZE= flag on a psect directive) but may also be set on the command line to the linker with this option.
For example:
-Srbss=80h
8.7.17 -Usymbol
This option will enter the specified symbol into the linker’s symbol table as an undefined symbol. This
is useful for linking entirely from libraries, or for linking a module from a library where the ordering has
been arranged so that by default a later module will be linked.
8.7.18 -Vavmap
To produce an Avocet format symbol file, the linker needs to be given a map file to allow it to map psect
names to Avocet memory identifiers. The avmap file will normally be supplied with the compiler, or
created automatically by the compiler driver as required. For a description of the format of an avmap file,
see appendix “File Formats”.
8.7.19 -Wnum
The -W option can be used to set the warning level, in the range -9 to 9, or the width of the map file, for
values = 10.
8.7.20 -X
Local symbols can be suppressed from a symbol file with this option. Global symbols will always appear
in the symbol file.
8
8.7.21 -Z
Some local symbols are compiler generated and not of interest in debugging. This option will suppress
from the symbol file all local symbols that have the form of a single alphabetic character, followed by a
digit string. The set of letters that can start a trivial symbol is currently “klfLSu”. The -Z option will strip
any local symbols starting with one of these letters, and followed by a digit string.
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. For example a link command file
called X.LNK and containing the following text:
-Z -OX.OBJ -MX.MAP \
-Ptext=0,data=0/,bss,nvram=bss/. \
X.OBJ Y.OBJ Z.OBJ C:\HT-Z80\LIB\Z80-SC.LIB
may be passed to the linker by one of the following:
HLINK @X.LNK
HLINK <X.LNK
109
Chapter 9
9.2 Usage
The librarian is called LIBR and is invoked as follows:
LIBR key file.lib file.obj ...
The key is a single letter which tells the librarian what action to perform using the single library file, and
zero or more object files. The allowable actions are listed in table 9-1.
9.2.1 Creating a library
To create a library, you should use the r command. If the specified library file does not exist, it will be 9
created and the listed object files appended to it. For example:
LIBR r test.lib file1.obj file2.obj file3.obj
will create the library file test.lib (if it does not already exist) and append to it the three object files. The
order of the object modules in the library is the same as the order of the files on the command line.
110
Creating libraries from PPD
112
Appendix A
Error Messages
This appendix lists all possible error messages from the Pacific C
compiler, with an explanation of each one. This information is also available on-line from within PPD.
#define syntax error
A macro definition has a syntax error. This could be due to a macro or formal parameter name that
does not start with a letter or a missing closing parenthesis (‘)’).
#elif may not follow #else
If a #else has been used after #if, you cannot then use a #elif in the same conditional block.
#elif must be in an #if
#elif must be preceded by a matching #if line. If there is an apparently corresponding #if line, check
for things like extra #endif’s, or improperly terminated comments.
#else may not follow #else
There can be only one #else corresponding to each #if.
#else must be in an #if
#else can only be used after a matching #if.
#endif must be in an #if
There must be a matching #if for each #endif. Check for the correct number of #ifs.
#error: *
This is a programmer generated error; there is a directive causing a deliberate error. This is normally
used to check compile time defines etc.
#if ... sizeof() syntax error
The preprocessor found a syntax error in the argument to sizeof, in a #if expression. Probable causes
are mismatched parentheses and similar things.
#if ... sizeof: bug, unknown type code *
The preprocessor has made an internal error in evaluating a sizeof() expression. Check for a
malformed type specifier.
#if ... sizeof: illegal type combination
A
The preprocessor found an illegal type combination in the argument to sizeof() in a #if expression.
Illegal combinations include such things as “short long int”.
#if bug, operand = *
The preprocessor has tried to evaluate an expression with an operator it does not understand. This is
an internal error.
114
-s, too many values, * unused
There were too many values supplied to a -S preprocessor option.
... illegal in non-prototype arg list
The ellipsis symbol may only appear as the last item in a prototyped argument list. It may not appear
on its own, nor may it appear after argument names that do not have types.
: expected
A colon is missing in a case label, or after the keyword “default”. This often occurs when a semicolon
is accidentally typed instead of a colon.
; expected
A semicolon is missing here. The semicolon is used as a terminator in many kinds of statements, e.g.
do .. while, return etc.
= expected
An equal sign was expected here.
] expected
A closing square bracket was expected in an array declaration or an expression using an array index.
a parameter may not be a function
A function parameter may not be a function. It may be a pointer to a function, so perhaps a “*” has
been omitted from the declaration.
absolute expression required
An absolute expression is required in this context.
add_reloc - bad size
This is an internal error that should never happen. The assembler may be corrupted, and should be
re-installed from the original distribution disks.
argument * conflicts with prototype
The argument specified (argument 1 is the left most argument) of this function declaration does not
agree with a previous prototype for this function.
argument list conflicts with prototype
The argument list in a function definition is not the same as a previous prototype for that function.
Check that the number and types of the arguments are all the same.
argument redeclared: *
The specified argument is declared more than once in the same argument list.
arguments redeclared
The arguments of the function have been declared differently in two or more places. A
arithmetic overflow in constant expression
A constant expression has been evaluated by the code generator that has resulted in a value that is too
big for the type of the expression, e.g. trying to store the value 256 in a “char”.
array dimension on * ignored
An array dimension on a function parameter is ignored, because the argument is actually converted
to a pointer when passed. Thus arrays of any size may be passed.
116
bad bconfloat - *
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
bad bit number
A bit number must be an absolute expression in the range 0-7.
bad bitfield type
A bitfield may only have a type of int.
bad character const
This character constant is badly formed.
bad character in extended tekhex line *
This is an internal error in objtohex and should never occur.
bad checksum specification
A checksum list supplied to the linker is syntatically incorrect.
bad combination of flags
The combination of options supplied to objtohex is invalid.
bad complex relocation
The linker has been asked to perform complex relocation that is not syntactically correct. Probably
means a corrupted object file.
bad confloat - *
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
bad conval - *
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
bad dimensions
The code generator has been passed a declaration that results in an array having a zero dimension.
bad element count expr
There is an error in the intermediate code. Try re-installing the compiler from the distribution disks,
as this could be caused by a corrupted file.
bad gn
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
bad high address in -a spec A
The high address given in a -A specification is invalid: it should be a valid number, in decimal, octal
or hexadecimal radix. The radix is specified by a trailing O (for octal) or H for hex. Decimal is default.
bad int. code
The code generator has been passed input that is not syntatically correct.
bad load address in -a spec
The load address given in a -A specification is invalid: it should be a valid number, in decimal, octal
or hexadecimal radix. The radix is specified by a trailing O (for octal) or H for hex. Decimal is default.
118
bad segspec *
The segspec option (-G) to the linker is invalid. The correct form of a segspec option is along the
following lines:
-Gnxc+o
where n stands for the segment number, x is a multiplier symbol, c is a constant (multiplier) and o is a
constant offset. For example the option
-Gnx4+16
would assign segment selectors starting from 16, and incrementing by 4 for each segment, i.e. in the order
16, 20, 24 etc.
bad size in -s option
The size part of a -S option is not a validly formed number. The number must be a decimal, octal or
hex number. A hex number needs a trailing H, and an octal number a trailing O. All others are assumed
to be decimal.
bad size list
The first pass of the compiler has been invoked with a -Z option, specifying sizes of types, that is
badly formed.
bad storage class
The storage class “auto” may only be used inside a function. A function parameter may not have any
storage class specifier other than “register”. If this error is issued by the code generator, it could mean
that the intermediate code file is invalid. This could be caused by running out of disk (or RAMdisk)
space.
bad string * in psect pragma
The code generator has been passed a “pragma psect” directive that has a badly formed string. “Pragma
psect” should be followed by something of the form “oldname=newname”.
bad sx
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
bad u usage
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
bad variable syntax A
There is an error in the intermediate code file. This could be caused by running out of disk (or
RAMdisk) space for temporary files.
bad which * after i
This is an internal compiler error. Contact HI-TECH Software technical support.
binary digit expected
A binary digit was expected. The format for a binary number is
0Bxxx
where xxx is a string of zeroes and ones, e.g.
0B0110
bit field too large * bits)
The maximum number of bits in a bit field is the same as the number of bits in an “int”.
bug: illegal __ macro *
This is an internal error in the preprocessor that should not happen.
can’t allocate space for port variables: *
“Port” variables may only be declared “extern” or have an absolute address associated via the “@
address” construct. They may not be declared in such a way that would require the compiler to allocate
space for them.
can’t be both far and near
It is illegal to qualify a type as both far and near.
can’t be long
Only “int” and “float” can be qualified with “long”. Thus combinations like “long char” are illegal.
can’t be register
Only function parameters or auto (local) variables may be declared “register”.
can’t be short
Only “int” can be modified with short. Thus combinations like “short float” are illegal.
can’t be unsigned
There is no such thing as an unsigned floating point number.
can’t call an interrupt function
A function qualified “interrupt” can’t be called from other functions. It can only be called by a
hardware (or software) interrupt. This is because an interrupt function has special function entry and
exit code that is appropriate only for calling from an interrupt. An “interrupt” function can call other
non-interrupt functions.
can’t create *
The named file could not be created. Check that all directories in the path are present.
can’t create cross reference file *
The cross reference file could not be created. Check that all directories are present. This can also be
caused by the assembler running out of memory.
A can’t create temp file
The compiler was unable to create a temporary file. Check the DOS Environment variable TEMP
(and TMP) and verify it points to a directory that exists, and that there is space available on that drive.
For example, AUTOEXEC.BAT should have something like:
SET TEMP=C:\TEMP
where the directory C:\TEMP exists.
120
can’t create temp file *
The compiler could not create the temporary file named. Check that all the directories in the file path
exist.
can’t create xref file *
An output file for the cross reference could not be created.
can’t enter abs psect
This is an internal assembler error. Contact HI-TECH technical support with full details of the code
that caused this error.
can’t find op
Internal error - Contact HI-TECH.
can’t find space for psect * in segment *
The named psect cannot be placed in the specified segment. This probably means your code has got
too big for the specified ROM space (using -A options).
can’t generate code for this expression
This expression is too difficult for the code generator to handle. Try simplifying the expression, e.g.
using a temporary variable to hold an intermediate result.
can’t have ‘port’ variable: *
The qualifier “port” can be used only with pointers or absolute variables. You cannot define a port
variable as the compiler does not allocate space for port variables. You can declare an external port
variable.
can’t have ‘signed’ and ‘unsigned’ together
The type modifiers signed and unsigned cannot be used together in the same declaration, as they have
opposite meaning.
can’t have an array of bits or a pointer to bit
IT is not legal to have an array of bits, or a pointer to bit.
can’t have array of functions
You can’t have an array of functions. You can however have an array of pointers to functions. The
correct syntax for an array of pointers to functions is “int (* arrayname[])();”. Note that parentheses
are used to associate the star (*) with the array name before the parentheses denoting a function.
can’t initialise auto aggregates
You can’t initialise structures or arrays local to a function unless they are declared “static”.
can’t initialize arg
A function argument can’t have an initialiser. The initialisation of the argument happens when the A
function is called and a value is provided for the argument by the calling function.
can’t mix proto and non-proto args
A function declaration can only have all prototyped arguments (i.e. with types inside the parentheses)
or all K&R style args (i.e. only names inside the parentheses and the argument types in a declaration
list before the start of the function body).
can’t open
A file can’t be opened - check spelling.
can’t open *
The named file could not be opened. Check the spelling and the directory path. This can also be caused
by running out of memory.
can’t open avmap file *
A file required for producing Avocet format symbol files is missing. Try re-installing the compiler.
can’t open checksum file *
The checksum file specified to objtohex could not be opened. Check spelling etc.
can’t open command file *
The command file specified could not be opened for reading. Check spelling!
can’t open include file *
The named include file could not be opened. Check spelling. This can also be caused by running out
of memory, or running out of file handles.
can’t open input file *
The specified input file could not be opened. Check the spelling of the file name.
can’t open output file *
The specified output file could not be created. This could be because a directory in the path name
does not exist.
can’t reopen *
The compiler could not reopen a temporary file it had just created.
can’t seek in *
The linker can’t seek in the specified file. Make sure the output file is a valid filename.
can’t take address of register variable
A variable declared “register” may not have storage allocated for it in memory, and thus it is illegal
to attempt to take the address of it by applying the “&” operator.
can’t take sizeof func
Functions don’t have sizes, so you can’t take use the “sizeof” operator on a function.
can’t take sizeof(bit)
You can’t take sizeof a bit value, since it is smaller than a byte.
can’t take this address
The expression which was the object of the “&” operator is not one that denotes memory storage (“an
lvalue”) and therefore its address can not be defined.
can’t use a string in an #if
A The preprocessor does not allow the use of strings in #if expressions.
cannot get memory
The linker is out of memory! This is unlikely to happen, but removing TSR’s etc is the cure.
cannot open
A file cannot be opened - check spelling.
122
cannot open include file *
The named include file could not be opened for reading by the preprocessor. Check the spelling of
the filename. If it is a standard header file, not in the current directory, then the name should be
enclosed in angle brackets (<>) not quotes.
cast type must be scalar or void
A typecast (an abstract type declarator enclosed in parentheses) must denote a type which is either
scalar (i.e. not an array or a structure) or the type “void”.
char const too long
A character constant enclosed in single quotes may not contain more than one character.
character not valid at this point in format specifier
The printf() style format specifier has an illegal character.
close error (disk space?)
When the compiler closed a temporary file, an error was reported. The most likely cause of this is
that there was insufficient space on disk for the file. Note that temporary files may be created on a
RAM disk, so even if your hard disk has ample space it is still possible to get this error.
common symbol psect conflict: *
A common symbol has been defined to be in more than one psect.
complex relocation not supported for -r or -l options yet
The linker was given a -R or -L option with file that contain complex relocation. This is not yet
supported.
conflicting fnconf records
This is probably caused by multiple run-time startoff module. Check the linker arguments, or “Object
Files...” in HPD.
constant conditional branch
A conditional branch (generated by an “if” statement etc.) always follows the same path. This may
indicate an expression with missing or badly placed parentheses, causing the evaluation to yield a
value different to what you expected, or it may be because you have written something like “while(1)”.
To produce an infinite loop, use “for(;;)”.
constant conditional branch: possible use of = instead of ==
There is an expression inside an if or other conditional construct, where a constant is being assigned
to a variable. This may mean you have inadvertentley used an assignment (=) instead of a compare
(==).
constant expression required A
In this context an expression is required that can be evaluated to a constant at compile time.
constant left operand to ?
The left operand to a conditional operator (?) is constant, thus the result of the tertiary operator ?: will
always be the same.
constant operand to || or &&
One operand to the logical operators || or && is a constant. Check the expression for missing or badly
placed parentheses.
124
dimension required
Only the most significant (i.e. the first) dimension in a multi-dimension array may not be assigned a
value. All succeeding dimensions must be present.
directive not recognized
An assembler directive is unrecognized. Check spelling.
divide by zero in #if, zero result assumed
Inside a #if expression, there is a division by zero which has been treated as yielding zero.
division by zero
A constant expression that was being evaluated involved a division by zero.
double float argument required
The printf format specifier corresponding to this argument is %f or similar, and requires a floating
point expression. Check for missing or extra format specifiers or arguments to printf.
duplicate -m flag
The linker only likes to see one -m flag, unless one of them does not specify a file name. Two map
file names are more than it can handle!
duplicate case label
There are two case labels with the same value in this switch statement.
duplicate label *
The same name is used for a label more than once in this function. Note that the scope of labels is the
entire function, not just the block that encloses a label.
duplicate qualifier
There are two occurences of the same qualifier in this type specification. This can occur either directly
or through the use of a typedef. Remove the redundant qualifier.
duplicate qualifier key *
This qualifier key (given via a -Q option, has been used twice.
duplicate qualifier name *
A duplicate qualifier name has been specified to P1 via a -Q option. This should not occur if the
standard compiler drivers are used.
end of file within macro argument from line *
A macro argument has not been terminated. This probably means the closing parenthesis has been
omitted from a macro invocation. The line number given is the line where the macro argument started.
end of string in format specifier
The format specifier for the printf() style function is malformed. A
entry point multiply defined
There is more than one entry point defined in the object files given the linker.
enum tag or { expected
After the keyword “enum” must come either an identifier that is or will be defined as an enum tag,
or an opening brace.
eof in #asm
An end of file has been encountered inside a #asm block. This probably means the #endasm is missing
or misspelt.
eof in comment
End of file was encountered inside a comment. Check for a missing closing comment flag.
eof inside conditional
END-of-FILE was encountered while scanning for an “endif” to match a previous “if”.
eof inside macro def’n
End-of-file was encountered while processing a macro definition. This means there is a missing
“endm” directive.
eof on string file
P1 has encountered an unexpected end-of-file while re-reading its file used to store constant strings
before sorting and merging. This is most probably due to running out of disk space. Check free disk
space, OR RAM disk size. The RAM disk may be too small, if it is used for temporary files.
error closing output file
The compiler detected an error when closing a file. This most probably means there is insufficient
disk space, but note that the file could be on a RAM disk, so even if you have ample space on your
hard disk, this error can still occur. If this is the case, increase the size of your ram disk or move your
temporary file area onto the hard disk.
error in format string
There is an error in the format string here. The string has been interpreted as a printf() style format
string, and it is not syntactically correct. If not corrected, this will cause unexpected behaviour at run
time.
evaluation period has expired
The evaluation period for this compiler has expired. Contact HI-TECH to purchase a full licence.
expand - bad how
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
expand - bad which
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
expected ‘-’ in -a spec
A There should be a minus sign (-) between the high and low addresses in a -A spec, e.g.
-AROM=1000h-1FFFh
exponent expected
A floating point constant must have at least one digit after the “e” or “E”.
expression error
There is a syntax error in this expression, OR there is an error in the intermediate code file. This could
be caused by running of disk (or RAMdisk) space.
126
expression generates no code
This expression generates no code. Check for things like leaving off the parentheses in a function call.
expression stack overflow at op *
Expressions in #if lines are evaluated using a stack with a size of 128. It is possible for very complex
expressions to overflow this. Simplify the expression.
expression syntax
This expression is badly formed and cannot be parsed by the compiler.
expression too complex
This expression has caused overflow of the compiler’s internal stack and should be re-arranged or
split into two expressions.
external declaration inside function
A function contains an “extern” declaration. This is legal but is invariably A Bad Thing as it restricts
the scope of the function declaration to the function body. This means that if the compiler encounters
another declaration, use or definition of the extern object later in the same file, it will no longer have
the earlier declaration and thus will be unable to check that the declarations are consistent. This can
lead to strange behaviour of your program or signature errors at link time. It will also hide any previous
declarations of the same thing, again subverting the compiler’s type checking. As a general rule,
always declare “extern” variables and functions outside any other functions.
fast interrupt can’t be used in large model
The large model (bank switched) does not support fast interrupts, as the alternate register set is used
for bank switching.
field width not valid at this point
A field width may not appear at this point in a printf() type format specifier.
filename work buffer overflow
A filename constructed while looking for an include file has exceeded the length of an internal buffer.
Since this buffer is 4096 bytes long, this is unlikely to happen.
fixup overflow in expression *
The linker was asked to relocate (fixup) an item that would not fit back into the space after relocation.
For example this will occur if a byte size object is initialized with an address that is bigger than 255.
This error occurred in a complex expression.
fixup overflow referencing *
The linker was asked to relocate (fixup) an item that would not fit back into the space after relocation.
For example this will occur if a byte size object is initialized with an address that is bigger than 255. A
flag * unknown
This option used on a “PSECT” directive is unknown to the assembler.
float param coerced to double
Where a non-prototyped function has a parameter declared as “float”, the compiler convert this into
a “double float”. This is because the default C type conversion conventions provide that when a
floating point number is passed to a non-prototyped function, it will be converted to double. It is
important that the function declaration be consistent with this convention.
128
function or function pointer required
Only a function or function pointer can be the subject of a function call. This error can be produced
when an expression has a syntax error resulting in a variable or expression being followed by an
opening parenthesis (“(”) which denotes a function call.
functions can’t return arrays
A function can return only a scalar (simple) type or a structure. It cannot return an array.
functions can’t return functions
A function cannot return a function. It can return a function pointer. A function returning a pointer to
a function could be declared like this: int (* (name()))(). Note the many parentheses that are necessary
to make the parts of the declaration bind correctly.
functions nested too deep
This error is unlikely to happen with C code, since C cannot have nested functions!
garbage after operands
There is something on this line after the operands other than a comment. This could indicate an operand
error.
garbage on end of line
There were non-blank and non-comment characters after the end of the operands for this instruction.
Note that a comment must be started with a semicolon.
hex digit expected
After “0x” should follow at least one of the hex digits 0-9 and A-F or a-f.
ident records do not match
The object files passed to the linker do not have matching ident records. This means they are for
different processor types.
identifier expected
Inside the braces of an “enum” declaration should be a comma-separated list of identifiers.
identifier redefined: *
This identifier has already been defined. It cannot be defined again.
identifier redefined: * (from line *)
This identifier has been defined twice. The ‘from line ‘ value is the line number of the first declaration.
illegal # command *
The preprocessor has encountered a line starting with #, but which is not followed by a recognized
control keyword. This probably means the keyword has been misspelt. Legal control keywords are:
assert asm define elif else endasm endif error if A
ifdef ifndef include line pragma undef
illegal #if line
There is a syntax error in the expression following #if. Check the expression to ensure it is properly
constructed.
illegal #undef argument
The argument to #undef must be a valid name. It must start with a letter.
130
illegal initialisation
You can’t initialise a “typedef” declaration, because it does not reserve any storage that could be
initialised.
illegal operation on a bit variable
Not all operations on bit variables are supported. This operation is one of those.
illegal operator in #if
A #if expression has an illegal operator. Check for correct syntax.
illegal or too many -p flags
There are too many -p options to the linker. Combine some of them.
illegal record type
There is an error in an object file. This is either an invalid object file, or an internal error in the linker.
Try recreating the object file.
illegal relocation size: *
There is an error in the object code format read by the linker. This either means you are using a linker
that is out of date, or that there is an internale error in the assembler or linker.
illegal relocation type: *
An object file contained a relocation record with an illegal relocation type. This probably means the
file is corrupted or not an object file.
illegal switch *
This command line option was not understood.
illegal type for array dimension
An array dimension must be either an integral type or an enumerated value.
illegal type for index expression
An index expression must be either integral or an enumerated value.
illegal type for switch expression
A “switch” operation must have an expression that is either an integral type or an enumerated value.
illegal use of void expression
A void expression has no value and therefore you can’t use it anywhere an expression with a value
is required, e.g. as an operand to an arithmetic operator.
image too big
The program image being constructed by objtohex is too big for its virtual memory system.
implicit conversion of float to integer
A floating point value has been assigned or otherwise converted to an integral type. This could result A
in truncation of the floating point value. A typecast will make this warning go away.
implicit return at end of non-void function
A function which has been declared to return a value has an execution path that will allow it to reach
the end of the function body, thus returning without a value. Either insert a return statement with a
value, or if the function is not to return a value, declare it “void”.
132
initialisation syntax
The initialisation of this object is syntactically incorrect. Check for the correct placement and number
of braces and commas.
initializer in ‘extern’ declaration
A declaration containing the keyword “extern” has an initialiser. This overrides the “extern” storage
class, since to initialise an object it is necessary to define (i.e. allocate storage for ) it.
insufficient memory for macro def’n
There is not sufficient memory to store a macro definition.
integer constant expected
A colon appearing after a member name in a structure declaration indicates that the member is a
bitfield. An integral constant must appear after the colon to define the number of bits in the bitfield.
integer expression required
In an “enum” declaration, values may be assigned to the members, but the expression must evaluate
to a constant of type “int”.
integral argument required
An integral argument is required for this format specifier. Check the number and order of format
specifiers and corresponding arguments.
integral type required
This operator requires operands that are of integral type only.
invalid disable: *
This is an internal preprocessor error that should not occur.
invalid format specifier or type modifier
The format specifier or modifier in the printf() style string is illegal for this particular format.
invalid number syntax
The syntax of a number is invalid. This can be, e.g. use of 8 or 9 in an octal number, or other malformed
numbers.
jump out of range
A short jump (“JR”) instruction has been given an address that is more than 128 bytes away from the
present location. Use the “JP” opcode instead.
label identifier expected
An identifier denoting a label must appear after “goto”.
lexical error
An unrecognized character or token has been seen in the input. A
library * is badly ordered
This library is badly ordered. IT will still link correctly, but it will link faster if better ordered.
line does not have a newline on the end
The last line in the file is missing the newline (linefeed, hex 0A) from the end. Some editors will
create such files, which can cause problems for include files. The ANSI C standard requires all source
files to consist of complete lines only.
134
mismatched comparision
A comparison is being made between a variable or expression and a constant value which is not in
the range of possible values for that expression, e.g. if you compare an unsigned character to the
constant value 300, the result will always be false (not equal) since an unsigned character can NEVER
equal 300. As an 8 bit value it can represent only 0-255.
misplaced ‘?’ or ‘:’, previous operator is *
A colon operator has been encountered in a #if expression that does not match up with a corresponding
? operator. Check parentheses etc.
misplaced constant in #if
A constant in a #if expression should only occur in syntactically correct places. This error is most
probably caused by omission of an operator.
missing ‘)’
A closing parenthesis was missing from this expression.
missing ‘=’ in class spec
A class spec needs an = sign, e.g.
-Ctext=ROM
missing ‘]’
A closing square bracket was missing from this expression.
missing arg to -a
The -a option requires the name of a qualifier as an argument.
missing arg to -u
The -U (undefine) option needs an argument, e.g.
-U_symbol
missing arg to -w
The -W option (listing width) needs a numeric argument.
missing argument to ‘pragma psect’
The pragma ‘psect’ requires an argument of the form oldname=newname where oldname is an existing
psect name known to the compiler, and newname is the desired new name. Example:
#pragma psect bss=battery
missing basic type: int assumed
This declaration does not include a basic type, so int has been assumed. This declaration is not illegal,
but it is preferable to include a basic type to make it clear what is intended. A
missing key in avmap file
A file required for producing Avocet format symbol files is corrupted. Try re-installing the compiler.
missing memory key in avmap file
A file required for producing Avocet format symbol files is corrupted. Try re-installing the compiler.
missing name after pragma ‘inline’
The ‘inline’ pragma has the syntax:
136
nested comments
This warning is issued when nested comments are found. A nested comment may indicate that a
previous closing comment marker is missing or malformed.
no #asm before #endasm
A #endasm operator has been encountered, but there was no previous matching #asm.
no arg to -o
The assembler requires that an output file name argument be supplied after the “-O” option. No space
should be left between the -O and the filename.
no case labels
There are no case labels in this switch statement.
no end record
This object file has no end record. This probably means it is not an object file.
no end record found
An object file did not contain an end record. This probably means the file is corrupted or not an object
file.
no file arguments
The assembler has been invoked without any file arguments. It cannot assemble anything.
no identifier in declaration
The identifier is missing in this declaration. This error can also occur where the compiler has been
confused by such things as missing closing braces.
no memory for string buffer
P1 was unable to allocate memory for the longest string encountered, as it attempts to sort and merge
strings. Try reducing the number or length of strings in this module.
no psect specified for function variable/argument allocation
This is probably caused by omission of correct run-time startoff module. Check the linker arguments,
or “Object Files...” in HPD.
no space for macro def’n
The assembler has run out of memory.
no start record: entry point defaults to zero
None of the object files passed to the linker contained a start record. The start address of the program
has been set to zero. This may be harmless, but it is recommended that you define a start address in
your startup module by using the “END” directive.
no. of arguments redeclared A
The number of arguments in this function declaration does not agree with a previous declaration of
the same function.
nodecount = *
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
non-constant case label
A case label in this switch statement has a value which is not a constant.
138
operand error
The operand to this opcode is invalid. Check you assembler reference manual for the proper form of
operands for this instruction.
operands of * not same pointer type
The operands of this operator are of different pointer types. This probably means you have used the
wrong pointer, but if the code is actually what you intended, use a typecast to suppress the error
message.
operands of * not same type
The operands of this operator are of different pointer. This probably means you have used the wrong
variable, but if the code is actually what you intended, use a typecast to suppress the error message.
operator * in incorrect context
An operator has been encountered in a #if expression that is incorrectly placed, e.g. two binary
operators are not separated by a value.
out of far memory
The compiler has run out of far memory. Try removing TSR’s etc. If your system supports EMS
memory, the compiler will be able to use up to 64K of this, so if it is not enable, try enabling EMS.
out of far memory (wanted * bytes)
The code generator could not allocate any more far memory. Try reducing the memory used by TSR’s
etc.
out of memory
The compiler has run out of memory. If you have unnecessary TSRs loaded, remove them. If you are
running the compiler from inside another program, try running it directly from the command prompt.
Similarly, if you are using HPD, try using the command line compiler driver instead.
out of memory for assembler lines
The optimizer has run out of memory to store assembler lines, e.g. #asm lines from the C source, or
C source comment lines. Reduce the size of the function.
out of near memory
The compiler has run out of near memory. This is probably due to too many symbol names. Try
splitting the program up, or reducing the number of unused symbols in header files etc.
out of space in macro * arg expansion
A macro argument has exceeded the length of an internal buffer. This buffer is normally 4096 bytes
long.
output file cannot be also an input file A
The linker has detected an attempt to write its output file over one of its input files. This cannot be
done, because it needs to simultaneously read and write input and output files.
page width must be >= 41
The listing page widthe must be at least 41 characters. Any less will not allow a properly formatted
listing to be produced.
phase error
The assembler has calculated a different value for a symbol on two different passes. This is probably
due to bizarre use of macros or conditional assembly.
phase error in macro args
The assembler has detected a difference in the definition of a symbol on the first and a subsequent
pass.
phase error on temporary label
The assembler has detected a difference in the definition of a symbol on the first and a subsequent
pass.
pointer required
A pointer is required here. This often means you have used “->” with a structure rather than a structure
pointer.
pointer to * argument required
A pointer argument is required for this format specifier. Check the number and order of format
specifiers and corresponding arguments.
pointer to non-static object returned
This function returns a pointer to a non-static (e.g. automatic) variable. This is likely to be an error,
since the storage associated with automatic variables becomes invalid when the function returns.
portion of expression has no effect
Part of this expression has no side effects, and no effect on the value of the expression.
possible pointer truncation
A pointer qualifed “far” has been assigned to a default pointer or a pointer qualified “near”, or a default
pointer has been assigned to a pointer qualified “near”. This may result in truncation of the pointer
and loss of information, depending on the memory model in use.
preprocessor assertion failure
The argument to a preprocessor #assert directive has evaluated to zero. This is a programmer induced
error.
probable missing ‘}’ in previous block
The compiler has encountered what looks like a function or other declaration, but the preceding
function has not been ended with a closing brace. This probably means that a closing brace has been
omitted from somewhere in the previous function, although it may well not be the last one.
psect ‘*’ re-orged
A This psect has its address multiply defined. Check the linker options.
psect * cannot be in classes *
A psect cannot be in more than one class. This is either due to assembler modules with conflicting
class= options, or use of the -C option to the linker.
psect * cannot be in classes * and *
This psect has been declared as being in two different classes, which is not allowed.
psect * in more than one group
This psect has been defined to be in more than one group.
140
psect * not loaded on * boundary
This psect has a relocatability requirement that is not met by the load address given in a -P option.
For example if a psect must be on a 4K byte boundary, you could not start it at 100H.
psect * not relocated on * boundary
This psect is not relocated on the required boundary. Check the relocatability of the psect and correct
the -p option. if necessary.
psect * not specified in -p option
This psect was not specified in a “-P” option to the linker. It has been linked at the end of the program,
which is probably not where you wanted it.
psect * not specified in -p option (first appears in *
This psect is missing from any -p or -A option. It will be linked at a default address, which is almost
certainly not what you want.
psect * re-orged
This psect has had its start address specified more than once.
psect * selector value redefined
The selector value for this psect has been defined more than once.
psect * type redefined: *
This psect has had its type defined differently by different modules. This probably means you are
trying to link imcompatible object modules, e.g. linking 386 flat model code with 8086 real mode
code.
psect exceeds max size: *
The psect has more bytes in it than the maximum allowed.
psect is absolute: *
This psect is absolute and should not have an address specified in a -P option.
psect may not be local and global
A psect may not be declared to be local if it has already been declared to be (default) global.
psect origin multiply defined: *
The origin of this psect is defined more than once.
psect property redefined
A property of a psect has been defined in more than place to be different.
psect reloc redefined
The relocatability of this psect has been defined differently in two or more places.
psect selector redefined A
The selector associated with this psect has been defined differently in two or more places.
psect size redefined
The maximum size of this psect has been defined differently in two or more places.
qualifiers redeclared
This function has different qualifiers in different declarations.
read error on *
The linker encountered an error trying to read this file.
142
signatures do not match: *
The specified function has different signatures in different modules. This means it has been declared
differently, e.g. it may have been prototyped in one module and not another. Check what declarations
for the function are visible in the two modules specified and make sure they are compatible.
signed bitfields not supported
Only unsigned bitfields are supported. If a bitfield is declared to be type “int”, the compiler still treats
it as unsigned.
simple integer expression required
A simple integral expression is required after the operator “@”, used to associate an absolute address
with a variable.
simple type required for *
A simple type (i.e. not an array or structure)is required as an operand to this operator.
sizeof external array * is zero
The sizeof an external array evaluates to zero. This is probably due to the array not having an explicit
dimension in the extern declaration.
sizeof yields 0
The code generator has taken the size of an object and found it to be zero. This almost certainly
indicates an error in your declaration of a pointer, e.g. you may have declared a pointer to a zero length
array. In general, pointers to arrays are of little use. If you require a pointer to an array of objects of
unknown length, you only need a pointer to a single object that can then be indexed or incremented.
storage class illegal
A structure or union member may not be given a storage class. Its storage class is determined by the
storage class of the structure.
storage class redeclared
A variable or function has been re-declared with a different storage class. This can occur where there
are two conflicting declarations, or where an implicit declaration is followed by an actual declaration.
strange character * after ##
A character has been seen after the token catenation operator ## that is neither a letter nor a digit.
Since the result of this operator must be a legal token, the operands must be tokens containing only
letters and digits.
strange character after # *
There is an unexpected character after #.
string expected A
The operand to an “asm” statement must be a string enclosed in parentheses.
string too long
This string is too long. Shorten it.
struct/union member expected
A structure or union member name must follow a dot (“.”) or arrow (“->”).
struct/union redefined: *
A structure or union has been defined more than once.
struct/union required
A structure or union identifier is required before a dot (“.”).
struct/union tag or ‘{‘ expected
An identifier denoting a structure or union or an opening brace must follow a “struct” or “union”
keyword.
symbol * cannot be global
There is an error in an object file, where a local symbol has been declared global. This is either an
invalid object file, or an internal error in the linker. Try recreating the object file.
symbol * has erroneous psect: *
There is an error in an object file, where a symbol has an invalid psect. This is either an invalid object
file, or an internal error in the linker. Try recreating the object file.
symbol * not defined in #undef
The symbol supplied as argument to #undef was not already defined. This is a warning only, but could
be avoided by including the #undef in a #ifdef ... #endif block.
syntax error
A syntax error has been detexted. This could be caused a number of things.
syntax error in -a spec
The -A spec is invalid. A valid -A spec should be something like:
-AROM=1000h-1FFFh
syntax error in checksum list
There is a syntax error in a checksum list read by the linker. The checksum list is read from standard
input by the linker, in response to an option. Re-read the manual on checksum listt.
syntax error in local argument
There is a syntax error in a local argument.
text does not start at 0
Code in some things must start at zero. Here it doesn’t.
text offset too low
You aren’t likely to see this error. Rhubarb!
text record has bad length: *
There is an error in an object file. This is either an invalid object file, or an internal error in the linker.
Try recreating the object file.
text record has length too small: *
A This indicates that the object file is not a valid HI-TECH object file.
this function too large - try reducing level of optimization
A large function has been encountered when using a -Og (global optimization) switch. Try re-com-
piling without the global optimization, or reduce the size of the function.
this is a struct
This identifier following a “union” or “enum” keyword is already the tag for a structure, and thus
should only follow the keyword “struct”.
144
this is a union
This identifier following a “struct” or “enum” keyword is already the tag for a union, and thus should
only follow the keyword “union”.
this is an enum
This identifier following a “struct” or “union” keyword is already the tag for an enumerated type, and
thus should only follow the keyword “enum”.
too few arguments
This function requires more arguments than are provided in this call.
too few arguments for format string
There are too few arguments for this format string. This would result in a garbage value being printed
or converted at run time.
too many (*) enumeration constants
There are too many enumeration constants in an enumerated type. The maximum number of
enumerated constants allowed in an enumerated type is 512.
too many (*) structure members
There are too many members in a structure or union. The maximum number of members allowed in
one structure or union is 512.
too many arguments
This function does not accept as many arguments as there are here.
too many arguments for format string
There are too many arguments for this format string. This is harmless, but may represent an incorrect
format string.
too many arguments for macro
A macro may only have up to 31 parameters, as per the C Standard.
too many arguments in macro expansion
There were too many arguments supplied in a macro invocation. The maximum number allowed is
31.
too many cases in switch
There are too many case labels in this switch statement. The maximum allowable number of case
labels in any one switch statement is 511.
too many comment lines - discarding
The compiler is generating assembler code with embedded comments, but this function is so large
that an excessive number of source line comments are being generated. This has been suppressed so A
that the optimizer will not run out of memory loading comment lines.
too many errors
There were so many errors that the compiler has given up. Correct the first few errors and many of
the later ones will probably go away.
too many file arguments. usage: cpp [input [output]]
CPP should be invoked with at most two file arguments.
146
type modifier already specified
This type modifier has already be specified in this type.
type modifiers not valid with this format
Type modifiers may not be used with this format.
type redeclared
The type of this function or object has been redeclared. This can occur because of two incompatible
declarations, or because an implicit declaration is followed by an incompatible declaration.
type specifier reqd. for proto arg
A type specifier is required for a prototyped argument. It is not acceptable to just have an identifier.
unbalanced paren’s, op is *
The evaluation fo a #if expression found mismatched parentheses. Check the expression for correct
parenthesisation.
undefined enum tag: *
This enum tag has not been defined.
undefined identifier: *
This symbol has been used in the program, but has not been defined or declared. Check for spelling
errors.
undefined shift * bits)
An attempt has been made to shift a value by a number of bits equal to or greater than the number of
bits in the data type, e.g. shifting a long by 32 bits. This will produce an undefined result on many
processors. This is non-portable code and is flagged as having undefined results by the C Standard.
undefined struct/union
This structure or union tag is undefined. Check spelling etc.
undefined struct/union: *
The specified structure or union tag is undefined. Check spelling etc.
undefined symbol *
The named symbol is not defined, and has not been specified “GLOBAL”.
undefined symbol * in #if, 0 used
A symbol on a #if expression was not a defined preprocessor macro. For the purposes of this
expression, its value has been taken as zero.
undefined symbol:
The symbol following is undefined at link time. This could be due to spelling error, or failure to link
an appropriate module. A
undefined symbols:
A list of symbols follows that were undefined at link time.
undefined temporary label
A temporary label has been referenced that is not defined. Note that a temporary label must have a
number >= 0.
undefined variable: *
This variable has been used but not defined at this point
unexpected \ in #if
The backslash is incorrect in the #if statement.
unexpected end of file
This probably means an object file has been truncated because of a lack of disk (or RAMdisk) space.
unexpected eof
An end-of-file was encountered unexpectedly. Check syntax.
unexpected text in #control line ignored
This warning occurs when extra characters appear on the end of a control line, e.g.
#endif something
The “something” will be ignored, but a warning is issued. It is preferable (and in accordance with Standard
C) to enclose the “something” as a comment, e.g.
#endif /* something */
unknown complex operator *
There is an error in an object file. This is either an invalid object file, or an internal error in the linker.
Try recreating the object file.
unknown fnrec type *
This indicates that the object file is not a valid HI-TECH object file.
unknown option *
This option to the preprocessor is not recognized.
unknown pragma *
An unknow pragma directive was encountered.
unknown predicate *
Internal error - Contact HI-TECH.
unknown psect
The assembler file read by the optimizer has an unknown psect.
unknown psect: *
This psect has been listed in a -P option, but is not defined in any module within the program.
unknown qualifier * given to -a
The -a option to P1 should have as its argument a defined qualifier name,
unknown record type: *
An invalid object module has been read by the linker. It is either corrupted or not an object file.
A unknown symbol type *
The symbol type encountered is unknown to this linker. Check that the correct linker is being used.
unreachable code
This section of code will never be executed, because there is no execution path by which it could be
reached. Look for missing “break” statements inside a control structure like “while” or “for”.
148
unreasonable matching depth
This is an internal code generator error. Contact HI-TECH technical support with full details of the
code that caused this error.
unrecognized option to -z: *
The code generator has been passed a -Z option it does not understand. This should not happen if it
is invoked with the standard driver.
unrecognized qualifer name after ‘strings’
The pragma ‘strings’ requires a list of valid qualifer names. For example
#pragma strings const code
would add const and code to the current string qualifiers. If no qualifiers are specified, all qualification
will be removed from subsequent strings. The qualifer names must be recognized by the compiler.
unterminated #if[n][def] block from line *
A #if or similar block was not terminated with a matching #endif. The line number is the line on which
the #if block began.
unterminated macro arg
An argument to a macro is not terminated. Note that angle brackets (“<>”) are used to quote macro
arguments.
unterminated string
A string constant appears not to have a closing quote missing.
unterminated string in macro body
A macro definition contains a string that lacks a closing quote.
unused constant: *
This enumerated constant is never used. Maybe it isn’t needed at all.
unused enum: *
This enumerated type is never used. Maybe it isn’t needed at all.
unused label: *
This label is never used. Maybe it isn’t needed at all.
unused member: *
This structure member is never used. Maybe it isn’t needed at all.
unused structure: *
This structure tag is never used. Maybe it isn’t needed at all.
unused typedef: * A
This typedef is never used. Maybe it isn’t needed at all.
unused union: *
This union type is never used. Maybe it isn’t needed at all.
unused variable declaration: *
This variable is never used. Maybe it isn’t needed at all.
unused variable definition: *
This variable is never used. Maybe it isn’t needed at all.
150
Appendix B
Library Functions
The functions within the Pacific C library are listed in this appendix. Each entry begins with the name of
the function, followed by information under the following headings:
SYNOPSIS
Under this heading is given the C definition of the function, and the header file in which it is declared.
DESCRIPTION
This is a narrative description of the function and its purpose.
EXAMPLE
An example is given here of the use of the function. This usually consists of a complete small program
that illutstrates the function.
DATA TYPES
If any special data types (structures etc.) are defined for use with the function, they are listed here with
their C definition. These data types will be defined in the header file given under SYNOPSIS.
RETURN VALUE
B
The type and nature of the return value of the function (if any) is given. Information on error returns is
also included.
SEE ALSO
Where there are related functions that may be of interest in connection with the current function, they are
listed here.
NOTE
Sometimes special information will be provided under this heading.
153
ACOS
ACOS
SYNOPSIS
#include <math.h>
double acos(double f)
DESCRIPTION
Acos() implements the converse of cos(), i.e. it is passed a value in the range -1 to +1, and returns an
angle in radians whose cosine is equal to that value.
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
float i, a;
RETURN VALUE
An angle in radians, in the range 0 to 2π. Where the argument value is outside the domain -1 to 1, the
return value will be zero.
SEE ALSO
sin, cos, tan, acos, atan, atan2
ASCTIME
SYNOPSIS
#include <time.h>
char * asctime(struct tm * 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. The example gets
the current time, converts it to a struct tm pointer with localtime, then converts this to ASCII and prints
it.
EXAMPLE
#include <stdio.h>
#include <time.h>
main()
{
time_t clock;
struct tm * tp;
time(&clock);
tp = localtime(&clock);
printf(“%s”, asctime(tp));
}
DATA TYPES
struct tm { int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
B int tm_wday;
int tm_yday;
155
ASCTIME
int tm_isdst;
};
SEE ALSO
ctime, time, gmtime, localtime, time
ASIN
SYNOPSIS
#include <math.h>
double asin(double f)
DESCRIPTION
Asin() implements the converse of sin(), i.e. it is passed a value in the range -1 to +1, and returns an angle
in radians whose sine is equal to that value.
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
float i, a;
RETURN VALUE
An angle in radians, in the range -π/2 to +π/2. Where the argument value is outside the domain -1 to 1,
the return value will be zero.
SEE ALSO
sin, cos, tan
157
ASSERT
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
following 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
discussion of the uses of assert is impossible in limited space, but it is closely linked to methods of proving
program correctness.
EXAMPLE
ptrfunc(struct xyz * tp)
{
assert(tp != 0);
}
ATAN
SYNOPSIS
#include <math.h>
double atan(double x);
DESCRIPTION
This function returns the arc tangent of its argument, i.e. it returns an angle ein the range π⁄2 to −pi⁄2 such
that sin(e)≡x.
SEE ALSO
tan, asin, acos, atan2
159
ATEXIT
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
program termination. On program termination, all functions registered by atexit() are called, in the
reverse order of their registration.
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
char * fname;
FILE * fp;
void
rmfile(void)
{
if(fp)
fclose(fp);
if(fname)
remove(fname);
}
main()
{ /* create a file; on exit, close and remove it */
RETURN VALUE
Atexit() returns zero if the registration succeeds, nonzero if it fails.
SEE ALSO B
exit
ATOF
SYNOPSIS
#include <stdlib.h>
double atof(char * s)
DESCRIPTION
Atof scans the character string passed to it, skipping leading blanks, and converts an ASCII representation
of a number to a double. The number may be in decimal, normal floating point or scientific notation.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
main()
{
char buf[80];
double i;
gets(buf);
i = atof(buf);
printf(“Read %s: converted to %f\n”, buf, i);
}
RETURN VALUE
A double precision floating point number. If no number is found in the string, 0.0 will be returned.
SEE ALSO
atoi, atol
161
ATOI
ATOI
SYNOPSIS
#include <math.h>
double atoi(char * s)
DESCRIPTION
Atoi scans the character string passed to it, skipping leading blanks, and converts an ASCII representation
of a decimal number to an integer.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
main()
{
char buf[80];
int i;
gets(buf);
i = atoi(buf);
printf(“Read %s: converted to %d\n”, buf, i);
}
RETURN VALUE
A signed integer. If no number is found in the string, 0 will be returned.
SEE ALSO
atof, atol
ATOL
SYNOPSIS
#include <math.h>
double atol(char * s)
DESCRIPTION
Atoi scans the character string passed to it, skipping leading blanks, and converts an ASCII representation
of a decimal number to a long integer.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
main()
{
char buf[80];
long i;
gets(buf);
i = atol(buf);
printf(“Read %s: converted to %ld\n”, buf, i);
}
RETURN VALUE
A long integer. If no number is found in the string, 0 will be returned.
SEE ALSO
atoi, atof
163
BSEARCH
BSEARCH
SYNOPSIS
#include <stdlib.h>
void * bsearch(const void * key, const void * base, size_t n_memb,
size_t size, int (*compar)(const void *, const void
*));
DESCRIPTION
The bsearch() function searches a sorted array for an element matching a particular key. It uses a binary
search algorithm, calling the function pointed to by compar to compare elements in the array.
EXAMPLE
/* sample bsearch program */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct value {
char name[40];
int value;
} values[100];
int
val_cmp(const void * p1, const void * p2)
{
return strcmp(((const struct value *)p1)-name,
((const struct value *)p2)-name);
}
main()
{
char inbuf[80];
int i;
struct value * vp;
i = 0;
while(gets(inbuf)) {
sscanf(inbuf,"%s %d", values[i].name, &values[i].value); B
i++;
}
qsort(values, i, sizeof values[0], val_cmp);
RETURN VALUE
A pointer to the matched array element (if there is more than one matching element, any of these may be
returned). If no match is found, a null pointer is returned.
NOTE
The comparison function must have the correct prototype.
SEE ALSO
qsort
165
CALLOC
CALLOC
SYNOPSIS
#include <stdlib.h>
void * 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 zeros.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
struct test {
int a[20];
} * ptr;
main()
{ /* allocate space for 20 structs */
RETURN VALUE
A pointer to the block is returned, or 0 if the memory could not be allocated.
SEE ALSO
brk, sbrk, malloc, free
CEIL
SYNOPSIS
#include <math.h>
double ceil(double f)
DESCRIPTION
This routine returns the smallest whole number not less than f.
167
CGETS
CGETS
SYNOPSIS
#include <conio.h>
char * cgets(char * s)
DESCRIPTION
Cgets() will read one line of input from the console into the buffer passed as an argument. It does so by
repeated calls to getche(). As characters are read, they are buffered, with BACKSPACE deleting the
previously typed character, and ctrl-U deleting the entire line typed so far. Other characters are placed in
the buffer, with a carriage return or line feed (newline) terminating the function. The collected string is
null terminated.
EXAMPLE
#include <conio.h>
#include <string.h>
char buffer[80];
main()
{
for(;;) {
cgets(buffer);
if(strcmp(buffer, “exit”) == 0)
break;
cputs(“Type ‘exit’ to finish\n”);
}
}
RETURN VALUE
The return value is the character pointer passed as the sole argument.
SEE ALSO
getch, getche, putch, cputs
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 C:\FRED, or relative, as in ..\SOURCES.
EXAMPLE
#include <sys.h>
main()
{
chdir(“C:\\”);
}
RETURN VALUE
A return value of -1 indicates that the requested change could not be performed. This usually indicates
the directory or some component of the path name does not exist. On success the return value will be
zero.
NOTE
Under MS-DOS, there is a “current directory” for each drive. If there is a drive specification in the path,
this function will change the current directory for that drive, but will NOT change the current drive.
SEE ALSO
mkdir, rmdir, getcwd
169
CHDRV
CHDRV
SYNOPSIS
#include <sys.h>
int chdrv(char * drvname);
DESCRIPTION
To set the current DOS drive, invoke this function with its argument pointing to a string where the first
character is a drive letter.
EXAMPLE
#include <sys.h>
main()
{
chdrv(“C:”);
}
RETURN VALUE
If the selected drive is invalid, a value of -1 is returned.
SEE ALSO
chmod
CHMOD
SYNOPSIS
#include <stat.h> #include <unixio.h>
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.
EXAMPLE
#include <stat.h>
#include <stdio.h>
#include <unixio.h>
main(argc, argv)
char ** argv;
{
if(argc > 1)
if(chmod(argv[1], S_IREAD) < 0)
perror(argv[1]);
}
RETURN VALUE
Zero is returned on success, -1 on failure.
NOTE
Not all bits may be changed under all operating systems, e.g. neither 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
B stat, creat
171
CLOSE
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() or creat().
EXAMPLE
#include <unixio.h>
#include <stdio.h>
main(argc, argv)
char ** argv;
{
int fd;
if(argc > 1) {
if((fd = creat(argv[1], 0600)) < 0)
perror(argv[1]);
else
close(fd);
}
}
RETURN VALUE
Close() returns 0 for a successful 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
specified 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. If a clreof() is not done, then repeated reads will continue to return EOF.
EXAMPLE
#include <stdio.h>
#include <string.h>
main()
{
char buf[80];
for(;;) {
if(!gets(buf)) {
printf(“EOF seen\n”);
clreof(stdin);
} else if(strcmp(buf, “quit”) == 0)
break;
}
}
SEE ALSO
fopen, fclose
173
COS
COS
SYNOPSIS
#include <math.h>
double cos(double f)
DESCRIPTION
This function yields the cosine of its argument. The cosine is calculated by expansion of a polynomial
series approximation.
EXAMPLE
#include <math.h>
#include <stdio.h>
#define C 3.141592/180.0
main()
{
double i;
RETURN VALUE
A double in the range -1 to +1.
SEE ALSO
sin, tan, asin, acos, atan
DESCRIPTION
These functions implement the hyperbolic trig functions.
175
CPUTS
CPUTS
SYNOPSIS
#include <conio.h>
void cputs(const char * s)
DESCRIPTION
Cputs() writes its argument string to the console, outputting carriage returns before each newline in the
string. It calls putch() repeatedly.On a hosted system cputs() differs from puts() in that it reads the console
directly, rather than using file I/O. In an embedded system cputs and puts are equivalent.
EXAMPLE
#include <conio.h>
#include <string.h>
char buffer[80];
main()
{
for(;;) {
cgets(buffer);
if(strcmp(buffer, “exit”) == 0)
break;
cputs(“Type ‘exit’ to finish\n”);
}
}
SEE ALSO
cputs, puts, putch
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 file’s attributes is via the chmod() function.
EXAMPLE
#include <unixio.h>
#include <stdio.h>
main(argc, argv)
char ** argv;
{
int fd;
if(argc > 1) {
if((fd = creat(argv[1], 0600)) < 0)
perror(argv[1]);
else
close(fd);
}
}
SEE ALSO
open, close, read, write, seek, stat, chmod
177
CTIME
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 example program prints the current time and date:
EXAMPLE
#include <stdio.h>
#include <time.h>
main()
{
time_t clock;
time(&clock);
printf(“%s”, ctime(&clock));
}
DATA TYPES
typedef long time_t;
SEE ALSO
gmtime, localtime, asctime, time
DI, EI
SYNOPSIS
#include <intrpt.h>
void ei(void);
void di(void);
DESCRIPTION
Ei() and di() enable and disable interrupts respectively. These are implemented as macros defined in
intrpt.h. On most processors they will expand to an in-line assembler instruction that sets or clears the
interrupt enable or mask bit. The example shows the use of ei() and di around access to a long variable
that is modified during an interrupt. If this was not done, it would be possible to return an incorrect value,
if the interrupt occurred between accesses to successive words of the count value.
EXAMPLE
#include <intrpt.h>
long count;
void interrupt
tick(void)
{
count++;
}
long
getticks(void)
{
long val;
di();
val = count;
ei();
return val;
}
B
179
DIV
DIV
SYNOPSIS
#include <stdlib.h>
div_t div(int numer, int demon);
DESCRIPTION
The div() function computes the quotient and remainder of the numerator divided by the denominator.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
main()
{
div_t x;
x = div(12345, 66);
printf(“quotient = %d, remainder = %d\n”, x.quot, x.rem);
}
DATA TYPES
typedef struct {
int quot;
int rem;
} div_t;
DRIVER
SYNOPSIS
#include <dos.h>
int driverx(far void * entry, union REGS * regs, struct SREGS
sregs);
int driver(far void * entry, union REGS * regs);
DESCRIPTION
These routines allow entry points into external code to be called, with registers set up to specific values.
They are used for accessing DOS features where a far call, rather than an interrupt, is used, for example
the XMS routines.
DATA TYPES
struct WORDREGS { unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
unsigned int si;
unsigned int di;
unsigned int cflag;
unsigned int psw;
};
struct BYTEREGS {
unsigned char al, ah;
unsigned char bl, bh;
unsigned char cl, ch;
unsigned char dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
B struct SREGS {
unsigned int es;
unsigned int cs;
unsigned int ss;
181
DRIVER
SEE ALSO
int86, int86x, intdos, intdosx
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.
EXAMPLE
#include <stdio.h>
#include <unixio.h>
#include <stdlib.h>
#include <sys.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
if(argc < 3) {
fprintf(stderr, “Usage: fd2 stderr_file command ...\n”);
exit(1);
}
if(!(fp = fopen(argv[1], “w”))) {
perror(argv[1]);
exit(1);
}
close(2);
dup(fileno(fp)); /* make stderr reference file */
fclose(fp);
spawnvp(argv[2], argv+2);
close(2);
}
RETURN VALUE
B -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
183
DUP2
DUP2
SYNOPSIS
#include <unixio.h>
int dup2(int original, int new)
DESCRIPTION
Dup2() duplicates a file handle, so that the open file may be referred to by the new handle as well as the
old handle. Unlike dup() this function allows the new file handle to be specified, rather than the next free
handle being allocated. If the new handle new is already in use before the dup2() call, it will be closed
first.
EXAMPLE
#include <stdio.h>
#include <unixio.h>
#include <stdlib.h>
#include <sys.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
if(argc < 3) {
fprintf(stderr, “Usage: fd2 stderr_file command ...\n”);
exit(1);
}
if(!(fp = fopen(argv[1], “w”))) {
perror(argv[1]);
exit(1);
}
dup2(fileno(fp), 2); /* make stderr reference file */
fclose(fp);
spawnvp(argv[2], argv+2);
close(2);
}
RETURN VALUE
If either handle is invalid, or the original handle does not refer to an open file, -1 will be returned. B
SEE ALSO
dup
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,
under MS-DOS a return to the DOS prompt or the program which spawned the current program. Status
is a value that is used as the exit value of the program. This is recovered under DOS with the wait for
status DOS call. The status value will be stored on CP/M at 80H. In an embedded system exit() normally
restarts the program as though a hardware reset had occured. This call will never return.
EXAMPLE
#include <stdlib.h>
main()
{
exit(0);
}
RETURN VALUE
Never returns.
SEE ALSO
atexit
185
EXP
EXP
SYNOPSIS
#include <math.h>
double exp(double f)
DESCRIPTION
Exp() returns the exponential function of its argument, i.e. e sup f .
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
double f;
SEE ALSO
log, log10, pow
FABS
SYNOPSIS
#include <math.h>
double fabs(double f)
DESCRIPTION
This routine returns the absolute value of its double argument.
SEE ALSO
abs
187
FARMALLOC, FARFREE, FARREALLOC
for(i = 0 ; i != 10 ; i++) {
if(!(x = farmalloc(32768)))
break;
i++;
}
printf(“allocated %ld Kbytes in 32K blocks\n”, i*32768L);
}
NOTE
B
In large and compact models farmalloc and farfree are the same functions as malloc and free. Freed
memory is not returned to DOS until the program exits, but will be reallocated by farmalloc.
SEE ALSO
farstrcpy, farmemcpy, malloc, free, realloc
189
FARMEMCPY, FARMEMSET
FARMEMCPY, FARMEMSET
SYNOPSIS
#include <stdlib.h>
far void * farmemcpy(far void * to, far void * from, size_t
count);
far void * farmemset(far void * buf, int val, size_t count);
DESCRIPTION
Farmemcpy() will copy count bytes from one far memory address to another. IT is used in small and
compact models for copying between memory blocks where either the source or destination block is not
in the default data segment.
Similarly farmemset() will set a far block of memory to a specified value.
EXAMPLE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
RETURN VALUE
The destination buffer pointer is returned.
SEE ALSO
farmalloc, memcpy, memset B
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().
EXAMPLE
#include <stdio.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
if(argc > 1) {
if(!(fp = fopen(argv[1], “r”)))
perror(argv[1]);
else {
fprintf(stderr, “Opened %s\n”, argv[1]);
fclose(fp);
}
}
}
RETURN VALUE
Zero is returned on a successful close, EOF otherwise.
SEE ALSO
fopen, fread, fwrite
191
FDOPEN
FDOPEN
SYNOPSIS
#include <stdio.h>
FILE * fdopen(int fd, char * mode);
DESCRIPTION
Where it is desired to associate a STDIO stream with a low-level file descriptor that already refers to an
open file this function may be used. It will return a pointer to a FILE structure which references the
specified low-level file descriptor, as though the function fopen() had been called. The mode argument
is the same as for fopen().
EXAMPLE
#include <stdio.h>
main()
{
FILE * fp;
fp = fdopen(3, “w”);
fprintf(fp, “AUX test line\n”);
}
RETURN VALUE
NULL if a FILE structure could not be allocated
SEE ALSO
fopen, freopen, close
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.
EXAMPLE
#include <stdio.h>
main()
{
while(!feof(stdin))
getchar();
}
SEE ALSO
fopen, fclose
193
FFIRST, FNEXT
FFIRST, FNEXT
SYNOPSIS
#include <stat.h>
struct dirbuf * ffirst(char *);
struct dirbuf * fnext(void);
DESCRIPTION
These two functions provide a means of finding DOS files that match a particular filename pattern. Ffirst()
is called first, and is passed a filename that may include the special pattern matching characters ? and *.
DATA TYPES
struct stat {
unsigned long st_ino;
unsigned short st_dev;
unsigned short st_mode; /* flags */
long st_atime; /* access time */
long st_mtime; /* modification time */
long st_size; /* file size in bytes */
};
struct dirbuf
{
struct stat di_stat; /* info on the file */
char di_name[MAXNAMLEN+1]; /* the file name */
};
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
applications. Normally stdout is opened in line buffered mode, and is flushed before any input is done
on a stdio stream, but if input is to be done via console I/O routines, it may be necessary to call fflush()
first.
EXAMPLE
#include <stdio.h>
#include <conio.h>
main()
{
printf(“press a key: ”);
fflush(stdout);
getch();
}
SEE ALSO
fopen, fclose
195
FGETC
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 function 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().
RETURN VALUE
A character from the input stream, or EOF on end of file.
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 terminated in any case.
EXAMPLE
#include <stdio.h>
main()
{
char buffer[128];
RETURN VALUE
A successful fgets() will return its first argument; NULL is returned on end-of-file or error.
197
FILENO
FILENO
SYNOPSIS
#include <stdio.h>
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.
EXAMPLE
#include <stdio.h>
#include <unixio.h>
#include <stdlib.h>
#include <sys.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
if(argc < 3) {
fprintf(stderr, “Usage: fd2 stderr_file command ...\n”);
exit(1);
}
if(!(fp = fopen(argv[1], “w”))) {
perror(argv[1]);
exit(1);
}
close(2);
dup(fileno(fp)); /* make stderr reference file */
fclose(fp);
spawnvp(argv[2], argv+2);
close(2);
}
SEE ALSO
fopen, fclose, open, close, dup
B
FLOOR
SYNOPSIS
#include <math.h>
double floor(double f)
DESCRIPTION
This routine returns the largest whole number not greater than f.
199
FOPEN
FOPEN
SYNOPSIS
#include <stdio.h>
FILE * fopen(char * name, char * mode);
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:
rThe file is opened 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 writing. If the file does not already exist the call fails.
wThe 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 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 treatment 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.
B
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 arbitrarily 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 reading a binary stream, 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.
EXAMPLE
#include <stdio.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
if(argc > 1) {
if(!(fp = fopen(argv[1], “r”)))
perror(argv[1]);
else {
fprintf(stderr, “Opened %s\n”, argv[1]);
fclose(fp);
}
}
}
SEE ALSO
fclose, fgetc, fputc, freopen, fread, fflush, fwrite, fseek
201
FPRINTF
FPRINTF
SYNOPSIS
#include <stdio.h>
int fprintf(FILE * stream, char * fmt, ...);
DESCRIPTION
Fprintf() performs formatted printing on the specified stream. Refer to printf() for the details of the
available formats.
EXAMPLE
#include <stdio.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
if(argc > 1) {
if(!(fp = fopen(argv[1], “r”)))
perror(argv[1]);
else {
fprintf(stderr, “Opened %s\n”, argv[1]);
fclose(fp);
}
}
}
RETURN VALUE
The number of characters written.
SEE ALSO
printf, fscanf, sscanf, sprintf, vfprintf
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
available 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, sprintf
203
FPUTC
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().
RETURN VALUE
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 associated with the stream.
SEE ALSO
putc, fgetc, fopen, fflush
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()).
EXAMPLE
#include <stdio.h>
main()
{
fputs(“this is a line\n”, stdout);
}
RETURN VALUE
The return value is 0 for success, EOF for error.
SEE ALSO
puts, fgets, fopen, fclose
205
FREAD
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. No word alignment
in the stream is assumed or necessary. The read is done via successive getc()‘s.
EXAMPLE
#include <stdio.h>
main()
{
char buf[80];
int i;
RETURN VALUE
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()).
SEE ALSO
fwrite, fopen, fclose, getc
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
calloc().
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
struct test {
int a[20];
} * ptr;
main()
{ /* allocate space for 20 structs */
SEE ALSO
malloc, calloc
207
FREOPEN
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. This function is commonly used to attach stdin or stdout
to a file, as in the example.
EXAMPLE
#include <stdio.h>
main()
{
char buf[80];
RETURN VALUE
It either returns the stream argument, if successful, or NULL if not. See fopen() for more information.
SEE ALSO
fopen, fclose
FREXP
SYNOPSIS
#include <math.h>
double frexp(double f, int * p)
DESCRIPTION
Frexp() breaks a floating point number into a normalized 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.
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
double f;
int i;
f = frexp(23456.34, &i);
printf(“23456.34 = %f * 2^%d\n”, f, i);
}
SEE ALSO
ldexp
209
FSCANF
FSCANF
SYNOPSIS
#include <stdio.h>
int fscanf(FILE * stream, char * fmt, ...)
DESCRIPTION
This routine performs formatted input from the specified stream. See scanf() for a full description of the
behaviour of the routine.
EXAMPLE
#include <stdio.h>
main()
{
int i;
RETURN VALUE
The number of values assigned, or EOF if an error occurred and no items were converted.
SEE ALSO
scanf, sscanf, fopen, fclose
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 specified
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. Note however 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. The current file position can be determined with the function ftell().
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE * fp;
211
FSEEK
SEE ALSO
lseek, fopen, fclose, ftell
FTELL
SYNOPSIS
#include <stdio.h>
long ftell(FILE * stream)
DESCRIPTION
This function returns the current position of the conceptual 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.
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE * fp;
fp = fopen(“test.fil”, “r”);
if(!fp)
exit(1);
fseek(fp, 0L, 2); /* seek to end */
printf(“size = %ld\n”, ftell(fp));
}
SEE ALSO
fseek
213
FWRITE
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.
EXAMPLE
#include <stdio.h>
main()
{
if(fwrite(“a test string\n”, 1, 14, stdout) != 14)
fprintf(stderr, “Fwrite failed\n”);
}
RETURN VALUE
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
GETC
SYNOPSIS
#include <stdio.h>
int getc(FILE * stream)
FILE * stream;
DESCRIPTION
One character is read from the specified stream and returned. This is the macro version of fgetc(), and is
defined in stdio.h.
EXAMPLE
#include <stdio.h>
main()
{
int i;
RETURN VALUE
EOF will be returned on end-of-file or error.
215
GETCH, GETCHE, UNGETCH
DESCRIPTION
Getch() reads a single character from the console keyboard 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. to the console screen, prepending a carriage return if the
character is a newline. In an embedded system, the source of characters is defined by the particular
routines supplied. By default, the library contains a version of getch() that will interface to the Lucifer
debugger. The user should supply an appropriate routine if another source is desired, e.g. a serial port.
The module getch.c in the SOURCES directory contains model versions of all the console I/O routines.
Other modules may also be supplied, e.g. ser180.c has routines for the serial port in a Z180.
EXAMPLE
#include <conio.h>
main()
{
char c;
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 circumstances
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
217
GETCWD
GETCWD
SYNOPSIS
#include <sys.h>
char * getcwd(char * drive)
DESCRIPTION
Getcwd() returns the path name of the current working directory on the specified drive, where drive is
a string, the first character of which is taken as a drive letter. If the string is null (“”) then the current drive
working directory will be returned.
EXAMPLE
#include <sys.h>
#include <stdio.h>
main()
{
char * cp;
cp = getcwd(“C”);
printf(“cwd = %s\n”, cp);
}
RETURN VALUE
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, getdrv
GETDRV
SYNOPSIS
#include <sys.h>
char * getdrv(void)
DESCRIPTION
Calling this function will return a pointer to a static buffer containing a string of the form “X:”, where X
is the letter representing the current drive, e.g. “C:”.
EXAMPLE
#include <sys.h>
#include <stdio.h>
main()
{
char * cp;
cp = getdrv();
printf(“Current drive is %s\n”, cp);
}
SEE ALSO
getcwd, setdrv
219
GETENV
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=C:\COMMAND.COM
then getenv(“COMSPEC”) will return C:\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 environment 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 contain 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 an equal sign (‘=’) then the value to be
assigned to that variable.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
main()
{
printf(“comspec = %s\n”, getenv(“COMSPEC”));
}
RETURN VALUE
NULL if the specified variable could not be found.
GETFREEMEM
SYNOPSIS
#include <sys.h>
void getfreemem(struct freemem *);
DESCRIPTION
To find the free DOS memory, both conventional and extended, use this function. It fills in a buffer whose
address is passed with the free memory in bytes.
EXAMPLE
#include <sys.h>
#include <stdio.h>
main()
{
struct freemem fm;
getfreemem(&fm);
printf(“conventional memory: %lu bytes, extended memory: %lu bytes\n”,
fm.fr_dosmem, fm.fr_extmem);
}
DATA TYPES
struct freemem { unsigned long fr_dosmem;
unsigned long fr_extmem;
};
NOTE
The “extended” memory value is the amount of extended memory available via the BIOS. For XMS
memory, see the _xms routines.
221
GETIVA
GETIVA
SYNOPSIS
#include <intrpt.h>
extern isr getiva(int intnum);
DESCRIPTION
Getiva() returns a pointer to a far function that is currently pointed to by the nominated interrupt vector.
It uses the DOS int 21h/35h call.
EXAMPLE
#include <intrpt.h>
#include <stdio.h>
main()
{
isr fp;
fp = getiva(0x23);
printf(“int 23h points to address %4.4X:%4.4X\n”,
(unsigned)((unsigned long)fp > 16), (unsigned short)fp);
}
DATA TYPES
typedef far interrupt void (*isr)(void);
SEE ALSO
setiva
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. In an embedded system, gets is equivalent to cgets(), and results in getche() being
called repeatedly to getch characters. Editing (with backspace) is available.
EXAMPLE
#include <stdio.h>
main()
{
char buf[80];
RETURN VALUE
It returns its argument, or NULL on end-of-file.
SEE ALSO
fgets, freopen, puts
223
GETW
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 consecutive getc()‘s. The byte ordering is however undefined. The word read should in general have
been written by putw(). Do not rely on this function to read binary data written by another program.
SEE ALSO
putw, getc, fopen, fclose
GMTIME
SYNOPSIS
#include <time.h>
struct tm * gmtime(time_t * t)
DESCRIPTION
This function converts 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. The structure is as follows:
struct tm { int tm_sec;
int tm_min;
int tm_hour;
int tm_mday; /* day of month */
int tm_mon; /* month; 0-11
int tm_year; /* year -1900 */
int tm_wday; /* weekday - sunday = 0 */
int tm_yday; /* day of year - 0-365 */
int tm_isdst;
};
EXAMPLE
#include <stdio.h>
#include <time.h>
main()
{
time_t clock;
struct tm * tp;
time(&clock);
tp = gmtime(&clock);
printf(“It’s %d in London\n”,
tp-tm_year+1900);
}
B DATA TYPES
typedef long time_t; struct tm {
int tm_sec;
int tm_min;
225
GMTIME
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
SEE ALSO
ctime, asctime, time, localtime
INT86, INT86X
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)
DESCRIPTION
These functions allow calling of software interrupts from C programs. Int86() and int86x() execute the
software interrupt specified by intno. 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.
EXAMPLE
#include <stdio.h>
#include <dos.h>
main()
{
union REGS rbuf;
rbuf.x.ax = 0x8800;
int86(0x15, &rbuf, &rbuf);
printf(“Free extended memory = %uK\n”,
rbuf.x.ax);
}
RETURN VALUE
The return value is of no significance. Test the appropriate register values.
DATA TYPES
B
struct WORDREGS { unsigned int ax;
unsigned int bx;
unsigned int cx;
227
INT86, INT86X
struct BYTEREGS {
unsigned char al, ah;
unsigned char bl, bh;
unsigned char cl, ch;
unsigned char dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
struct SREGS {
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
SEE ALSO
segread, intdos, intdosx
INTDOS, INTDOSX
SYNOPSIS
#include <dos.h>
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 DOS 0x21 interrupts from C programs. 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
version of the call also takes 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.
EXAMPLE
#include <stdio.h>
#include <dos.h>
main()
{
/* determine DOS free memory */
union REGS rbuf;
rbuf.x.ax = 0x4800;
rbuf.x.bx = 0xFFFF;
intdos(&rbuf, &rbuf);
printf(“DOS has %lu bytes free\n”, rbuf.x.bx*16l);
}
DATA TYPES
struct WORDREGS { unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
unsigned int si;
B unsigned int di;
unsigned int cflag;
unsigned int psw;
};
229
INTDOS, INTDOSX
struct BYTEREGS {
unsigned char al, ah;
unsigned char bl, bh;
unsigned char cl, ch;
unsigned char dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
struct SREGS {
unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
SEE ALSO
segread
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 if isascii(c) is true or if c = EOF.
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
isalnum(c) c is in 0-9 or a-z or A-Z
EXAMPLE
B #include <ctype.h>
#include <stdio.h>
main()
231
ISALNUM, ISALPHA, ISDIGIT, ISLOWER et. al.
{
char buf[80];
int i;
gets(buf);
i = 0;
while(isalnum(buf[i]))
i++;
buf[i] = 0;
printf(“’%s’ is the word\n”, buf);
}
SEE ALSO
toupper, tolower, toascii
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 device.
This would normally be used for testing if standard input is coming from a file or the console. For testing
STDIO streams, use isatty(fileno(stream)).
EXAMPLE
#include <unixio.h>
#include <stdio.h>
main()
{
if(isatty(fileno(stdin)))
printf(“input not redirected\n”);
else
printf(“Input is redirected\n”);
}
RETURN VALUE
Zero if the stream is associated with a file; 1 if it is associated with the console or other keyboard type
device.
233
ISNEC98
ISNEC98
SYNOPSIS
#include <dos.h>
int isnec98(void);
DESCRIPTION
This function returns TRUE if executed on a NEC 98xx series computer, false otherwise. If you don’t
know what a NEC 98 series machine is, you don’t need this function. If you’re curious, it is a Japanese
PC that runs MS-DOS but is NOT and IBM compatible.
EXAMPLE
#include <dos.h>
#include <stdio.h>
main()
{
printf(“This is%s a NEC 98xx machine\n”,
isnec98() ? “” : “ not”);
}
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().
EXAMPLE
#include <conio.h>
main()
{
int i;
while(!kbhit()) {
cputs(“I’m waiting..”);
for(i = 0 ; i != 1000 ; i++)
continue;
}
}
SEE ALSO
getch, getche
235
LDEXP
LDEXP
SYNOPSIS
#include <math.h>
double ldexp(double f, int i)
DESCRIPTION
Ldexp() performs the inverse of frexp(). operation; the integer i is added to the exponent of the floating
point f and the resultant value returned.
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
double f;
f = ldexp(1.0, 10);
printf(“1.0 * 2^10 = %f\n”, f);
}
SEE ALSO
frexp
LDIV
SYNOPSIS
#include <stdlib.h>
ldiv_t ldiv(long number, long denom);
DESCRIPTION
The ldiv() routine divides the numerator by the denominator, computing the quotient and the remainder.
The sign of the quotient is the same as that of the mathematical quotient. Its absolute value is the largest
integer which is less than the absolute value of the mathematical quotient.
The ldiv() function is similar to the div() function, the difference being that the arguments and the
members of the returned structure are all of type long int.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
main()
{
ldiv_t lt;
lt = ldiv(1234567, 12345);
printf(“Quotient = %ld, remainder = %ld\n”,
lt.quot, lt.rem);
}
RETURN VALUE
A structure of type ldiv_t
DATA TYPES
typedef struct { long quot; /* quotient */
long rem; /* remainder */
} ldiv_t;
SEE ALSO
B
div
237
LOCALTIME
LOCALTIME
SYNOPSIS
#include <time.h>
struct tm * localtime(time_t * t)
DESCRIPTION
Localtime converts 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. Localtime() takes into account the contents
of the global 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 actually pre-determining this
value, by default localtime() will return the same result as gmtime().
EXAMPLE
#include <stdio.h>
#include <time.h>
char * wday[] = {
“Sunday”, “Monday”, “Tuesday”, “Wednesday”,
“Thursday”, “Friday”, “Saturday”
};
main()
{
time_t clock;
struct tm * tp;
time(&clock);
tp = localtime(&clock);
printf(“Today is %s\n”, wday[tp-tm_wday]);
}
DATA TYPES
typedef long time_t; struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday; B
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
SEE ALSO
ctime, asctime, time
239
LOG, LOG10
LOG, LOG10
SYNOPSIS
#include <math.h>
double log(double f)
double log10(double f)
DESCRIPTION
Log() returns the natural logarithm of f, i.e. the number x such that e e sup x = f . Log10() returns the
logarithm to base 10 of f, i.e the number x such that e 10 sup x = f .
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
double f;
RETURN VALUE
Zero if the argument is negative.
SEE ALSO
exp, pow
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.
EXAMPLE
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
jmp_buf jb;
inner(void)
{
longjmp(jb, 5);
}
main()
{
int i;
if(i = setjmp(jb)) {
printf(“setjmp returned %d\n”, i);
exit(0);
}
printf(“setjmp returned 0 - good\n”);
printf(“calling inner...\n”);
B inner();
printf(“inner returned - bad!\n”);
}
241
LONGJMP
RETURN VALUE
Longjmp never returns.
SEE ALSO
setjmp
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.
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
#include <unixio.h>
main()
{
int fd;
RETURN VALUE
-1 is returned on error, the resulting location otherwise.
SEE ALSO
open, close, read, write
243
MALLOC
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 successful, 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, unlike calloc()..
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
main()
{
char * cp;
cp = malloc(80);
if(!cp)
printf(“Malloc failed\n”);
else {
strcpy(cp, “a string”);
printf(“block = ‘%s’\n”, cp);
free(cp);
}
}
RETURN VALUE
A pointer to the memory if it succeeded; NULL otherwise.
SEE ALSO
calloc, free, realloc
B
MEMCHR
SYNOPSIS
#include <string.h>
void * memchr(const void * block, int val, size_t length);
DESCRIPTION
Memchr() is similar to strchr() except that instead of searching null-terminated strings, it searches a block
of memory specified by length for a particular byte. Its arguments are a pointer to the memory to be
searched, the value of the byte to be searched for, and the length of the block. A pointer to the first
occurrence of that byte in the block is returned.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char * cp;
RETURN VALUE
A pointer to the first byte matching the argument if one exists; NULL otherwise.
SEE ALSO
strchr
B
245
MEMCMP
MEMCMP
SYNOPSIS
#include <string.h>
int memcmp(void * s1, void * s2, size_t n)
DESCRIPTION
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 character. 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. Testing for equality is always reliable.
EXAMPLE
#include <stdio.h>
#include <string.h>
main()
{
int buf[10], cow[10], i;
buf[0] = 1;
buf[2] = 4;
cow[0] = 1;
cow[2] = 5;
buf[1] = 3;
cow[1] = 3;
i = memcmp(buf, cow, 3*sizeof(int));
if(i < 0)
printf(“less than\n”);
else if(i > 0)
printf(“Greater than\n”);
else
printf(“Equal\n”);
}
RETURN VALUE
Memcmp() returns -1, 0 or 1, depending on whether s1 points to string which is less than, equal to or
greater than the string pointed to by s2 in the collating sequence. B
SEE ALSO
strncpy, strncmp, strchr, memset, memchr
MEMCPY
SYNOPSIS
#include <string.h>
void * memcpy(void * d, void * s, size_t n)
DESCRIPTION
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. Memcpy() differs from strcpy()
in that it copies a specified number of bytes, rather than all bytes up to a null terminator.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char buf[80];
RETURN VALUE
Memcpy() returns its first argument.
SEE ALSO
strncpy, strncmp, strchr, memset
247
MEMMOVE
MEMMOVE
SYNOPSIS
#include <string.h>
void * memmove(void * s1, void * s2, size_t n)
DESCRIPTION
Memmove() is similar to memcpy() except copying of overlapping blocks is handled correctly. That is, it
will copy forwards or backwards as appropriate to correctly copy one block to another that overlaps it.
RETURN VALUE
Memmove() returns its first argument.
SEE ALSO
strncpy, strncmp, strchr
MEMSET
SYNOPSIS
#include <string.h>
void memset(void * s, char c, size_t n)
DESCRIPTION
Memset() fills n bytes of memory starting at the location pointed to by s with the character c.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char abuf[20];
SEE ALSO
strncpy, strncmp, strchr, memcpy, memchr
249
MKDIR
MKDIR
SYNOPSIS
#include <sys.h>
int mkdir(char * s)
DESCRIPTION
This function creates a directory under MS-DOS. The argument is a path name, and if successful the
directory specified by the path name will be created. All interemediate directories in the path name must
already exist.
EXAMPLE
#include <sys.h>
#include <stdio.h>
main()
{
if(mkdir(“test.dir”) < 0)
perror(“test.dir”);
else
printf(“Succeeded\n”);
}
RETURN VALUE
Success returns 0, failure -1.
SEE ALSO
chdir, rmdir
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.Under MS-DOS the syntax of filenames are standard
MS-DOS. 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
B getuid(). If drive: is omitted, the file will be sought on the currently selected drive. The following special
file names are recognized:
lst: Accesses the list device - write only
251
OPEN
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.
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
#include <unixio.h>
main()
{
int fd;
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 argument s, followed by a descriptive message detailing
the last error returned from a DOS system call. The error number is retrieved from the global variable
errno. Perror() is of limited usefulness under CP/M as it does not give as much error information as
MS-DOS.
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
main(argc, argv)
char ** argv;
{
if(argc < 2)
exit(0);
if(!freopen(argv[1], “r”, stdin))
perror(argv[1]);
}
SEE ALSO
strerror
253
POW
POW
SYNOPSIS
#include <math.h>
double pow(double f, double p)
DESCRIPTION
Pow() raises its first argument, f, to the power p.
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
double f;
SEE ALSO
log, log10, exp
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, followed by
a list of zero or more arguments. In the format 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
performed 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 performed with zeroes rather than blanks. For integer
formats, the precision indicates a minimum number of digits to be output, with leading zeros inserted to
make up this number if required.
A hash character (#) preceding the width indicates that an alternate format is to be used. The nature of
the alternate format is discussed below. Not all formats have alternates. In those cases, the presence of
the hash character has no effect.
The floating point formats require that the appropriate floating point library is linked. From within HPD
this can be forced by selecting the “Float formats in printf” selection in the options menu. From the
command line driver, use the option -LF.
If the character * is used in place of a decimal constant, e.g. in the format %*d, then one integer argument
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. If the precision is zero, the decimal point will be omitted unless the alternate format
is specified.
e Print the corresponding argument in scientific notation. Otherwise similar to f.
B g Use e or f format, whichever gives maximum precision in minimum width. Any trailing zeros after the
decimal point will be removed, and if no digits remain after the decimal point, it will also be
removed.
255
PRINTF, VPRINTF
o x X u d Integer conversion - in radices 8, 16, 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. When the alternate format is specified, a leading zero will
be supplied for the octal format, and al leading 0x or 0X for the hex format.
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.
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 variable argument lists. An example of using
vprintf is given below.
EXAMPLE
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’
/* vprintf example */
#include <stdio.h>
int
error(char * s, ...)
{
va_list ap;
va_start(ap, s);
printf(“Error: ”);
B
vprintf(s, ap);
putchar(‘\n’);
va_end(ap);
main()
{
int i;
i = 3;
error(“testing 1 2 %d”, i);
}
RETURN VALUE
Printf() returns the number of characters written to stdout.
SEE ALSO
fprintf, sprintf
257
PUTC
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. It places the supplied character onto the
specified I/O stream.
EXAMPLE
#include <stdio.h>
main()
{
char * cp;
cp = x;
while(*x)
putc(*x++, stdout);
putc(‘\n’, stdout);
}
RETURN VALUE
EOF on error, the character passed as argument otherwise.
SEE ALSO
fputc, getc, fopen, fclose, putch
PUTCH
SYNOPSIS
#include <conio.h>
void putch(int c)
DESCRIPTION
Putch() outputs the character c to the console screen, prepending a carriage return if the character is a
newline. In a CP/M or MS-DOS system this will ue one of the system I/O calls. In an embedded system
this routine, and associated others, will be defined in a hardware dependent way. The standard putch()
routines in the embedded library interface either to a serial port or to the Lucifer debugger.
EXAMPLE
#include <conio.h>
main()
{
char * cp;
cp = x;
while(*x)
putch(*x++);
putch(‘\n’);
}
SEE ALSO
cgets, cputs, getch, getche
259
PUTCHAR
PUTCHAR
SYNOPSIS
#include <stdio.h>
int putchar(int c)
DESCRIPTION
Putchar() is a putc() operation on stdout, defined in stdio.h.
EXAMPLE
#include <stdio.h>
main()
{
char * cp;
cp = x;
while(*x)
putchar(*x++);
putchar(‘\n’);
}
RETURN VALUE
The character, or EOF if an error occurred.
SEE ALSO
putc, getc, freopen, fclose
PUTS
SYNOPSIS
#include <stdio.h>
int puts(char * s)
DESCRIPTION
Puts() writes the string s to the stdout stream, appending a newline. Thenull terminating the string is not
copied.
EXAMPLE
#include <stdio.h>
main()
{
puts(“Hello, world!”);
}
RETURN VALUE
EOF is returned on error; zero otherwise.
SEE ALSO
fputs, gets, freopen, fclose
261
PUTW
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. The routine getw() may be used
to read in integer written by putw().
SEE ALSO
getw, fopen, fclose
QSORT
SYNOPSIS
#include <stdlib.h>
void qsort(void * base, size_t nel,
size_t width, int (*func)(void *, void *))
DESCRIPTION
Qsort() is an implementation of the quicksort algorithm. 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
compare 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.
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
int aray[] = {
567, 23, 456, 1024, 17, 567, 66
};
int
sortem(const void * p1, const void * p2)
{
return *(int *)p1 - *(int *)p2;
}
main()
{
register int i;
263
QSORT
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. The algorithm will produce a deterministic sequence if started
from the same point. The starting point is set using the srand() call. The example shows use of the time()
function to generate a different starting point for the sequence each time.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
main()
{
time_t toc;
int i;
time(&toc);
srand((int)toc);
for(i = 0 ; i != 10 ; i++)
printf(“%d\t”, rand());
putchar(‘\n’);
}
SEE ALSO
srand
265
READ
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.
EXAMPLE
#include <stdio.h>
#include <unixio.h>
main()
{
char buf[80];
int i;
RETURN VALUE
The number of bytes read; zero on EOF, -1 on error. Be careful not to misinterpret a read of > 32767 as
a negative return value.
SEE ALSO
open, close, write
REALLOC
SYNOPSIS
#include <stdlib.h>
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
malloc(), 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.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
main()
{
char * cp;
cp = malloc(255);
if(gets(cp))
cp = realloc(cp, strlen(cp)+1);
printf(“buffer now %d bytes long\n”,
strlen(cp)+1);
}
RETURN VALUE
A pointer to the new (or resized) block. NULL if the block could not be expanded. A request to shrink a
block will never fail.
SEE ALSO
malloc, calloc, realloc
267
REMOVE
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.
EXAMPLE
#include <stdio.h>
main()
{
if(remove(“test.fil”) < 0)
perror(“test.fil”);
}
RETURN VALUE
Zero on success, -1 on error.
SEE ALSO
unlink
RENAME
SYNOPSIS
#include <stdio.h>
int rename(char * name1, char * name2)
DESCRIPTION
The file named by name1 will be renamed to name2.
EXAMPLE
#include <stdio.h>
main()
{
if(rename(“test.fil”, “test1.fil”))
perror(“Rename”);
}
RETURN VALUE
-1 will be returned if the rename was not successful, zero if the rename was performed.
NOTE
Rename is not permitted across drives or directories.
SEE ALSO
open, close, unlink
269
REWIND
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. This call is equivalent to fseek(stream, 0L, 0).
EXAMPLE
#include <stdio.h>
#include <stdlib.h>
main()
{
char buf[80];
RETURN VALUE
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
RMDIR
SYNOPSIS
#include <sys.h>
int rmdir(char *)
DESCRIPTION
Rmdir() will remove the directory specified by the path name. The directory cannot be removed unless
it is empty.
EXAMPLE
#include <sys.h>
#include <stdio.h>
main()
{
if(rmdir(“test.dir”) < 0)
perror(“test.dir”);
else
printf(“Succeeded\n”);
}
RETURN VALUE
Zero on success, -1 on failure
271
SBRK
SBRK
SYNOPSIS
#include <stdlib.h>
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. This is a low-level routine not intended to be called by user code. Use malloc()
instead.
RETURN VALUE
If there is insufficient memory to satisfy the request, (char *)-1 is returned.
SEE ALSO
brk, malloc, calloc, realloc, free
SCANF, VSCANF
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 followed 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 variable 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
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 preceded by an l to indicate that the corresponding
B 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.
273
SCANF, VSCANF
EXAMPLE
scanf(“%d %s”, &a, &s)
with input “ 12s”
will assign 12 to a, and “s” to s.
RETURN VALUE
Scanf() returns the number of successful conversions; EOF is returned if end-of-file was seen before any
conversions were performed.
SEE ALSO
fscanf, sscanf, printf, va_arg
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. This usually
used to initialize a struct SREGS before calling int86x() or intdosx(). See these functions for more
information.
DATA TYPES
struct SREGS { unsigned int es;
unsigned int cs;
unsigned int ss;
unsigned int ds;
};
SEE ALSO
int86, int86x, intdos, intdosx
275
SETJMP
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.
EXAMPLE
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
jmp_buf jb;
inner(void)
{
longjmp(jb, 5);
}
main()
{
int i;
if(i = setjmp(jb)) {
printf(“setjmp returned %d\n”, i);
exit(0);
}
printf(“setjmp returned 0 - good\n”);
printf(“calling inner...\n”);
inner();
printf(“inner returned - bad!\n”);
}
RETURN VALUE
Setjmp() returns 0 after the real call, and non-zero if it apparently returns after a call to longjmp().
SEE ALSO
longjmp
B
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 compatibility. 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 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. By default, stdout and stdin are line buffered when associated with a terminal-like device, and
full buffered when associated with a file.
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.
EXAMPLE
#include <stdio.h>
char buffer[8192];
main()
{
int i, j;
277
SETVBUF, SETBUF
continue;
}
NOTE
If the buf argument is null, then the size is ignored.
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 initialized. 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.
Not all compilers support this routine; the macros ROM_VECTOR, RAM_VECTOR and
CHANGE_VECTOR are used with some processors, and are to be preferred even where set_vector is
supported. See
h or the processor specific manual section to determine what is supported for a particular compiler.
The example shown sets up a vector for the DOS ctrl-BREAK interrupt.
EXAMPLE
#include <signal.h>
#include <stdlib.h>
#include <intrpt.h>
void
set_trap(void)
{
set_vector(BRKINTV, brkintr);
}
B
RETURN VALUE
The return value of set_vector() is the previous contents of the vector, if set_vector() is implemented as
a function. If it is implemented as a macro, it has no return value.
279
SET_VECTOR
SEE ALSO
di(), ei(), ROM_VECTOR, RAM_VECTOR, CHANGE_VECTOR
SIGNAL
SYNOPSIS
#include <signal.h> void (* signal)(int sig, void (*func)(int));
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 i.e. to exit immediately, SIG_IGN, to ignore
control-C’s completely, 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.
EXAMPLE
#include <signal.h>
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
jmp_buf jb;
void
catch(int c)
{
longjmp(jb, 1);
}
main()
{
int i;
if(setjmp(jb)) {
printf(“\n\nCaught signal\n”);
exit(0);
B }
signal(SIGINT, catch);
for(i = 0 ;; i++ ) {
printf(“%6d\r”, i);
281
SIGNAL
}
}
SEE ALSO
exit
SIN
SYNOPSIS
#include <math.h>
double sin(double f);
DESCRIPTION
This function returns the sine function of its argument.
EXAMPLE
#include <math.h>
#include <stdio.h>
#define C 3.141592/180.0
main()
{
double i;
SEE ALSO
cos, tan, asin, acos, atan
283
SPAWNL, SPAWNV, SPAWNVE
DESCRIPTION
These function execute sub-programs under MS-DOS. The first argument is the program to execute. In
the case of spawnlp() and spawnvp() this may be simply a name, without path or file type. The function
will search the current PATH to locate the corresponding program, just as the DOS command line
interpreter does. The other functions require a path name with file type, e.g. C:\BIN\TEST.EXE.
The remaining arguments provide the command line arguments. These are a list of character pointers
(strings) terminated by a null pointer. This list can be explicit in the call (the l functions) or be a separate
array pointed to by a char ** pointer (the p functions). In either case the first entry in the list is the nominal
argv[0] which should appear in the called programs arguments. However since DOS does not pass this
to the called program, it is in fact an unused placeholder.
The functions ending in e also take an environment pointer. This is a pointer to an array of char * strings,
which will be used as the environment for the called program. The other functions use the global variable
environ to provide the environment. See getenv() for more information on environment variables.
EXAMPLE
#include <sys.h>
char * args[] =
{
“mem”, /* this is required */
“/c”,
0
};
main()
{
B
spawnlp(“mem”, “mem”, NULL);
spawnv(“c:\\dos\\mem.exe”, args);
}
RETURN VALUE
Failure to execute the program returns -1; otherwise the return value is the exit value of the spawned
program. By convention an exit value of zero means no error, and non-zero indicates some kind of error.
SEE ALSO
execl, execv
285
SPRINTF
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.
RETURN VALUE
Sprintf() returns the number of characters placed into the buffer.
SEE ALSO
printf, fprintf, sscanf
SQRT
SYNOPSIS
#include <math.h>
double sqrt(double f)
DESCRIPTION
Sqrt() implements a square root function using Newton’s approximation.
EXAMPLE
#include <math.h>
#include <stdio.h>
main()
{
double i;
SEE ALSO
exp
287
SRAND
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, or just using the system time.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
main()
{
time_t toc;
int i;
time(&toc);
srand((int)toc);
for(i = 0 ; i != 10 ; i++)
printf(“%d\t”, rand());
putchar(‘\n’);
}
SEE ALSO
rand
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
289
STAT
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:
{ 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 value. The file
size is self explanatory. The flag bits are as follows:
Flag Meaning
S_IFMTmask for file type S_IFDIRfile is a directory S_IFREGfile is a regular file S_IREADfile is
readable S_IWRITEfile is writeable S_IEXECfile is executable S_HIDDENfile is hidden S_SYS-
TEMfile is marked system S_ARCHIVEfile has been written to
EXAMPLE
#include <stdio.h>
#include <stat.h>
#include <time.h>
#include <stdlib.h>
main(argc, argv)
char ** argv;
{ B
struct stat sb;
if(argc > 1) {
if(stat(argv[1], &sb)) {
perror(argv[1]);
exit(1);
}
printf(“%s: %ld bytes, modified %s”, argv[1],
sb.st_size, ctime(&sb.st_mtime));
}
exit(0);
}
RETURN VALUE
Stat returns 0 on success, -1 on failure, e.g. if the file could not be found.
SEE ALSO
ctime, creat, chmod
291
STRCAT
STRCAT
SYNOPSIS
#include <string.h>
char * strcat(char * s1, char * s2);
DESCRIPTION
This function appends (catenates) string s2 to the end of string s1. The result will be null terminated. S1
must point to a character array big enough to hold the resultant string.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char buffer[256];
char * s1, * s2;
RETURN VALUE
The value of s1 is returned.
SEE ALSO
strcpy, strcmp, strncat, strlen
STRCHR
SYNOPSIS
#include <string.h>
char * strchr(char * s, int c)
DESCRIPTION
Strchr() searches the string s for an occurence of the character c. If one is found, a pointer to that character
is returned, otherwise NULL is returned.
RETURN VALUE
A pointer to the first match found, or NULL if the character does not exist in the string.
NOTE
Although the function takes an int argument for the character, only the lower 8 bits of the value are used.
SEE ALSO
strrchr, strlen, strcmp
293
STRCMP
STRCMP
SYNOPSIS
#include <string.h>
int strcmp(char * s1, char * s2);
DESCRIPTION
Strcmp() compares its two string (null terminated) arguments and returns a signed integer to indicate
whether s1 is less than, equal to or greater than s2. The comparison is done with the standard collating
sequence, which is that of the ASCII character set.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
int i;
RETURN VALUE
A signed integer less than, equal to or greater than zero.
NOTE
Other C implementations may use a different collating sequence; the return value is negative, zero or
positive, i.e. do not test explicitly for -1 or 1.
SEE ALSO
strlen, strncmp, strcpy, strcat
B
STRCPY
SYNOPSIS
#include <string.h>
int strcpy(char * s1, char * s2);
DESCRIPTION
This function copies a null-terminated string s2 to a character array pointed to by s1. The destination
array must be large enough to hold the entire string, including the null terminator.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char buffer[256];
char * s1, * s2;
RETURN VALUE
The destination buffer pointer s1 is returned.
SEE ALSO
strncpy, strlen, strcat, strlen
295
STRLEN
STRLEN
SYNOPSIS
#include <string.h>
int strlen(char * s);
DESCRIPTION
Strlen() returns the number of characters in the string s, not including the null terminator.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char buffer[256];
char * s1, * s2;
STRNCAT
SYNOPSIS
#include <string.h>
char * strncat(char * s1, char * s2, sizt_t n);
DESCRIPTION
This function appends (catenates) string s2 to the end of string s1. At most n characters will be copied,
and the result will be null terminated. S1 must point to a character array big enough to hold the resultant
string.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char buffer[256];
char * s1, * s2;
RETURN VALUE
The value of s1 is returned.
SEE ALSO
strcpy, strcmp, strcat, strlen
297
STRNCMP
STRNCMP
SYNOPSIS
#include <string.h>
int strncmp(char * s1, char * s2, size_t n);
DESCRIPTION
Strcmp() compares its two string (null terminated) arguments, up to a maximum of n characters, and
returns a signed integer to indicate whether s1 is less than, equal to or greater than s2. The comparison
is done with the standard collating sequence, which is that of the ASCII character set.
RETURN VALUE
A signed integer less than, equal to or greater than zero.
NOTE
Other C implementations may use a different collating sequence; the return value is negative, zero or
positive, i.e. do not test explicitly for -1 or 1.
SEE ALSO
strlen, strcmp, strcpy, strcat
STRNCPY
SYNOPSIS
#include <string.h>
int strncpy(char * s1, char * s2, size_t n);
DESCRIPTION
This function copies a null-terminated string s2 to a character array pointed to by s1. At most n characters
are copied. If string s2 is longer than n then the destination string will not be null terminated. The
destination array must be large enough to hold the entire string, including the null terminator.
EXAMPLE
#include <string.h>
#include <stdio.h>
main()
{
char buffer[256];
char * s1, * s2;
RETURN VALUE
The destination buffer pointer s1 is returned.
SEE ALSO
strcpy, strcat, strlen, strcmp
299
STRRCHR
STRRCHR
SYNOPSIS
#include <string.h>
char * strrchr(char * s, int c)
DESCRIPTION
Strrchr() is similar to strchr() but searches from the end of the string rather than the beginning, i.e. it
locates the last occurrence of the character c in the null-terminated string s. If successful it returns a
pointer to that occurrence, otherwise it returns NULL.
RETURN VALUE
A pointer to the character, or NULL if none is found.
SEE ALSO
strchr, strlen, strcmp, strcpy, strcat
SYSTEM
SYNOPSIS
#include <sys.h>
int system(char * s)
DESCRIPTION
When executed under MS-DOS system() will pass the argument 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(). Unfortunately this does not have any relation to the exit value returned
by the command executed by the command processor. Use one of the spawn() functions if you need to
test exit status.
The example sets the baud rate on COM1.
EXAMPLE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
main(argc, argv)
char ** argv;
{
/* set the baud rate on com1 */
system(“MODE COM1:96,N,8,1,P”);
}
SEE ALSO
spawnl, spawnv
301
TAN
TAN
SYNOPSIS
#include <math.h>
double tan(double f);
DESCRIPTION
This is the tangent function.
EXAMPLE
#include <math.h>
#include <stdio.h>
#define C 3.141592/180.0
main()
{
double i;
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 2.2
but does work under MS-DOS and CP/M+.
EXAMPLE
#include <stdio.h>
#include <time.h>
main()
{
time_t clock;
time(&clock);
printf(“%s”, ctime(&clock));
}
SEE ALSO
ctime, gmtime, localtime, asctime
303
TOLOWER, TOUPPER, TOASCII
DESCRIPTION
Toupper() converts its lower case alphabetic argument to upper case, tolower() performs the reverse
conversion, 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()
operation will return the character. At most one level of pushback will be allowed, and if the stream is
not buffered, even this may not be possible. EOF is returned if the ungetc() could not be performed.
SEE ALSO
getc
305
UNLINK
UNLINK
SYNOPSIS
#include <unixio.h>
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. The ANSI function remove() is preferred to unlink().
SEE ALSO
open, close, rename, remove
DESCRIPTION
These macros are provided to give access in a portable way to parameters to a function represented in a
prototype 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 example 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 function 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 ensure that correct arguments are supplied.
EXAMPLE
#include <stdio.h>
#include <stdarg.h>
pf(int a, ...)
{
va_list ap;
va_start(ap, a);
while(a—)
puts(va_arg(ap, char *));
va_end(ap);
B }
main()
{
307
VA_START, VA_ARG, VA_END
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() ).
EXAMPLE
#include <unixio.h>
main()
{
write(1, “A test string\r\n”, 15);
}
SEE ALSO
open, close, read
309
_DOS_GETFTIME
_DOS_GETFTIME
SYNOPSIS
#include <dos.h>
int _dos_getftime(int fd, unsigned short * date, unsigned short *
time);
DESCRIPTION
This function takes as its arguments a DOS file handle, and two pointers to unsigned shorts, into which
will be stored the DOS date and time values associated with the file identified by the file handle. Refer
to a DOS programming manual for information about the format of these values. The standard function
stat() is preferred for determining the modification date of a file.
EXAMPLE
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
main(argc, argv)
char ** argv;
{
FILE * fp;
unsigned short i, j;
if(argc == 1)
exit(1);
if(!(fp = fopen(argv[1], “r”))) {
perror(argv[1]);
exit(1);
}
_dos_getftime(fileno(fp), &i, &j);
printf(“date = %u, time =%u\n”, i, j);
}
SEE ALSO
stat
_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(). The argument is used as the program exit value for DOS.
EXAMPLE
main()
{
_exit(-1);
}
RETURN VALUE
None; the function will never return.
SEE ALSO
exit
311
_GETARGS
_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 processed. 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_.
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 and DOS 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.
< 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 following the
backslash is ignored, and not treated as white space.
EXAMPLE
#include <sys.h>
B
main(argc, argv)
char ** argv;
{
if(argc == 1) { /* no arguments */
argv = _getargs(0, “myname”);
argc = _argc_;
}
.
.
.
}
RETURN VALUE
A pointer to an array of strings.
NOTE
This routine is not usable in a ROM based system.
313
_XMS_ALLOC, _XMS_ALLOC_BYTES
_XMS_ALLOC, _XMS_ALLOC_BYTES
SYNOPSIS
#include <xms.h>
_XMS_HANDLE _xms_alloc(_XMS_SIZE_T size)
_XMS_HANDLE _xms_alloc_bytes(unsigned long size)
DESCRIPTION
The _xms_alloc() and _xms_alloc_bytes() functions are used to allocated blocks of XMS. The return
value is an XMS handle, or 0 if no memory could be allocated. The _XMS_HANDLE returned is used
by other XMS routines to access the allocated block. The argument to _xms_alloc() is a block size, in
1Kb increments. _xms_alloc_bytes() takes a block size in bytes, and will allocate an XMS block large
enough to hold the specified number of bytes.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE blk1, blk2;
RETURN VALUE
An _XMS_HANDLE, non zero on success, 0 on failure or if XMS is not available.
DATA TYPES
typedef unsigned int _XMS_HANDLE; typedef unsigned int _XMS_SIZE_T;
B
SEE ALSO
_xms_dispose, _xms_malloc, _xms_resize, _xms_resize_bytes
315
_XMS_DISPOSE
_XMS_DISPOSE
SYNOPSIS
#include <xms.h>
int _xms_dispose(_XMS_HANDLE handle)
DESCRIPTION
_xms_dispose() is used to free XMS blocks which have been allocated by _xms_alloc(), _xms_al-
loc_bytes(), _xms_resize() or _xms_resize_bytes(). Only XMS handles which have been obtained using
these routines should be passed to _xms_dispose().
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
RETURN VALUE
Integer, 1 on success, 0 on failure.
DATA TYPES
typedef unsigned int _XMS_HANDLE;
NOTE
Never attempt to _xms_dispose() handles from pointers obtained using _xms_calloc(), _xms_malloc(),
_xms_realloc() or _xms_sbrk.
SEE ALSO
_xms_alloc, _xms_alloc_bytes, _xms_resize, _xms_resize_bytes B
_XMS_DRIVER
SYNOPSIS
#include <xms.h>
_XMS_DRIVER _xms_driver(void)
DESCRIPTION
_xms_driver() returns a pointer to the XMS driver entry point. The return value is a 32 bit segment:offset
format pointer, suitable for use with the _driver() and _driverx() functions. If XMS is not installed, a
NULL pointer will be returned.
EXAMPLE
#include <stdio.h>
#include <xms.h>
union {
_XMS_DRIVER ptr;
struct {
unsigned short ofs;
unsigned short seg;
} w;
} xdriver;
main()
{
xdriver.ptr = _xms_driver();
printf(“Entry point = %4.4X:%4.4X\n”,
xdriver.w.seg, xdriver.w.ofs);
}
RETURN VALUE
A 32 bit segment:offset pointer which is the entry point for the XMS driver, or NULL if XMS is not
installed.
DATA TYPES
typedef far void * _XMS_DRIVER;
B SEE ALSO
_driver, _driverx, _xms_installed
317
_XMS_FLUSH
_XMS_FLUSH
SYNOPSIS
#include <xms.h>
void _xms_flush(_XMS_HANDLE handle)
DESCRIPTION
The _xms_flush() routine writes all “dirty” cache blocks belonging to the specified XMS handle back to
XMS. This routine may be used to ensure that all writes via the “high level” XMS support routines have
actually been stored to XMS. All XMS reads and writes performed using the following routines are
cached:
_xms_calloc()
_xms_get()
_xms_memmove()
_xms_memset()
_xms_put()
_xms_read()
_xms_write()
_xms_zalloc()
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
handle = _xms_alloc_bytes(SIZE);
if (handle) {
_xms_memset(handle, 0, 0xFF, SIZE);
printf(“Flush handle %4,4X\n”, handle);
_xms_flush(handle);
printf(“Done!\n”);
_xms_dispose(handle); B
} else
DATA TYPES
typedef unsigned int _XMS_HANDLE;
SEE ALSO
_xms_calloc, _xms_get, _xms_memmove, _xms_memset, _xms_put, _xms_read, _xms_write,
_xms_zalloc
319
_XMS_INFO
_XMS_INFO
SYNOPSIS
#include <xms.h>
int _xms_info(_XMS_HANDLE handle, struct _XMS_INFO * info)
DESCRIPTION
The _xms_info() call is used to determine the lock count for an XMS block, and the number of XMS
handles which are available.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
unsigned long addr;
struct _XMS_INFO info;
RETURN VALUE
Integer, 1 on success, 0 on failure.
DATA TYPES
typedef unsigned int _XMS_HANDLE; struct _XMS_INFO {
unsigned char lock_count;
unsigned char free_handles;
};
SEE ALSO
_xms_lock, _xms_unlock
321
_XMS_INSTALLED
_XMS_INSTALLED
SYNOPSIS
#include <xms.h>
int _xms_installed(void)
DESCRIPTION
_xms_installed() will return 1 if XMS is present, otherwise it will return 0. This function is generally
used to determine whether an XMS or conventional memory allocation scheme should be used.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
if (_xms_installed())
printf(“Using XMS\n”);
else
printf(“XMS not present\n”);
}
RETURN VALUE
An integer, 1 if XMS is present, otherwise 0.
SEE ALSO
_xms_driver
_XMS_LOCK
SYNOPSIS
#include <xms.h>
unsigned long _xms_lock(_XMS_HANDLE handle)
DESCRIPTION
_xms_lock() locks an XMS block, thereby preventing it from being moved, and returns its physical
address. The physical address returned is only valid while the block is locked. A locked block should
be unlocked as soon as possible, as it may prevent other blocks from being resized and cause memory
fragmentation. A lock count is maintained for extended memory blocks, the same number of _xms_lock()
calls as _xms_unlock() calls need to be made in order to unlock a block. The _xms_info() function may
be used to determine the lock count for an XMS block.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
unsigned long addr;
RETURN VALUE
Unsigned long, the physical address of the block on success, 0 on failure.
DATA TYPES
B typedef unsigned int _XMS_HANDLE;
SEE ALSO
_xms_info, _xms_unlock
323
_XMS_MEMAVAIL
_XMS_MEMAVAIL
SYNOPSIS
#include <xms.h>
int _xms_memavail(struct _XMS_FREE * mem)
DESCRIPTION
The _xms_memavail() function returns information about the amount of free XMS in the struct
_XMS_FREE provided by the user. All values in struct _XMS_FREE represent quantities of memory
in Kilobytes. For example, a “maxblock” value of 128 means that the largest XMS block which may be
allocated is 128Kb.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
struct _XMS_FREE mem;
if (_xms_memavail(&mem)) {
printf(“XMS available = %uKb”, mem.total);
printf(“Largest block = %uKb”, mem.maxblock);
printf(“XMS used = %uKb”, mem.used);
} else
printf(“XMS not available\n”);
}
RETURN VALUE
Integer, 1 on success, 0 on failure or if XMS is not present.
DATA TYPES
typedef unsigned int _XMS_SIZE_T; struct _XMS_FREE {
_XMS_SIZE_T maxblock;
_XMS_SIZE_T total;
_XMS_SIZE_T used;
};
B
SEE ALSO
_xms_info, _xms_version
325
_XMS_MEMSET
_XMS_MEMSET
SYNOPSIS
#include <xms.h>
int _xms_memset(_XMS_HANDLE dst, unsigned long ofs, int ch,
unsigned long size);
DESCRIPTION
_xms_memset() is used to set a block of XMS to a specified value. “Dst” is the destination handle, “ofs”
is the offset within the XMS block, “ch” is the fill character, and “size” is the number of bytes to clear.
All writes are performed via the XMS cache using the _xms_write() routine.
RETURN VALUE
Integer, 1 on success, 0 on failure.
DATA TYPES
typedef unsigned int _XMS_HANDLE;
SEE ALSO
_xms_memmove, _xms_write, _xms_zalloc
_XMS_MOVE
SYNOPSIS
#include <xms.h>
int _xms_move(struct _XMS_MOVE * move)
DESCRIPTION
_xms_move() is the C interface to the XMS driver “Move Extended Memory Block” call. Although this
function is intended to move blocks of data between conventional DOS memory and XMS, it can also
move data within conventional DOS memory and within XMS. XMS addresses are encoded as an XMS
handle plus a 32 bit offset. Conventional memory addresses are encoded as a zero handle plus a 32 bit
pointer.
The parameters for the move are taken from the _XMS_MOVE structure. The length of the transfer must
be even. Performance is improved if the blocks are word-aligned, or double word-aligned on 80386 and
80486 machines. Transfers of overlapping blocks should not be attempted using this routine. The
_xms_memmove() function provides a safe way of transferring overlapping blocks.
EXAMPLE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
struct _XMS_MOVE move;
char buf[256];
handle = _xms_alloc_bytes(sizeof(buf));
if (!handle) {
printf(“Couldn’t get XMS\n”);
exit(1);
}
strcpy(buf, “** TEST STRING - 0123456789 **”);
move.count = sizeof(buf);
move.src_handle = 0; /* conventional memory */
B move.src.ptr = buf;
move.dst_handle = handle; /* XMS */
move.dst.offset = 0;
if (!_xms_move(&move)) {
327
_XMS_MOVE
RETURN VALUE
Integer, 1 on success, 0 on failure or if XMS is not present.
DATA TYPES
union ptr_ofs { far void * ptr;
unsigned long offset;
};
struct _XMS_MOVE {
unsigned long count;
_XMS_HANDLE src_handle;
union ptr_ofs src;
_XMS_HANDLE dst_handle;
union ptr_ofs dst;
};
SEE ALSO
_xms_memmove, _xms_read, _xms_write
B
_XMS_READ
SYNOPSIS
#include <xms.h>
int _xms_read(_XMS_HANDLE src, unsigned int size,
unsigned long ofs, far void * dst)
DESCRIPTION
_xms_read()
is used to read from XMS via the cache. “Size” bytes are transferred to the destination address from
the specified offset within the source XMS handle. Odd length transfers are permitted, as _xms_read()
uses the XMS cache to hide the limitations of the XMS driver.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
char buf[256];
handle = _xms_alloc_bytes(sizeof(buf));
if (handle) {
_xms_write(handle, sizeof(test), 0, test);
_xms_read(handle, sizeof(test), 0, buf);
printf(“buf = ‘%s’\n”, buf);
_xms_dispose(handle);
} else
printf(“Unable to allocate XMS\n”);
}
RETURN VALUE
Integer, 1 on success, 0 on failure.
B
DATA TYPES
typdef unsigned int _XMS_HANDLE;
329
_XMS_READ
SEE ALSO
_xms_write
_XMS_RESIZE, _XMS_RESIZE_BYTES
SYNOPSIS
#include <xms.h>
int _xms_resize(_XMS_HANDLE handle, _XMS_SIZE_T new_size)
int _xms_resize_bytes(_XMS_HANDLE handle, unsigned long
new_size)
DESCRIPTION
The _xms_resize() and _xms_resize_bytes() functions are used to change the size of XMS blocks. If the
new block is the same size or larger, all data is copied. If the new size is smaller, all data at the upper
end of the block is lost. These functions both return an _XMS_HANDLE which is the new handle for
the block. With some XMS drivers this will be the same as the original handle. If the _xms_driver_re-
alloc flag is set, _xms_resize() and _xms_resize_bytes() will fail if the XMS driver “realloc” call cannot
be used and the same handle cannot be returned.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle, new;
RETURN VALUE
An _XMS_HANDLE on success, 0 on failure.
331
_XMS_RESIZE, _XMS_RESIZE_BYTES
DATA TYPES
typedef unsigned int _XMS_HANDLE; typedef unsigned int _XMS_SIZE_T;
NOTE
If these functions fail, the original block will not be affected and the old handle will still be valid.
_XMS_UNLOCK
SYNOPSIS
#include <xms.h>
int _xms_unlock(_XMS_HANDLE handle)
DESCRIPTION
_xms_unlock() is used to unlock XMS blocks which have previously been locked by one or more
_xms_lock() calls. Lock counts are maintained for XMS blocks, so _xms_unlock() and _xms_lock() calls
need to be balanced. The _xms_info() function may be used to determine the lock count for an XMS
block.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
unsigned long addr;
RETURN VALUE
Integer, 1 on success, 0 on failure.
DATA TYPES
typedef unsigned int _XMS_HANDLE;
B SEE ALSO
_xms_info, _xms_lock
333
_XMS_VERSION
_XMS_VERSION
SYNOPSIS
#include <xms.h>
int _xms_version(struct _XMS_VERSION * vers)
DESCRIPTION
This function returns information about the XMS driver in the _XMS_VERSION structure provided by
the user. The return value is 1 on success, 0 if XMS is not installed or driver information could not be
obtained. The “hma_exists” flag in struct _XMS_VERSION is used to determine whether the MS-DOS
High Memory Area at segment FFFF exists.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
struct _XMS_VERSION vi;
if (_xms_version(&vi)) {
printf(“XMS V%X.%2.2X\n”, vi.ver_major, vi.ver_minor);
printf(“Driver revision %X.%2.2X\n”, vi.rev_major,
vi.rev_minor);
if (vi.hma_exists)
printf(“HMA exists\n”);
else
printf(“No HMA\n”);
} else
printf(“XMS not available\n”);
}
RETURN VALUE
1 on success, 0 on failure or if XMS is not installed.
DATA TYPES
struct _XMS_VERSION { unsigned char ver_major;
unsigned char ver_minor; B
unsigned char rev_major;
unsigned char rev_minor;
SEE ALSO
_xms_info, _xms_memavail
335
_XMS_WRITE
_XMS_WRITE
SYNOPSIS
#include <xms.h>
int _xms_write(_XMS_HANDLE dst, unsigned int size,
unsigned long ofs, far void * src)
DESCRIPTION
_xms_write()
is used to write to XMS via the cache. “Size” bytes are transferred from the source address to the
specified offset within then destination XMS block. Odd length transfers are permitted, as _xms_write()
uses the XMS cache to hide the limitations of the XMS driver.
EXAMPLE
#include <stdio.h>
#include <xms.h>
main()
{
_XMS_HANDLE handle;
char buf[256];
handle = _xms_alloc_bytes(sizeof(buf));
if (handle) {
_xms_write(handle, sizeof(test), 0, test);
_xms_read(handle, sizeof(test), 0, buf);
printf(“buf = ‘%s’\n”, buf);
_xms_dispose(handle);
} else
printf(“Unable to allocate XMS\n”);
}
RETURN VALUE
Integer, 1 on success, 0 on failure.
DATA TYPES B
typedef unsigned int _XMS_HANDLE;
SEE ALSO
_xms_flush, _xms_read
337
_XMS_ZALLOC
_XMS_ZALLOC
SYNOPSIS
#include <xms.h>
_XMS_HANDLE _xms_zalloc(unsigned int n_elem, unsigned int size)
DESCRIPTION
This function will allocate and clear a block of XMS large enough to hold an array of “n_elem” elements,
each of “size” bytes. The block is cleared via a call to _xms_memset().
EXAMPLE
#include <stdio.h>
#include <xms.h>
#define COUNT 32
main()
{
_XMS_HANDLE handle;
RETURN VALUE
Integer, 1 on success, 0 on failure.
DATA TYPES
typedef unsigned int _XMS_HANDLE;
339
Index load, 49
1
argc, 78
argument
! passing, 45
arguments
to, 44
argv, 77
32 bit, 64
arrays
80186, 56
displaying, 84
80286, 56
as86
80386, 56
options, 55
80486, 56
pseudo, 68
8086, 55
pseudo-ops, 61
ASCTIME, 155
80C188EB, 88
ASIN, 157
_DOS_GETFTIME, 310
assembler, 55
_EXIT, 311
_GETARGS, 312
compatibility, 55
_XMS_ALLOC, _XMS_ALLOC_BYTES, 314
interface, 46
_XMS_DISPOSE, 316
listing, 56
_XMS_DRIVER, 317
output, 56
_XMS_FLUSH, 318
ASSERT, 158
_XMS_INFO, 320
ATAN, 159
_XMS_INSTALLED, 322
ATEXIT, 160
_XMS_LOCK, 323
ATOF, 161
_XMS_MEMAVAIL, 324
ATOI, 162
_XMS_MEMSET, 326
ATOL, 163
_XMS_MOVE, 327
AUTOEXEC.BAT, 3
_XMS_READ, 329
_XMS_RESIZE, _XMS_RESIZE_BYTES, 331
_XMS_UNLOCK, 333 B
_XMS_VERSION, 334
_XMS_WRITE, 336 baud rate , 97
_XMS_ZALLOC, 338 bp, 45
branch, 57
A BSEARCH, 164
ACOS, 154
address
arithmetic, 78
link, 49
340
Index
1
FREOPEN, 208 object, 56
FREXP, 209 inter-segment
FSCANF, 210 call, 57
FSEEK, 211 interrupt vectors, 89, 94
FTELL, 213 ISALNUM, ISALPHA, ISDIGIT, IS-
function LOWER et. al., 231
prototypes, 45 ISATTY, 233
FWRITE, 214 ISNEC98, 234
G J
main(), 43 pointers, 48
MALLOC, 244 POW, 254
MEMCHR, 245 powerup routine, 92
MEMCMP, 246 PRINTF, VPRINTF, 255
MEMCPY, 247 Processor Type, 92
MEMMOVE, 248 prototypes
memory function, 45
allocation, 45 psect, 49, 59, 61
Memory Model, 90 flags, 63
memory organization , 89 linking,100
MEMSET, 249 PUTC, 258
Microsoft PUTCH, 259
assembler, 55 PUTCHAR, 260
object, 58 PUTS, 261
MKDIR, 249 PUTW, 262
MS-DOS, 53
linker, 56 Q
N QSORT, 263
non-volatile RAM, 94 R
numbers
in linker options, 102 RAM
non-volatile, 94
O RAND, 265
READ, 266
OPEN, 251 REALLOC, 267
Optimisation , 95 reboot
options after installation, 3
linker, 102 reloc=, 50
relocatable
code, 59
P relocation,100
REMOVE, 268
PACC, 6 RENAME, 269
PACC.EXE, 3 reset address, 89
PACKING.LST, 1 REWIND, 270
PATH environment variable, 3 RMDIR, 271
342
Index
1
code, 48 STRRCHR,300
ROM Development, 88 symbols, 57
run-time startups, 88 global, 100
runtime SYSTEM, 301
organization, 43
startup, 43 T
S TAN, 302
temporary
SBRK, 272 labels, 58
SCANF, VSCANF, 273 TIME, 303
segment, 48 TOLOWER, TOUPPER, TOASCII, 304
SEGREAD, 275
serial number, 2 U
serial port , 88
serial.c, 96
SET_VECTOR, 279 undefined
SETJMP, 276 symbols, 55
SETVBUF, SETBUF, 277 UNGETC, 305
SIGNAL, 281 UNLINK, 306
signatures, 47
SIN, 283 V
size
error, 57 VA_START, VA_ARG, VA_END, 307
Source File List, 95
SPAWNL, SPAWNV, SPAWNVE, 284
SPRINTF, 286 W
SQRT, 287
SRAND, 288 WRITE, 309
SSCANF, 289
stack, 45
frame, 44
STAT, 290
STRCAT, 292
STRCHR, 293
STRCMP, 294
STRCPY, 295
STRLEN, 296
STRNCAT, 297
STRNCMP, 298
344
1
1 Introduction
3 Using PPD
4 Runtime Organization
A Error Messages
B Library Functions
1
1