1


2

Registration Card 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! 


Yourname: ______________________________________________ 
Company name (if applicable): _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
Your postal address: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ Country: _ _ _ _ _ _ _ _ _ _ _ _ Post/ Zip code: _ _ _ _ _ _ _ _ 
Phone:_ _ _ _ _ _ _ _ _ _ _ Fax:_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ E-mail: _ _ _ _ _ _ _ _ _ _ _ _ _ 
Software package: _______________________ Version: ____________ 
Serialno: _________ Suppliedby: _____________________________ 
I hereby agree to the terms and conditions of the licence agreement for this software 
Signed: 8 _______________________________________________ 
Unsigned registrations will not be accepted. 


Please help us to help you by answering the following questions. We will use 
this information to improve our products. 


Pacific C for DOS 
Fold here 
Please tick the operating 
systems you use: 


q MS-DOS 
q Windows 3. 1 or 3.11 or WfWg 
q Windows '95 
q Windows NT 
q OS/ 2 
q Unix (specify platform) 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 


q Other (please specify) 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 


Please indicate programming 
languages you use 


q C 
q C++ 
q Objective-C 
q Eiffel 
q Pascal 
q Modula-2 
q Modula-3 
q Simula 
q Smalltalk 
q Forth 
q Assembler 
q Other (please specify) 


________________ 


If you program embedded 
systems, please list the 
processors you use 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 
__ ___ ___ ___ ___ __ 


Thank you! 


1 
3

HI-TECH Software PO Box 103 
ALDERLEY QLD 4051 AUSTRALIA 


Please 
attach 
correct 
postage 


Tap e h ere 
1 
4

2 
3 
4 
5 
6 
7 
8 
9 
A 
B 


1 Introduction 
Quick Start Guide 
Using PPD 
Runtime Organization 
8086 Assembler Reference Manual 
Lucifer-A Source Level Debugger 
Rom Development with Pacific C 
Linker Reference Manual 
Librarian Reference Manual 
Error Messages 
Library Functions 


1 
5

1 
6

YOU SHOULD CAREFULLY READ THE FOLLOWING BEFORE INSTALLING OR USING THIS SOFTWARE PACK-AGE. 
IF YOU DO NOT ACCEPT THE TERMS AND CONDITIONS BELOWYOU 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-tration 
card and return it to HI-TECH Software immediately. 


SOFTWARE LICENCE AGREEMENT 
HI-TECH Software, a division of Gretetoy Pty. Ltd., of 41 Yarrabee Rd., The Gap, QLD 4061 Australia, provides this software pack-age 
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 
7

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: 


Pacific C; HI-TECH C; Lucifer; PPD; HPD 
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. 


Within Australia From elsewhere 
Fax 07 3354 2411 +61 7 3354 2422 
Phone 07 3354 2411 +61 7 3354 2411 
Electronic mail support@ htsoft. com support@ htsoft. com 
World Wide Web http:// www. htsoft. com http:// www. htsoft. com 


1 
8

There is also a mailing list you may join which carries discussion of Pacific C. For information or to join this list, send electronic mail 
to pacific-request@ htsoft. com. You will get an automatic reply with information on subscribing. 


HI-TECH Software a division of Gretetoy Pty. Ltd. 
PO Box 103, Alderley QLD 4051 Australia 


1 
9

1 
10

Contents 
1 -Introduction 
1.1 The Pacific C Compiler ............................ 1 


1.2 Installation ................................... 1 
1.2.1 INSTALL Program ........................... 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 


1 


Pacific C Compiler i 
11

3.4.4.1 Selecting Text .......................... 23 
3.4.4.2 Clipboard Commands ...................... 24 
3.5 PPD Menus .................................. 24 
3.5.1 <<>> Menu ............................... 26 


3.5.2 File Menu ................................ 27 
3.5.3 Edit Menu ............................... 28 
3.5.4 Options Menu ............................. 30 
3.5.5 Compile Menu ............................. 32 
3.5.6 Make Menu ............................... 33 
3.5.7 Run Menu ............................... 37 
3.5.8 Utility Menu .............................. 39 
3.5.9 Help Menu ............................... 42 
4 -Runtime Organization 
4.1 Memory Models ............................... 43 


4.2 Runtime Startup ............................... 43 
4.3 Stack Frame Organization .......................... 43 
4.4 Prototyped Function Arguments ...................... 45 
4.5 Stack and Heap Allocation ......................... 45 
4.6 Linkage to Assembler ............................ 45 
4.6.1 Assembler Interface Example ..................... 46 


4.6.2 Signatures ............................... 47 
4.7 Data Representation ............................. 48 
4.7.1 Longs .................................. 48 


4.7.2 Pointers ................................ 48 
4.7.3 Floats .................................. 48 
4.8 Linking 8086 Programs ........................... 48 
4.8.1 Terms .................................. 49 


4.8.2 Link and Load Addresses ....................... 49 
4.8.3 Segmentation .............................. 49 


1 
Pacific C Compiler 


ii 
12

4.8.4 Link Addresses ............................ 49 
4.8.5 Load Addresses ............................ 50 
4.8.6 Linking and the -P option ....................... 50 
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 
Contents 


Pacific C Compiler iii 
13

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 


1 
Pacific C Compiler 


iv 
14

5.3.5.7 I/ O ................................ 71 
5.3.5.8 Segment prefixes ......................... 71 
5.3.5.9 Jump ............................... 71 
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 


1 
Contents 


Pacific C Compiler v 
15

6.3.18 The = Command: display next page of source ............ 85 
6.3.19 The -Command: display previous page of source .......... 85 
6.3.20 The / Command: search source file for a string ............ 86 
6.3.21 The ! Command: execute a DOS command ............. 86 
6.3.22 Other Commands ........................... 86 
7 -ROM Development with Pacific C 
7.1 Requirements for ROM Development .................... 87 


7.2 ROM Code vs. DOS .EXE Files ....................... 87 
7.3 What You Need to Know .......................... 88 
7.4 First Steps .................................. 90 
7.4.1 Entering the Program .......................... 91 


7.4.2 Selecting Processor Type ........................ 91 
7.4.3 Choosing the File Type ........................ 93 
7.4.4 Setting Memory Addresses ....................... 93 
7.4.5 Selecting Optimizations ........................ 94 
7.4.6 Entering Source Files ......................... 94 
7.4.7 Making the Program .......................... 95 
7.4.8 Running the Code ........................... 95 
7.5 Going Further ................................ 96 


7.6 Implementing Lucifer ............................ 96 
7.7 Debugging with Lucifer ........................... 97 
8 -Linker Reference Manual 
8.1 Introduction ................................. 99 


8.2 Relocation and Psects ............................ 99 
8.3 Program Sections ............................. 100 
8.4 Local Psects ................................ 100 
8.5 Global Symbols .............................. 100 
8.6 Link and load addresses .......................... 100 
8.7 Operation ................................. 101 


1 
Pacific C Compiler 


vi 
16

8.7.1 Numbers in linker options ..................... 101 
8.7.2 -8 ................................... 101 
8.7.3 -Aclass= low-high,... ......................... 101 
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 
Contents 


Pacific C Compiler vii 
17

Appendix A -Error Messages ......................... 113 
Appendix B -Library Functions ........................ 151 


1 
Pacific C Compiler 


viii 
18

Chapter 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. 


1 


Pacific C Compiler 1 
19

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. 


1 
Chapter 1 -Introduction 


2 
20

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 
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. 


1 
Installation 


Pacific C Compiler 3 
21

1 
Chapter 1 -Introduction 


4 
22

Chapter 2 
Quick Start Guide 
2.1 Getting started 
For new users of the Pacific C compiler, the following section gives a step-by-step guide to getting a first 
program running with Pacific C. 


2.2 A Sample Program 
/* 
#include <stdio. h> 


main() 
{ 
printf(" Hello, world!\ n"); 
} 


2.3 Using PPD 
You will find a complete guide to using PPD in the section "PPD User's Guide" (page ). To enter this 
program, simply follow these steps: 


q Start PPD by typing its name, then pressing ENTER. If you have installed PPD properly, it will be 
in your search path. You should have on screen a menu bar, a large Edit window, and a smaller 
Message window. 


q Start typing the program text in the edit window. The editor command keys allow either the standard 
PC keys (arrow keys etc.) or WordStar-compatible keystrokes. 


q After typing the complete program (with any modifications necessary for your hardware) press 
ALT-S. Adialog box will appear asking you to enter a name to save the file. Type the name HELLO. C 
and press RETURN. The file will be saved to disk. 


q Press F3 to compile the program. PPD will compile the program. Any errors found will stop the 
compilation, and the errors will be listed in a window that appears at the bottom of the screen. The 
cursor in the edit window will be positioned on the error line. Correct the error, then press F3 again. 
You will not have to re-enter the memory addresses. On completion of compilation, an output file 
called HELLO. EXE will be left in the current directory. 


2 


Pacific C Compiler 5 
23

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. 


2.4 Using PACC 
To use PACC to compile your sample program, you will first need to create a file containing the program. 
You should use whatever text editor you are used to using, as long as it can create a plain ASCII file. The 
DOS EDIT command is satisfactory. Call the file HELLO. C. Then run PACC thus 


PACC HELLO. C 
If you have correctly entered the sample program, no error messages should result. If you do get error 
messages, edit the program to correct them, and recompile with PACC as before. After a successful 
compilation, PACC will print a memory usage summary. Then run your program by typing the command 


HELLO 
This will load and run HELLO. EXE. You should see the words "Hello, world!" appear. 


2 
Chapter 2 -Quick Start Guide 


6 
24

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 
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. 


3 


Pacific C Compiler 7 
25

3.2 The HI-TECH Windows User Interface 
The HI-TECH Windows user interface used by PPD provides a powerful text screen based user interface 
which can be used either by keyboard alone, or with a combination of keyboard and mouse operations. 
For new users most operations will be simpler using the mouse, however as experience with the package 
is gained hot-key sequences for most commonly used functions will be learned. 


3.2.1 Hardware Requirements 
HI-TECH Windows based applications will run on any MS-DOS based machine with a standard display 
card capable of supporting text screens of 80 columns by 25 rows or more. Higher resolution text modes 
like the EGA 80 x 43 mode will be recognised and used if the mode has already been selected before 


Figure 3-1; PPD Startup screen 


3 
Chapter 3 -Using PPD 


8 
26

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 
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: 


Action Key Mouse 
Open menu alt-Space Press left button in menu bar or press middle button anywhere on screen 
Escape from menu alt-Space or Escape Press left button outside menu system 
Select item Enter Release left or centre button on highlighted item 
Clickleft orcentrebutton on an item 
Next menu right arrow Drag to right 
Previous menu left arrow Drag to left 
Next item down arrow Drag downwards 
Previous item up arrow Drag upwards 


Table 3-1; PPD keyboard and mouse actions 


3 
The HI-TECH Windows User Interface 


Pacific C Compiler 9 
27

3.2. 2.1 Keyboard Menu Selection 
Selecting a menu itemby keyboard is accomplished by pressing alt-Space to open the menu system, then 
using the arrow keys to move to the desired menu and highlight the item required. When the item required 
is highlighted it can be selected by pressing Enter. Some menu items will displayed with lower intensity 
or a different colour and are not be selectable. These items are disabled because their selection is not 
appropriate within the current context of the application. To give an example, the Save project item will 
not be selectable if no project has been loaded or defined. 


3.2. 2.2 Mouse Menu Selection 
Selecting a menu item using the mouse appears to be somewhat awkward to new users, however it soon 
becomes second nature with experience. The menu system is opened by moving the pointer to the title 
of the menu which is desired and pressing the left button. It is possible to browse through the menu system 
by holding the left button down and dragging the mouse across the titles of several menus, opening each 
in turn. The menu system may also be operated with the middle button on three button mice. Pressing 
the middle button brings the menu bar to the front, making it selectable even if it is completely hidden 
by a zoomed window. 


Once a menu has been opened, two styles of selection are possible. If the left or middle button is released 
while no menu item is highlighted, the menu will be left open and selection can be made using the 
keyboard or by moving the pointer to the desired menu item and clicking the left or middle mouse button. 
If the mouse button is left down after the menu is opened, a selection can be made by dragging the mouse 
to the desired item and releasing the button. 


3.2. 2.3 Menu Hot Keys 
When browsing through the menu system you will notice that some menu items have hot key sequences 
displayed. For example, the PPD menu item Save has the key sequence alt-S displayed as part of the 
item. When a menu item has a key equivalent, it can be selected directly by pressing that key without 
opening the menu system. Key equivalents will be either alt-alphanumeric keys or function keys. Where 
function keys are used, different but related menu items will commonly be grouped on the one key. For 
example, in PPD F3 is assigned to Compile and Link, shift-F3 is assigned to Compile to .OBJ and 
ctrl-F3 is assigned to Compile to .AS. 


Key equivalents are also assigned to entire menus, providing a convenient method of going to a particular 
menu with a single keystroke. The key assigned will usually be alt and the first letter of the menu name, 
for example alt-E for the Edit menu. The menu key equivalents are distinguished by being highlighted 
in a different colour (except on monochrome displays) and are highlighted with inverse video when the 
alt key is depressed. 


A full list of PPD key equivalents is shown in table 3-2. 


3 
Chapter 3 -Using PPD 


10 
28

3.2.3 Selecting Windows 
HI-TECH Windows allows windows to be overlapped or tiled under user control. If using the keyboard, 
you can bring a window to the front by pressing ctrl-Enter one or more times. Each time ctrl-Enter is 
pressed, the rearmost window is brought to the front and each other window on screen shuffles one level 
towards the back. A series of ctrl-Enter presses will cycle endlessly through the window hierarchy. 


If you are using the mouse, you can bring any visible window to the front by pressing the left button in 
its content region 1 . A window can be made rearmost by holding the alt key down and pressing the left 
button in its content region. If a window is completely hidden by other windows, it can usually be located 
either by pressing ctrl-Enter a few times or by moving other windows to the back with alt-left-button. 


Some windows will not come to the front when the left button is pressed in them. These windows have 
a special attribute set by the application and are usually made that way for a good reason. To give an 
example, the PPD compiler error window will not be made front most if it is clicked, instead it will accept 
the click as if it were already the front window. This allows the mouse to be used to select the compiler 
errors listed while leaving the editor window front most so the program text can be altered. 


3.2.4 Moving and Resizing Windows 
Most windows can be moved and resized by the user. There is nothing on screen to distinguish windows 
which cannot be moved or resized, if you attempt to move or resize and window and nothing happens, it 
indicates that the window cannot be resized. Some windows can be moved but not resized, usually because 
their contents are of a fixed size and resizing the window would not make sense. The PPD calculator is 
an example of a window which can be moved but not resized. 


Windows can be moved and resized either using the keyboard or the mouse. When using the keyboard, 
move/ resize mode can be entered by pressing ctrl-alt-space. The application will respond by replacing 
the menu bar with the move/ resize menu ( ), allowing the front most window to be moved and resized. 


The allowable actions in move/ resize mode are as follows: 
Move/ resize mode can also be exited with any normal application action, like a mouse click, hot key or 
menu system activation with alt-space. 


Windows can also be moved and resized using the mouse. Any visible window can be moved by pressing 
the left mouse button on its frame, dragging it to a new position and releasing the button. If a window is 
"grabbed" near one of its corners the pointer will change to a diamond and it will be possible to move 
the window in any direction, including diagonally. If a window is grabbed near the middle of the top or 


3 
The HI-TECH Windows User Interface 


Pacific C Compiler 11 
1 * Pressing the left button in a window frame has a completely different effect, as discussed later in this chapter. 
29

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 
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 


Table 3-2; PPD menu hot keys 
3 


Chapter 3 -Using PPD 


12 
30

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. 


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 


The HI-TECH Windows User Interface 


Pacific C Compiler 13 
31

3.2.6 The Setup Menu 
If you open the system menu, identfified by the symbol <<>> on the menu bar, you will find two entries; 
an About entry which will display information about the version number of PPD, and a Setup entry. 
Selecting the Setup entry will open a dialogue box as shown in figure 3-6. This box both displays 
information about PPD's memory usave, and allows you to set the mouse sensitivity, whether the time 
of day is displayed in the menu bar, and whether sound is used. After changing mouse sensitivity values, 
you can test them by clicking on the Test button. This will change the mouse values so you can test the 
altered sensitivity. If you subsequently click Cancel, they will be restored to the previous values. Selecting 
OK will confirm the altered values, and save them in PPD's initialisation file, so they will be reloaded 
next time you run PPD. 


Similarly, the sound and clock settings will be stored in the initialisation file if you select OK. 


3.3 Tutorial: Creating and Compiling a C Program 
This tutorial should be sufficient to get you started using PPD, it does not attempt to give you a 
comprehensive tour of PPD's features, that is left to the reference section of this chapter. If you have not 
used a HI-TECH Windows based application before, we strongly suggest that you complete this tutorial 
even if you are an experienced C programmer. 


Before starting PPD, we first need to create a work directory. Make sure you are logged to the root 
directory on your hard disk and type the following commands: 


C:\> md tutorial 
C:\> cd tutorial 
C:\> TUTORIAL> PPD 


Key Action 
left arrow Move window to left 
right arrow Move window to right 
up arrow Move window upwards 
down arrow Move window downards 
shift-left arrow Shrink window horizontally 
shift-right arrow Expand window horizontally 
shift-up arrow Shrink window vertically 
shift-down arrow Expand window vertically 
Enter or Escape Exit move/ resize mode 


Table 3-3; Resize keys 
3 


Chapter 3 -Using PPD 


14 
32

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> 


/* 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. 


3 
Tutorial: Creating and Compiling a C Program 


Pacific C Compiler 15 
33

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 PPDwill 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. 


Figure 3-2; Hello proram in PPD 


3 
Chapter 3 -Using PPD 


16 
34

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. 


Figure 3-3; PPD File menu 


3 
Tutorial: Creating and Compiling a C Program 


Pacific C Compiler 17 
35

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). 


Figure 3-4; PPD File save dialogue 


3 
Chapter 3 -Using PPD 


18 
36

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. 


Figure 3-5; PPD Error window 


3 
Tutorial: Creating and Compiling a C Program 


Pacific C Compiler 19 
37

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.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 


3 
Chapter 3 -Using PPD 


20 
38

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 
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. 


3 
The PPD Editor 


Pacific C Compiler 21 
39

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 
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. 


3 
Chapter 3 -Using PPD 


22 
40

Read block from file ctrl-K R 
The ctrl-K R command prompts the user for the name of a text file which is to be read and inserted before 
the current line. The inserted text will be selected as the current block. This operation may be undone by 
deleting the current block. 
Write block to file ctrl-K W 
The ctrl-K Wcommand prompts the user for the name of a text file to which the current block selection 
will be written. This command does not alter the block selection, editor text or clipboard in any way. 


Indent 
This operation is available only via the Edit menu. It will indent by one tab stop the current block, or the 
current line if no block is selected. 
Outdent 
This is the complement to the previous operation, i. e. it removes one tab from the beginning of each line 
in the selection, or the current line if there is no block selected. It is accessible only via the Edit menu. 
Comment/ Uncomment 
Also available only in the Edit menu, this operation will insert or remove a C++ style comment leader 
(//) at the beginning of each line in the current block, or the current line if there is no block selected. If a 
line is currently uncommented, it will be commented, and if it is already commented, it will be 
uncommented. This is repeated for each line in the selection. This allows a quick way of commenting 
out a portion of code during debugging or testing. 


3.4.4 Clipboard Editing 
The PPD editor also supports mouse driven clipboard operations, similar to those supported by several 
well known graphical user interfaces. 


Text may be selected using mouse click and drag operations, deleted, cut or copied to the clipboard, and 
pasted from the clipboard. The clipboard is based on a standard editor window and may be directly 
manipulated by the user. Clipboard operations may be freely mixed with WordStar style block operations. 


3.4. 4.1 Selecting Text 
Blocks of text may be selected using left mouse button and click or drag operations. The following mouse 
operations may be used: Mouse Click A single click of the left mouse button will position the cursor and 
hide the current selection. The Hide menu item in the Edit menu, or the ctrl-K Hcommand, may be used 
to re display a block selection which was cancelled by a mouse click. Mouse Double Click A double 
click of the left mouse button will position the cursor and select the line as a single line block. Any 
previous selection will be cancelled. Mouse Click and Drag If the left button is pressed and held, a multi 
line selection from the position of the mouse click may be made by dragging the mouse in the direction 
which you wish to select. If the mouse moves outside the top or bottom bounds of the editor window, the 
editor will scroll to allow a selection of more than one page to be made. The cursor will be moved to the 
position of the mouse when the left button is released. Any previous selection will be cancelled. 


3 
The PPD Editor 


Pacific C Compiler 23 
41

3.4. 4.2 Clipboard Commands 
The PPD editor supports a number of clipboard manipulation commands which may be used to cut text 
to the clipboard, copy text to the clipboard, paste text from the clipboard, delete the current selection and 
hide or display the current selection. The clipboard window may be displayed and used as a secondary 
editing window. A number of the clipboard operations have both menu items and hot key sequences. The 
following clipboard operations are available: 
Cut alt-X 
The Cut option copies the current selection to the clipboard and then deletes the selection. This operation 
may be undone using the Paste operation. The previous contents of the clipboard are lost. 
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 ctrl-K H 
The Hide option toggles the current selection between the hidden and displayed state. This option is 
equivalent to the WordStar ctrl-K H command. 
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. 
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. 


3.5 PPD Menus 
This chapter presents a item-by-item description of each of the PPD menus. The description of each menu 
includes a screen dump showing the appearance of the menu within a typical PPD screen. 


3 
Chapter 3 -Using PPD 


24 
42

Command Key WordStar Key 
Character left left arrow ctrl-S 
Character right right arrow ctrl-D 
Word left ctrl-left arrow ctrl-A 
Word right ctrl-right arrow ctrl-F 
Line up up arrow ctrl-E 
Line down down arrow ctrl-X 
Page up PgUp ctrl-R 
Page down PgDn ctrl-C 
Start of line Home ctrl-Q S 
End of line End ctrl-Q D 
Top of window ctrl-Q E 
Bottom of window ctrl-Q X 
Start of file ctrl-Home ctrl-Q R 
End of file ctrl-End ctrl-Q C 
Goto previous line ctrl-Q P 
Insert mode toggle Ins ctrl-V 
Insert CR at cursor ctrl-N 
Open new line below cursor ctrl-O 
Delete char under cursor Del ctrl-G 
Delete char to left Backspace ctrl-H 
Delete line ctrl-Y 
Delete to end of line ctrl-Q Y 
Search F2 ctrl-Q F 
Search forwards shift-F2 ctrl-L 
Search backwards alt-F2 ctrl-P 
Toggle auto indent mode ctrl-Q I 
Zoom or unzoom window ctrl-Q Z 
Open file alt-O 
New file alt-N 
Save file alt-S 
Save file (new name) alt-A 


Table 3-4; Editor keys 
3 


PPD Menus 


Pacific C Compiler 25 
43

3.5.1 <<>> Menu 
The <<>> (system) menu is present in all HI-TECH Windows based applications. It contains any handy 
system configuration utilities and desk accessories which we considered to be worth making a standard 
part of the desktop. 
Setup ... 
This menu item selects the standard mouse firmware configuration menu, and is present in any HI-TECH 
Windows based application. The "mouse setup" dialogue allows you to adjust the horizontal and vertical 
sensitivity of the mouse, the ballistic threshold 2 of the mouse and the mouse button auto-repeat rate. This 
menu item will not be selectable if there is no mouse driver installed. With some early mouse drivers, 
this dialogue will not function correctly. Unfortunately there is no way to detect drivers which exhibit 
this behaviour because even the "mouse driver version info" call is missing from some of the older drivers! 


This dialogue will also display information about what kind of video card and monitor you have, DOS 
version, and free DOS memory available. See figure 3-6. 
About... 
The About dialogue displays information on the version number of PPD, the licence details, and the 
authors. 


Command Key Sequence 
Begin block ctrl-K B 
End block ctrl-K K 
Hide or show block ctrl-K H 
Go to block start ctrl-Q B 
Go to block end ctrl-Q K 
Copy block ctrl-K C 
Move block ctrl-K V 
Delete block ctrl-K Y 
Read block from file ctrl-K R 
Write block to file ctrl-K W 


Table 3-5; Block operation key sequences 
3 


Chapter 3 -Using PPD 


26 
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. 
44

3.5.2 File Menu 
The Edit menu contains editor file handling commands and the PPD Quit command. See figure 3-3. 
Open ... alt-O 
This command loads a file into the editor. You will be prompted for the file name and if a wildcard (e. g. 
"*. C") is entered, you will be presented with a file selector dialogue. If the previous edit file has been 
modified but not saved, you will be given an opportunity to save it or abort the command. 
New alt-N 
The New command clears the editor and creates a new edit file with default name "untitled". If the 
previous edit file has been modified but not saved, you will be given a chance to save it or abort the 
command. 
Save alt-S 
Save the current edit file. It the file is "untitled", you will be prompted for a new name, otherwise the 
current file name (displayed in the edit window's frame) will be used 


Figure 3-6; Setup dialogue 


3 
PPD Menus 


Pacific C Compiler 27 
45

Save as ... alt-A 
This command is similar to Save, except that a new file name is always requested. 
Autosave... 
This item will invoke a dialogue box allowing you to enter a time interval in minutes for auto saving of 
the edit file. If the value is non-zero, then the current edit file will automatically be saved to a temporary 
file at intervals. Should PPD not exit normally, e. g. if your computer suffers a power failure, then the 
next time you run PPD, it will automatically restore the saved version of the file. 
Quit alt-Q 
The Quit command is used to exit PPD to DOS. If the current edit file has been modified but not saved, 
you will be given an opportunity to save it or abort the command. 


3.5.3 Edit Menu 
The Edit menu contains items relating to the text editor and clipboard. The edit menu is shown in figure 
3-7. 
Cut alt-X 
The Cut option copies the current selection to the clipboard and then deletes the selection. This operation 
may be undone using the Paste operation. The previous contents of the clipboard are lost. 


Figure 3-7; PPD edit menu 
3 
Chapter 3 -Using PPD 


28 
46

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. 
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. 


3 
PPD Menus 


Pacific C Compiler 29 
47

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. 


Figure 3-8; PPD options menu 


3 
Chapter 3 -Using PPD 


30 
48

Memory model and chip type... 
This option activates a dialogue box which allows you to select which code generation memory model 
you wish to use. Available memory models are small (64K code plus 64K data) and large (large code 
and large data). You may also select the processor type, either 8086 or 80186/ 286. There is also a toggle 
for generation of 8087 (coprocessor) floating point instructions. By default a floating point library is 
linked that will work with or without a maths coprocessor. 
Heap size... 
This entry will open a dialogue box allowing you to set the heap size. The "heap size" value is placed in 
the .EXE file header to tell DOS how much heap and stack space should initially be allocated to the 
program. With Pacific C, it is used to limit the size of "near" data and heap, there is no "far" heap as 
such because the Pacific C memory allocation routines use MS-DOS system calls to obtain memory. The 
heap size should be entered as a hexadecimal value between 0 and 10000 (hex) inclusive. The default 
value is 0, which tells Pacific C to use a default heap size of 64K bytes. If a value larger than 64K is 
specified, it will not be accepted. 
Output file type 
The default output file type is a DOS .EXE file, i. e. an executable program. PPD will also create libraries 
that you can use to combine several modules you have written. Libraries are discussed in more detail in 
the Linker manual and the Utilities manua. This option will allow you to specifiy that you want to create 
a library rather than an .EXE file. A library can only be created from a project file. 
Getargs wild card expansion 
This option is a toggle, i. e. it is either on (indicated by a diamond shape next to it) or off (nothing next 
to it). When on, it will cause the linker to link into your program code to perform wild card expansion 
on command line arguments, i. e. command line arguments with * or ? characters will be expanded into 
matching file names. 
Use floating point library 
This option is also a toggle. It is used to tell the linker that you wish to use the floating point printf() 
support library. The float library includes a version of printf() which supports the floating point output 
formats %e, %f and %g. Use of this option will increase the size of the compiled application. You should 
only use this option if you wish to use floating point formats in printf(), it is not necessary if you only 
wish to perform floating point calculations. 
Source level debug info 
This menu item is used to enable or disable source level debug information in the current symbol file. If 
you are using a HI-TECH Software debugger like LUCIFER, you should enable this option. 
Suppress local symbols 
Prevents the inclusion of all local symbols in the symbol file. Even if this option is not active, the linker 
will filter irrelevant compiler generated symbols from the symbol file. 


3 
PPD Menus 


Pacific C Compiler 31 
49

3. 5. 5 Compile Menu 
The Compile menu, shown in figure 3-9, contains the various forms of the compile command along with 
several machine independent compiler configuration options. 
Compile and link F3 
This command will compile a single source file and then invoke the linker and objtoexe to produce an 
executable file. If the source file is an .AS file, it will be passed directly to the assembler. The output file 
will have the same base name as the source file, but a different extension. For example HELLO. C would 
be compiled to HELLO. EXE. 
Compile to .OBJ shift-F3 
Compiles a single source file to a .OBJ file only. The linker and objtoexe are not invoked. .AS files will 
be passed directly to the assembler. The object file produced will have the same base name as the source 
file and extension .OBJ. 


Figure 3-9; PPD Compile Menu 


3 
Chapter 3 -Using PPD 


32 
50

Compile to .AS ctrl-F3 
This menu item compiles a single source file to assembly language, producing an assembler file with the 
same base name as the source file and extension .AS This option is handy if you want to examine or 
modify the code generated by the compiler. If the current source file is an .AS file, nothing will happen. 
Stop on Warnings 
This toggle determines whether compilation will be halted when non-fatal errors are detected. A mark 
appears against this item when it is active. 


Warning level ... alt-W 
This command calls up a dialogue which allows you set the compiler warning level, i. e. it determines 
how picky the compiler is about legal but dubious code. The range of currently implemented warning 
levels is -3 to 9, lower warning levels are stricter. At level 9 all warnings (but not errors) are suppressed. 
Level 1 suppresses the "func() declared implicit int" message which is common when compiling Unix 
derived code. Level 3 is suggested for compiling code written with less strict (and K& R) compilers. Level 
0 is the default. This command is equivalent to the -W option to the PACC command. 
Optimization ... alt-Z 
Selecting this item will open a dialogue allowing you to select different kinds and levels of optimization. 
The default is no optimization. Selections made in this dialogue will be saved in the project file if one is 
being used. 
Pre-process assembler files 
Selecting this item (which will be indicated by a diamond mark against it if the menu is re-opened) will 
make PPD pass assembler files through the pre-processor before assembling. This makes it possible to 
use C pre-processor macros and conditionals in assembler files. 
Generate assembler listing 
This menu option tells the assembler to generate a listing file for each C or assembler source file which 
is compiled. The name of the list file is determined from the name of the symbol file, for example TEST. C 
will produce a listing file called TEST. LST. 


3.5.6 Make Menu 
The Make menu (figure 3-10) contains all of the commands required to use the PPD project facility. The 
project facility allows creation of complex multiple source file applications with ease, as well as a high 
degree of control of some internal compiler functions and utilities. 


To use the project facility, it is necessary to follow several steps. 
q Create a new project file using the Start new project ... command. After selecting the project file 
name, PPD will present several dialogues to allow you to set up the memory model. 


q Enter the list of source file names using the Source file list ... command. 


q Set up any special libraries, pre-defined pre-processor symbols, object files or linker options using 
the other items in the Make menu. 


3 
PPD Menus 


Pacific C Compiler 33 
51

q Save the project file using the Save project command. 
q Compile your project using the Make or Re-Make command. 
Make F5 
The Make command re-compiles the current project. When Make is selected, PPD re-compiles any source 
files which have been modified since the last Make command was issued. PPD determines whether a 
source file should be recompiled by testing the modification time and date on the source file and 
corresponding object file. If the modification time and date on the source file is more recent than that of 
the object file, it will be re-compiled. 


If all .OBJ files are current but the output file cannot be found, PPD will re-link using the object files 
already present. If all object files are current and the output file is present and up to date, PPD will print 
a message in the message window indicating that nothing was done. 


PPD will also automatically check dependencies, i. e. it will scan source files to determine what files are 
#included, and will include those files in the test to determine if a file needs to be recompiled, i. e. if you 
modify a header file, any source files #including that header file will need to be recompiled. 


Figure 3-10; PPD make menu 
3 
Chapter 3 -Using PPD 


34 
52

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. 
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 


3 
PPD Menus 


Pacific C Compiler 35 
53

Symbol file name ... 
This command allows selection of generation of a symbol file, and specification of the symbol file name. 
The default name of the symbol file will be generated from the project name, e. g. PROG1. SYM. The 
symbol file produced is suitable for use with any HI-TECH Software debugger. If Symbolic debug info 
in the Options menu is also selected, the symbol file will also contain line-number information for use 
with source level debuggers like the HI-TECH Software LUCIFER debugger. 
Source file list ... 
This option displays a dialogue which allows a list of source files to be edited. The source files for the 
project should be entered into the list, one per line. When finished, the source file list can be exited by 
pressing escape, clicking the mouse on the "DONE" button, or clicking the mouse in the menu bar. 


The source file list can contain any mix of C and assembly language source files. C source files should 
have suffix .C and assembly language files suffix .AS so that PPD can determine to which parts of the 
compiler files should be passed. 
Object file list ... 
This option allows any extra .OBJ files to be added to the project. One .OBJ file per line should be entered, 
operation of this dialogue is the same as for the source file list dialogue. This list will normally only 
contain one object file: the run-time startoff module for the current code generation model. For example, 
if a project is generating small model code, by default this list will contain the small model runtime startoff 
module RT86— DS. OBJ. Object files corresponding to files in the source file list SHOULD NOT be 
entered here as .OBJ files generated from source files are automatically used. This list should only be 
used for extra .OBJ files for which no source code is available, such as run-time startoff code or utility 
functions brought in from an outside source. 


If a large number of .OBJ files need to be linked in, they should be condensed into a single .LIB file using 
the LIBR utility and then accessed using the Library file list ... command. 
Library file list ... 
This command allows any extra object code libraries to be searched when the project is linked. This list 
normally only contains the default libraries for the memory model being used, for example if the current 
project is generating small model code and floating point code is in use, this list will contain the libraries 
86DSC. LIB and 86DSF. LIB. If an extra library, brought in from an external source is required, it should 
be entered here. 


It is a good practice to enter any non-standard libraries before the standard C libraries, in case they 
reference extra standard library routines. The normal order of libraries should be: user libraries, floating 
point library, standard C library. The floating point library should be linked before the standard C library 
if floating point is being used. 


3 
Chapter 3 -Using PPD 


36 
54

CPP pre-defined symbols ... 
This command allows any special pre-defined symbols to be defined. Each line in this list is equivalent 
to a -D option to the command line compiler PACC. For example, if a CPP macro called DEBUG with 
value 1, needs to be defined, add the line DEBUG= 1 to this list. Some standard symbols will be 
pre-defined in this list, these should not be deleted as some of the standard header file rely on their 
presence. 
CPP include paths ... 
This option allows extra directories to be searched by the C pre-processor when looking for header files. 
When a header file enclosed in angle brackets, for example <stdio. h> is included, the compiler will search 
each directory in this list until it finds the file. 


Linker options ... 
This command allows the options passed to the linker by PPD to be modified. The default contents of 
the linker command line are generated by the compiler from information selected in the Options menu: 
memory model, etc. You should only use this command if you are sure you know what you are doing ! 
Objtohex options ... 
This command allows the options passed to objtohex by PPD to be modified. Normally you will not need 
to change these options as generation of .EXE files can be selected in the Options menu. If you want to 
generate one of the "strange" output formats which objtohex can produce, like COFF files, you will need 
to change the objtohex options using this command. 


3.5.7 Run Menu 
The Run menu shown in figure 3-11 contains options allowing MS-DOS commands and user programs 
to be executed. 


Macro name Meaning 
$( LIB) Expands to the name of the system library file directory, e. g. 
C:\ PACIFIC\ LIB\ 


$( CWD) The current working directory. 
$( INC) The name of the system include directory. 
$( EDIT) The name of the file currently loaded into the editor. If the current file has been modified, this 
will be replaced by the name of the auto saved temporary file. On return this will be reloaded 
if it has changed. 


$( OUTFILE) The name of the current output file, i. e. the executable file 
$( PROJ) The base name of the current project, e. g. if the current project file is AUDIO. PRJ, this macro 
will expand to AUDIO with no dot or file type. 


Table 3-6; Macros usable in user commands 


3 
PPD Menus 


Pacific C Compiler 37 
55

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. 


Figure 3-11; PPD run menu 


3 
Chapter 3 -Using PPD 


38 
56

DOS Shell alt-J 
This item will invoke a DOS COMMAND. COM shell, i. e. you will be immediately presented with a 
DOS prompt, unlike the DOS command item which prompts for a command. To return to PPD, type 
"exit" at the DOS prompt. 
Debug PROG. EXE 
This option runs the LUCIFER debugger with the current compiled program and symbol file. See the 
Lucifer manual for more information on debugging. 


3.5.8 Utility Menu 
The Utility menu contains any useful utilities which have been included in PPD. 
String Search... 
The String Search command will allow you to search multiple files for occurences of a regular expression. 
When selected, a dialog box opens that allows you to enter a search string, and a file list. The search 
string can be simply any sequence of characters, including spaces, that will be searched for anywhere in 
the named files. The file list is a space-separated list of file names. You can use wild cards in this list, 


Figure 3-12; PPD utility menu 
3 
PPD Menus 


Pacific C Compiler 39 
57

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 
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. 


3 
Chapter 3 -Using PPD 


40 
58

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. 


Figure 3-13; PPD help menu 
3 
PPD Menus 


Pacific C Compiler 41 
59

3.5.9 Help Menu 
The Help menu contains items allowing help about any topics listed to be obtained. For most cross 
compilers this menu will contain an on-line C library reference, and editor key table and an instruction 
set reference for the target processor. 


On startup, PPD searches the current directory and the help directory for TBL files ,which are added to 
the Help menu. The path of the help directory can be specified by the environment variable 
HTC_ Z80_ HLP. If this is not set, it will be derived from the full path name used when PPD was invoked.. 
If the help directory cannot be located, none of the standard help entries will be available. 
C Library Reference 
This command selects an on-line manual for the standard ANSI C library. You will be presented with a 
window containing the index for the manual. Topics can be selected by double clicking the mouse on 
them, or by moving the cursor with the arrow keys and pressing return. 


Once a topic has been selected, the contents of the window will change to an entry for that topic, similar 
to the one shown below. You can move around within the reference using the keypad cursor keys and 
the index can be re-entered using the INDEX button at the bottom of the window. If you have a mouse, 
you can follow hypertext links by double clicking the mouse on any word, for example if you are in the 
printf entry and double click on the reference to fprintf, you will be taken to the entry for fprintf. 


This window can be re-sized and moved at will, and thus can be left on screen while the editor is in use. 
Editor Keys 
This menu item displays a window which contains a complete listing of the editor keyboard commands. 
The editor keys window may be scrolled using the scroll bar in the right edge of the window, or by using 
the down arrow, PgDn, up arrow and PgUp keys. The window may be closed by clicking on the close 
box in the top left corner of the frame, or by pressing ESC when the window is front most. 


3 
Chapter 3 -Using PPD 


42 
60

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. 


4.1 Memory Models 
The memory models supported by the compiler are shown table 4-1. In the table, small means not more 
than 64K bytes. Note also that in small model, the stack size is included in the data size. In large model 
the stack size may not exceed 64K. Code compiled for one model is not compatible with code compiled 
for another model. 


4.2 Runtime Startup 
The code located at the start address performs some initialization, notably clearing of the bss (uninitialized 
data) segment. It also calls a routine to set up the argv, argc values. Depending on compile-time options, 
this routine may or may not expand wild cards in file names (? and *) and perform I/ O redirection. 


The code for the startup tasks is in one of the startup modules listed in the table. 
Having set up the argument list, the startup code calls the function _main. Note the underscore ('_ ') 
prepended to the function name. All symbols derived from external names in a C program have this 
character prepended by the compiler. This helps prevent conflict with assembler names. The function 
main() is, by definition of the C language, the "main program". 


4.3 Stack Frame Organization 
On entry to _main, and all other C functions, some code is executed to set up the local stack frame. The 
exact code depends on whether the function has any arguments, or uses any register variables and whether 
it is prototyped. This can involve saving bp, copying sp to bp then adjusting sp to allow space for local 
variables, then finally saving si and di on the stack if required. Typical code on entry to a function would 
be: 


Model Run-time startoff 
module 
Standard 
library 
Float library Size limits 


Small RT86-DS. OBJ 86— DSC. LIB 86— DSF. LIB small code, small data 
Large RT86-DL. OBJ 86— DLC. LIB 86— DLF. LIB large code, large data 


Table 4-1; Memory models 


4 


Pacific C Compiler 43 
61

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 
bytes. If a char is passed as an argument, it is expanded to int length. 


Figure 4-1; Stack frame 
4 
Chapter 4 -Runtime Organization 


44 
62

Local variables are accessed at locations -1[ bp] downwards. 
Exit from the function is accomplished by restoring register variables, reloading sp from bp, then popping 
the saved bp. A return (small code) or far return (large code) is then executed. It is the responsibility of 
the calling function to remove arguments from the stack. 


4.4 Prototyped Function Arguments 
The above description holds generally true for all functions, however it is modified for functions with 
prototypes. Where the compiler is given argument information via a prototype, it optimizes parameter 
passing as follows: 


If a function has a fixed number of arguments, the first and second arguments will, if they are int length 
or less, be passed in DX and AX respectively. Arguments past the first two or bigger than int size will 
be passed on the stack as usual. If a function has a variable argument list (using ellipsis in the prototype) 
the argument immediately before the ellipsis will always be passed on the stack, to allow the variable 
part of the argument list to be anchored. 


In addition, a prototyped function with a fixed argument list will deallocate the parameters off the stack 
itself, rather than the calling function doing it. It does this with the "return and deallocate" forms of the 
RET instruction, e. g. RET #4. 


4.5 Stack and Heap Allocation 
As previously mentioned, the stack grows downwards. On startup, the stack pointer is initialized to the 
top of available memory. The heap, i. e. the area of memory dynamically allocated via sbrk(), calloc() or 
malloc(), grows upwards from the top of statically allocated memory. This is defined by the top of the 
bss segment, which the linker gives the name __ Hbss. Sbrk() checks the amount of memory left between 
the top of the heap and the bottom of the stack, and if less than 1k bytes (4k for the large model) would 
be left after granting the sbrk() request, it will deny it. This value may be modified by editing sbrk. as, 
re-assembling it and replacing it in the library. 


4.6 Linkage to Assembler 
It is quite feasible to write assembler routines to interface with C code. The following points should be 
noted: 


q When a routine is called from C, the arguments are pushed onto the stack in reverse order, so that 
the lexically first argument to the call will have the lowest memory address. The same convention 
must be followed by an assembler routine calling a C function. 


4 
Prototyped Function Arguments 


Pacific C Compiler 45 
63

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 
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: 


4 
Chapter 4 -Runtime Organization 


46 
64

; peek( unsigned seg, unsigned offs) 
.psect _TEXT 
.globl _peek 
_peek: 
mov es, dx ;segment part 
mov bx, ax ;offset part 
mov al, es:[ bx] 
mov ah,# 0 
ret 


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. 


4 
Linkage to Assembler 


Pacific C Compiler 47 
65

4.7 Data Representation 
The sizes of various data types are shown in the table below. For the 8086 byte ordering is always low 
byte first. 


4.7.1 Longs 
Long values are represented in 32 bits, with the low order word first. Within each word, the 8086 imposes 
a byte ordering of low byte first. This means that a long value is laid out as shown in figure 4-3. 


4.7.2 Pointers 
Pointers in the tiny and small model are 16 bits, and represent only the offset portion of the address. The 
DS register supplies the segment portion of the address for all data references (SS is set to the same as 
DS) while the CS register supplies the segment part of all text (i. e. program code) references. 


When the large memory model is used, all pointers occupy 32 bits. Note that all statically allocated data 
will be accessed within the segment pointed to by DS. ES is used direct accesses to local variables and 
parameters. SS and DS are initialized at program startup and are not modified. 


4.7.3 Floats 
Float and double are stored in 32 and 64 bit quantities respectively. The representation is as used by the 
8087 numeric co-processor, i. e. IEEE format. 


4.8 Linking 8086 Programs 
The subject of object code linking in general is complex; where the 8086 is concerned it is complicated 
by its segmented architecture. It is necessary to have a reasonable understanding of the issues involved 
if you wish to use the linker directly, i. e. rather than using the C command to perform all linking. The 
HI-TECH linker is very flexible, being suitable for ROM code as well as .EXE files, however this 
flexibility naturally involves the user making appropriate decisions in the linking process. You may need 


Data type Size (bits) 
int 16 
char 8 
short 16 
long 32 
float 32 
double 64 


Table 4-2; Data types 


4 
Chapter 4 -Runtime Organization 


48 
66

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 
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, 


address+ 0 address+ 1 address+ 2 address+ 3 
least significant byte 1 byte 2 most significant 


Figure 4-3; Long layout in memory 


4 


Linking 8086 Programs 


Pacific C Compiler 49 
67

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. 


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 


4 
Chapter 4 -Runtime Organization 


50 
68

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 


Figure 4-4; Small model memory layout 
4 


Linking 8086 Programs 


Pacific C Compiler 51 
69

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 


Figure 4-5; Large model memory layout 


4 
Chapter 4 -Runtime Organization 


52 
70

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 CODEclass 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 
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. 


4.9 Absolute Variables 
A global or static variable can be located at an absolute address by following its declaration with the 
construct @ address, for example: 


volatile unsigned char portvar @ 0x1020; 
will declare a variable called portvar located at 1020h. Note that the compiler does not reserve any storage, 
but merely equates the variable to that address, the compiler generated assembler will include a line of 
the form: 


_Portvar equ 1020h 
Note that the compiler and linker do not make any checks for overlap of absolute variables with other 
variables of any kind, so it is entirely the programmer's responsibility to ensure that absolute variables 
are allocated only in memory not in use for other purposes. 


4 
Absolute Variables 


Pacific C Compiler 53 
71

4.10 Port Type Qualifier 
The 8086 I/ O ports may be accessed directly via port type qualifier. For example, consider the following 
declaration: 


port unsigned char * pptr; 
port unsigned char io_ port @ 0xE0; 
The variable pptr is a pointer to an 8 bit wide port and the variable io_ port is mapped directly onto port 
0E0H and will be accessed using the appropriate IN and OUT instructions. For example, the statements 


io_ port |= 0x40; 
*pptr = 0x10; 
will generate the following code: 
;x. c: 8: io_ port |= 0x40; 
mov dx,# 224 
in al,[ dx] 
or al,# 64 
out [dx], al 
;x. c: 10: *pptr = 0x10; 
mov al,# 16 
mov dx,_ pptr 
out [dx], al 


4 


Chapter 4 -Runtime Organization 


54 
72

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 
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. 


5 


Pacific C Compiler 55 
73

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.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. 


5 
Chapter 5 -8086 Assembler Reference Manual 


56 
74

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.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. 


5 
The Assembly Language 


Pacific C Compiler 57 
75

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 
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 


Character Radix Name 
B 2 binary 
O 8 octal 
Q8 octal 
o8 octal 
q8 octal 
H16 hexadecimal 
h 16 hexadecimal 


Table 5-1; Constant radix suffixes 


5 


Chapter 5 -8086 Assembler Reference Manual 


58 
76

2: call fred ;here from jnz 2f 
1: ret ;here from jr 1f 


The digit string may be any positive decimal number 0 to 65535. A temporary label value may be re-used 
any number of times. Where a reference to e. g. 1b is made, this will reference the closest label 1: found 
by looking backwards from the current point in the file. Similarly 23f will reference the first label 23: 
found by looking forwards from the current point in the file. 


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 
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 


alabel: mov bx,# astring 


5 
The Assembly Language 


Pacific C Compiler 59 
77

call putit 
mov bx,# anotherstring 


psect data, global 
astring: 
.byte 'A string of chars', 0 
anotherstring: 


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 
.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. 


Table 5-2; AS86 expression operators 
5 


Chapter 5 -8086 Assembler Reference Manual 


60 
78

.byte 'Another string', 0 
.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 
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). 


5 
The Assembly Language 


Pacific C Compiler 61 
79

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.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: 


5 
Chapter 5 -8086 Assembler Reference Manual 


62 
80

.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.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. 


5 
The Assembly Language 


Pacific C Compiler 63 
81

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. 


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: 


5 
Chapter 5 -8086 Assembler Reference Manual 


64 
82

.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 
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 .MACRO par1,par2, par3 ;copy par1 to par2 
mov ax, par1& par3 
mov par2& par3, ax 
.ENDM 


copy loc1,loc2 
; expands to: 
mov ax, loc1 
mov loc2,ax 


copy loc1,loc2, x_ 
; expands to: 
mov ax, loc1_ x 


5 
The Assembly Language 


Pacific C Compiler 65 
83

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 
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 


5 
Chapter 5 -8086 Assembler Reference Manual 


66 
84

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 


5.3. 4.18 .IRP and .IRPC 
The .IRP and .IRPC directives operate similarly to .REPT, however instead of repeating the block a 
fixed number of times, it is repeated once for each member of an argument list. In the case of .IRP the 
list is a conventional macro argument list, in the case or .IRPC it is each character in one argument. For 
each repetition the argument is substituted for one formal parameter. For example: 


.IRP arg, lab1, lab2,# 23 
mov ax, arg 
stos word 
.ENDM 


; 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 


5 
The Assembly Language 


Pacific C Compiler 67 
85

; 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 


5.3. 4.19 Macro Invocations 
When invoking a macro, the argument list must be comma-separated. If it is desired to include a comma 
(or other delimiter such as space) in an argument then angle brackets (< and >) may be used to quote an 
argument. In addition the exclamation mark (!) may be used to quote a single character. The character 
immediately following the exclamation mark will be passed into the macro argument even if it is e. g. a 
semicolon, normally a comment indicator. 


If an argument is preceded by a percent sign (%) then that argument will be evaluated as a expression 
and passed as a decimal number, rather than as a string. This is useful if evaluation of the argument inside 
the macro body would yield a different result. 


5.3. 4.20 .TITLE 
This pseudo-op sets a title string to be used on the assembler listing. White space following the pseudo-op 
is skipped, then the rest of the line used as the title. This pseudo-op will not be listed. E. g. 


.TITLE Widget control program 
5.3. 4.21 .SUBTTL 
Subttl defines a sub-title for the program listing. The argument to it is similar to that for .TITLE. .SUBTTL 
will also cause a .PAGE to be executed. This pseudo-op will not appear in the listing. Example: 


.SUBTTL Initialization phase 
5.3. 4.22 .PAGE 
This causes a new page to be started in the listing. .PAGE is never listed. 
5.3. 4.23 .INCLUDE 
This directive allows the inclusion of other files in the assembly. For example: 
.INCLUDE macrodefs. i 


5 
Chapter 5 -8086 Assembler Reference Manual 


68 
86

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 


.LIST ;turn listing on 
fred ;expand the macro; this line appears 
; and so does this line 


5.3.5 Addressing Modes 
The 8086 (16 bit) addressing modes are represented as follows: 


5.3. 5.1 Register 
This is identical to the Intel register addressing mode. Example: 
mov ax, bx 


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. 


5 
The Assembly Language 


Pacific C Compiler 69 
87

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.4 Register indirect 
Square brackets are used in general to denote indirect addressing; register indirect requires the register 
name to be enclosed in brackets, e. g. 


mov al,[ si] 


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: 


5 
Chapter 5 -8086 Assembler Reference Manual 


70 
88

rep movs byte 
cmps word, es: 


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 


5.3.5.8 Segment prefixes 
Segment prefixes may be applied to any memory address in the usual manner. e. g. 
mov ss: 24,# 4, word 


5.3. 5.9 Jump 
The operands to jump and call instructions are normally treated as direct addressing, e. g. 
jmp jail ;go directly to jail 


Indirect addressing is indicated by enclosing a direct address in square brackets, e. g. 
jmpf [somewhere+ 4] 


Indexed addressing is as described above. 
5. 3. 6 80386 Addressing Modes 
The addresing modes for the 80386 are basically the same as above, except that 32 bit offsets and direct 
addresses are used instead of 16 bits. The indexed addressing form is however completely different. Refer 
to an 80386 programming handbook for full details, however the basic modes are summarized below. 
Note that any 32 bit general register plus ESP may be used in 386 indexed addresses. 


5.3.6.1 Segment Registers 
The 80386 has two extra segment registers (FS and GS) which can be used in the same manner as normal 
8086 segment registers. FS: and GS: can be included as segment overrides in instructions in the normal 
manner. Two new instructions, LFS and LGS are present and used in the same manner as LES. Example: 


5 
The Assembly Language 


Pacific C Compiler 71 
89

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.3.6.3 Single register 
This form has a single register optionally with an offset. Example: 
mov eax, 24[ ebx] 
5.3. 6.4 Double indexed 
This form allows two index registers, optionally with an offset. Example: 
mov ebp, alabel[ edx][ esi] 
5.3. 6.5 Scaled index 
This form allows one register to be multiplied by 2, 4 or 8 before being used in the address. Example: 
lea esi, 4[ eax][ edx* 4 


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. 


5 
Chapter 5 -8086 Assembler Reference Manual 


72 
90

80386 instruction/ addressing mode 
An instruction or addressing mode peculiar to the 80386 encountered. Use a .386 or .486 directive to 
allow these. 
80486 instruction/ addressing mode 
An instruction or addressing mode peculiar to the 80486 encountered. Use a .486 directive to allow these. 
absolute expression required 
An absolute expression is required in this context. 
bad character const 
This character constant is badly formed. 
bad operand size 
This instruction requires an operand size of byte. Any other size is illegal. 
conflicting operand sizes 
This instruction has more than one operand size specified. They are incompatible. 
division by zero 
An expression resulted in a division by zero. 
duplicate base register 
Only one base register, i. e. only one of BP and BX may be used in a 16 bit indexed addressing form. 
duplicate displacement in operand 
The operand on this instruction has two offsets. Only one is permitted. 
duplicate index register 
Only one index register (SI or DI) may be used in a 16 bit indexed form. 
esp not permitted as index register 
ESP is not permitted as an index register. 
expression error 
There is a syntax error in this expression. 
flag * unknown 
This option used on a "PSECT" directive is unknown to the assembler. 
floating number expected 
The arguments to the "DEFF" pseudo-op must be valid floating point numbers. 
garbage after operands 
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. 
illegal addressing mode 
This addressing mode is not permitted. 
illegal stack index 
The index used in a cop-processor instruction must be an absolute value 0-7. 
illegal switch * 
This command line option was not understood. 


5 
Diagnostics 


Pacific C Compiler 73 
91

indirection on illegal register 
Indirection on this register is not possible. 
insufficient memory for macro def'n 
out of memory 
The assembler has run out of memory. Try splitting your source file into a number of smaller modules. 
jump target out of range 
The address that this jump refers to is too far away to be reached by this jump. Use a longer jump form, 
or a short branch around a direct jump. 
lexical error 
An unrecognized character or token has been seen in the input. 
local illegal outside macros 
The "LOCAL" directive is only legal inside macros. It defines local labels that will be unique for each 
invocation of the macro. 
macro argument after % must be absolute 
If the charactyer "%" is used to force evaluation of macro argument, the argument must be an expression 
that evaluates to an absolute constant. 
macro argument may not appear after local 
The list of labels after the directive "LOCAL" may include any of the formal parameters to the macro. 
macro expansions nested too deep 
include files nested too deep 
Macro expansions and include file handling have filled up the assembler's internal stack. 
missing ') ' 
A closing parenthesis was missing from this expression. 
missing '] ' 
A closing square bracket was missing from this expression. 
mixed 16 and 32 bit index registers 
An indexed addressing mode must use only 16 bit or only 32 bit registers. They may not be used together. 
multiply defined symbol * 
This symbol has been defined in more than one place in this module. 
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 file argument 
There was no file argument to the assembler. 
no space for macro def'n 
The assembler has run out of memory. 
one segment override only permitted 
Only one segment override is permitted in an instruction. 
oops! -ve number of nops required! 
An internal error has occured. Contact HI-TECH. 


5 
Chapter 5 -8086 Assembler Reference Manual 


74 
92

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. 
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. 


5 
Diagnostics 


Pacific C Compiler 75 
93

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 
program. 
undefined symbol * 
The named symbol is not defined, and has not been specified "GLOBAL". 
undefined temporary label 
Atemporary 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. 


5 


Chapter 5 -8086 Assembler Reference Manual 


76 
94

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.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: 


6 


Pacific C Compiler 77 
95

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. 


More examples: 
bp-4 (address SS: BP -4) 
ds: dx (address DS: DX) 
0f121 (address 0f121 in default segment) 
ds: 200 (address DS: 0200) 


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. 


6 
Chapter 6 -Lucifer -A Source Level Debugger 


78 
96

6.3.2 The B Command: set or display breakpoints 
The b command is used to set and display breakpoints. If no expression is supplied after the b command, 
a list of all currently set breakpoints will be displayed. If an expression is supplied, a breakpoint will be 
set at the line or address specified. If you attempt to set a breakpoint which already exists, or enter an 
expression which Lucifer cannot understand, an appropriate error message will be displayed. Note: any 
decimal number specified will be interpreted as a line number by default, if you want to specify an absolute 
address, prefix it with a dollar sign or use a symbol name. 


:b 10 
Set breakpoint at _main+ 27 
: 


Example: (setting a breakpoint at line 
10 of a C program) 


6.3.3 The D Command: display memory contents 
The d command is used to display a hex dump of the contents of memory on the target system. If no 
expressions are specified, one byte is dumped from the address reached by the last d command. If one 
address is specified, 16 bytes are dumped from the address given. If two addresses are specified, the 
contents of memory from the first address to the second address are displayed. Dump addresses given 
can be symbols, line numbers, register names or absolute memory addresses. 


6. 3. 4 The E Command: examine C source code 
The e command is used to examine the C source code of a function or file. If a function name is given, 
Lucifer will locate the source file containing the function requested and display from just above the start 
of the function. If a file name is given, Lucifer will display from line 1 of the requested file. 


: e main 
2: 
3: int value, result; 
4: 
5: main() 
6:{ 
7: scanf("% d",& value); 
8: result = (value << 1) + 6; 
9: printf(" result = %d\\ n", result); 
10:} 
: 


6 


Commands 


Pacific C Compiler 79 
97

Example: (use of e command to list C 
main() function) 


6. 3. 5 The G Command: commence execution 
The g command is used to commence execution of code on the target system. If no expression is supplied 
after the g command, execution will commence from the current value of PC (the program counter). If 
an expression is supplied, execution will commence from the address given. Execution will continue until 
a breakpoint is reached, or the user interrupts with control-C. After a breakpoint has been reached, 
execution can be continued from the same place using the g, s and t commands. 


6.3.6 The I Command: toggle instruction trace mode 
The i command is used to toggle instruction trace mode. If instruction trace mode is enabled, each 
instruction is displayed before it is executed while stepping by entire C lines with the s command. 


Assume PC points to 9: 
printf(" result = %d\\ n", result); 


With instruction trace turned OFF, 
stepping would produce: 


:s 
result = 20 
Stepped to 
10:} 
: 


With instruction trace turned ON, 
stepping would produce: 


: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:} 


6 
Chapter 6 -Lucifer -A Source Level Debugger 


80 
98

: 
Note: the library function printf() was 
not traced by the stepping mechanism 
and thus functioned correctly. 


Example: (showing effect of i command on 
step display) 


6.3.7 The Q Command: exit to DOS 
The q command is used to exit from Lucifer to DOS. 


6. 3. 8 The R Command: remove breakpoints 
The r command is used to remove breakpoints which have been set with the b command. For each 
breakpoint, the user is prompted as to whether the breakpoint should be removed or not. 


:r 
Remove _main+ 27 "tst. c" line 10 ? y 
Remove _main+ 44 "tst. c" line 13 ? n 
Remove _test "tst. c" line 22 ? n 
: 


Example: (removes breakpoint at main+ 27) 


6.3.9 The S Command: step one C line 
The s command is used to step by one line of C source code. This is normally implemented by executing 
several machine instruction single steps, and therefore can be quite slow. If Lucifer can determine that 
there are no function calls or control structures (break, continue, etc.) in the line, it will set a temporary 
breakpoint on the next line and execute the line at full speed. 


When single stepping by machine instructions, the step command will execute subroutine calls to external 
and library functions at full speed, thereby avoiding the slow process of single stepping through complex 
library routines such as printf() or scanf(). Normal library console I/ O works correctly during single 
stepping. 


Assume current PC points to line 6: 
{ 


:s 


6 
Commands 


Pacific C Compiler 81 
99

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:} 
: 


Example: (stepping through several 
lines of C code) 


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 Clines 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); 


6 
Chapter 6 -Lucifer -A Source Level Debugger 


82 
100

_main+ 28 PUSH _answer 
_main+ 2C MOV DX,# 0074 
_main+ 2F PUSH DX 
_main+ 30 CALL _printf 
_main+ 33 ADD SP,# 04, WORD 
12: exit( answer << 1); 
_main+ 36 MOV DX,_ answer 
_main+ 3A SHL DX,# 1 
_main+ 3C CALL _exit 
: 


Example: (disassembly from line 10 of 
a C program) 


6.3.12 The X Command: examine or change registers 
The x command is used to examine and change the contents of the target CPU registers. If no parameters 
are given, the registers are displayed without change. To change the contents of a register, two parameters 
must be supplied, a valid register name and the new value of the register. After setting a new register 
value, the contents of the registers are displayed. 


Any valid 8086 register name may be used. pc and ip are both accepted for the program counter. psw 
and flags are both accepted for the flags register. The low and high bytes of the general purpose registers 
may be accessed with al, ah, bl, bh, etc. 


6.3.13 The @ Command: display memory as a C type 
The @ command is used to examine the contents of memory interpreted as one of the standard C types. 
The form of the @ command is: 


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 


6 
Commands 


Pacific C Compiler 83 
101

l long u = unsigned, x = hex, o = octal 
p pointer f = far pointer 
s string none 


Examples: 


To display a long variable "longvar" in hex: 
@lx longvar 
To display a character, pointed at by a far pointer "cptr": 
@c f* cptr 
To de-reference "ihandle": a pointer to a pointer to an unsigned 
int: 


@iu ** ihandle 


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. 


Assume execution was stopped by a breakpoint 
in f2() 


:^ 
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() 
: 


6 
Chapter 6 -Lucifer -A Source Level Debugger 


84 
102

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 
4: 
5: main() 
6: { 
7: scanf("% d",& value); 
8: result = (value << 1) + 6; 
9: printf(" result = %d\\ n", result); 
10:} 


6.3.18 The = Command: display next page of source 
The = Command is used to display the next 10 lines of source code from the current file. For example, 
if the last source line displayed was line 7, = will display 10 lines starting from line 8. 


6.3.19 The -Command: display previous page of source 
The -Command is used to display the previous 10 lines of source code from the current file. For example, 
if the last page displayed started at line 15, -will display 10 lines starting from line 5. 


6 


Commands 


Pacific C Compiler 85 
103

6.3.20 The / Command: search source file for a string 
The / command is used to search the current source file for occurences of a sequence of characters. Any 
text typed after the / is used to search the source file. The first source line containing the string specified 
is displayed. If no text is typed after the /, the previous search string will be used. Each string search 
starts from the point where the previous one finished, allowing the user to step through a source file 
finding all occurences of a string. 


: /printf 
10: printf(" Enter a number:"); 
:/ 
14: printf(" Result = %d\\ n", answer); 
:/ 
Can't find printf 
: 


Example: (use of / command to find all 
uses of printf() ) 


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. 


6 


Chapter 6 -Lucifer -A Source Level Debugger 


86 
104

Chapter 7 
ROM Development with 
Pacific C 


7.1 Requirements for ROM Development 
ROM development differs from generating executable files for MS-DOS, as discussed in the rest of this 
manual. To produce embedded code in ROM from Pacific C, you will need to have purchased either the 
Pacific C ROMDEV package or addon, or have obtained the Pacific CSpecial Edition -the Special Edtion 
is available only through educational institutions. If you have only the standard Pacific C package, you 
can obtain the ROMDEV addon from HI-TECH Software or your reseller. 


Once you have the appropriate software, you will need two pieces of hardware, apart from your PC. You 
will need a target system for development. This will usually consist of an evaluation board, or some other 
stand-alone circuit board with an 8086 family processor (e. g. an 80C188EB) and at least a ROM socket. 
The board will normally also have a RAM socket, and in order to use the remote debugger you will also 
need a serial port that can be connected to a serial port on your PC. The 80C188EB has two on-board 
serial ports which are suitable for this purpose. 


The remainder of this chapter will concentrate mainly on using the 80C188EB, as it is a very popular 
embedded variant of the 8086 family, however the techniques discussed are equally applicable to other 
processors, but may require additional work on your part to customize run-time startups and other 
components of the run-time environment. The exact nature of these changes will depend on the particular 
hardware. 


The other piece of equipment you will need is an EPROM programmer (or EPROM emulator). This is 
used to transfer your compiled program into non-volatile memory for execution in your target system. 
Most EPROM programmers include a software program that runs under DOS and will read a HEX or 
binary file and program it into the EPROM. The EPROM is then plugged into your target system where 
it will be executed. 


7.2 ROM Code vs. DOS .EXE Files 
When generating DOS programs, the Pacific C compiler will take your source code, in one or more C 
files, and translate it to 8086 machine code. This is then linked with an appropriate set of library routines, 
and converted into a DOS .EXE (dot-eksi) file that can be run under DOS. The libraries used for DOS 
programs make calls to DOS system functions (e. g. via int #21h) to perform all I/ O and many other 
functions. 


7 


Pacific C Compiler 88 
105

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 HEXfile 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. 


7.3 What You Need to Know 
In order to develop an embedded program, you need some information that you would normally not need 
to generate a DOS program. You will need to know: 


q The memory organization of your target system; 


q The initialization sequence required for your target system; 
q I/ O port definitions and functions 
q The steps required to program an EPROM for your target, or some other means of getting the 
compiled code into your target. 


The memory organization of your system means the starting address and size of your RAM and ROM. 
The ROM is used to hold the program, and the RAM is used for run-time storage of variables and stack. 
A typical 8086 based system will have ROM at high memory addresses, and RAM at low memory 
addresses, starting usually from zero. This is because the 8086 begins program execution after reset at a 
high memory address, usually FFFF0 hex -i. e. 16 bytes below the top of the 1Mbyte addressable memory 
range. Low memory holds interrupt vectors, which are best placed in RAMas they may need to be changed 
at run-time. The actual reset address is another piece of information you will need, but for any of the 
8086, 8088, 80186 and 80188 processors this will be FFFF0. 


7 


Chapter 7 -ROM Development with Pacific C 


89 
106

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 
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 ROMimplementing 
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. 


7 


What You Need to Know 


Pacific C Compiler 90 
107

7.4 First Steps 
Before attempting to generate code for an embedded system, it will be useful for you to familiarize 
yourself with the Pacific C compiler in general, and PPD in particular. Compile and run some of the 
programs in the EXAMPLES directory, then create one or two of your own programs and compile and 
run them under DOS. This will ensure that you are comfortable using PPD before following the 
procedures below. 


When compiling a first C program, it has been traditional to use a "Hello, world" program that does 
nothing but print a string. In an embedded system this seemingly simple task is quite an achievement -it 
requires not only that a program should start correctly, but that the serial port driver is correct, right down 
to the correct baud rate setting for the system crystal frequency. Then you must have the serial port wired 
correctly and connected to a terminal or terminal program. All of this is difficult to guarantee in one step. 


Accordingly, we present here some rather more basic code suitable for a first embedded program. This 
piece of code simply turns an I/ O port pin on and off, so that if a LED is connected to the I/ O port pin, 
or even a CRO, it will produce a visible signal that the program is running correctly. 


#include <80c188eb. h> 
/* 
* Demo program for the 80C188EB. This program 
* flashes a LED attached to bit 3 of port 1. 
*/ 


main() 
{ 
int i; 


_P1CON &= ~0x8; /* set bit 3 to output */ 
for(;;) { 
for( i = 0 ; i != 0x7fff ; i++) 
continue; 
_P1LTCH ^= 0x8; /* toggle the bit */ 
} 
} 


Figure 7-1 -The Hello Led Program 


7 


Chapter 7 -ROM Development with Pacific C 


91 
108

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 ROMcode with the mouse, or press Mand then press Enter or click 
the OK button. 


7.4.2 Selecting Processor Type 
The next dialog presented will allow you to select the memory model, which for now we will leave at 
the default of Small, and the processor type. The choices are 8086 or 8088 (the default) and 80186, 80188 
or 80286. Select the appropriate choice for your particular hardware. If you select 80188 code you will 
now see become visible another check box, marked 80C188EB specific powerup. Checking this option 
will enable standard powerup initialisation code for the 80C188EB to be linked in, as discussed earlier. 


Figure 7-2 -Select DOS or ROM code 


7 


First Steps 


Pacific C Compiler 92 
109

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. 


Figure 7-3-Select Processor Type 


Figure 7-4-Selecting the ROM file type 
7 


Chapter 7 -ROM Development with Pacific C 


93 
110

7. 4. 3 Choosing the File Type 
The dialog shown in figure -allows you to choose the type of output file you would like. This will be 
determined by the requirements of you EPROM programmer or other hardware that you will be using to 
get your code into your target system. If you will be using the Lucifer debugger, you should leave the 
default of Intel HEX. After choosing the type, press Enter to accept the selection. 


7. 4. 4 Setting Memory Addresses 
As discussed previously, you need to know the address and size of the ROM and RAM available in your 
system. The default values shown in figure -represent a 32Kbyte ROM (e. g. a 27256) located at the top 
of the memory space, and a 32K RAM( e. g. a 62256) located at zero. Note that it is not necessary to exactly 
match the actual sizes for the program to work; for example a 64K byte ROM would still work with this 
setup, but only the top half would be accessible, and when programming it the code would have to be 
programmed at offset 8000h. Note also that the addresses are given in bytes, not paragraphs, but in general 
will always be multiples of 16 since all memory addressing in the 8086 family is done in increments of 
16 bytes. Your EPROM programmer may require you to enter a segment address when you load the hex 
file -in this case the segment address would be F800 since the physical address of the start of the ROM 
is F8000. 


The RAM address is given as 100h, even though it probably actually starts at 0. This is to leave the 
interrupt vectors in the bottom 256 bytes of memory alone. The RAM size then becomes 7F00, since this 
represents the number of bytes available from the starting address given. The RAM starting address will 
be used to set the location for storage of variables; the RAM size plus RAM address will give the initial 
stack pointer, i. e. at the top of the available RAM. 


The non-volatile RAM address is unimportant for this program since we will not be using any persistent 
variables. If you do use non-volatile RAM, you should enter here the address of the battery backed RAM. 
It must not overlap the other RAM area, so that if all RAM is battery backed, you might choose to set 
non-volatile RAM at 100, and the normal RAM at 200 with a size of 7E00. 


Figure 7-5-Memory Addresses 
7 


First Steps 


Pacific C Compiler 94 
111

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. 


7.4.6 Entering Source Files 
After the Optimisation dialog, you will be presented with the Source File List. This allows you to enter 
the names of the source files you wish to include in this project. Since the list is initially empty, the name 
of the currently loaded editor file will be included automatically. For this demonstration this is all you 
need, but if you wish to enter further files, just press Enter to go to a new line, and type the name of 
another source file. The file does not have to exist at this point in time. Enter each file on a separate line, 
and include the .C filetype (or .AS for an assembler source file). 


Figure 7-6-Source File List 
7 


Chapter 7 -ROM Development with Pacific C 


95 
112

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. 


7.4.8 Running the Code 
Now that you have a HEX file or binary file, you need to get it into your target system. Run your EPROM 
programmer or other utility to place the compiled program into your EPROM. You can use the 
user-defined commands in the Utility menu as a convenient way of invoking an EPROM programmer. 
After the EPROM is programmed, plug it into your system, and power it up. The led should flash! 


Figure 7-7-Compilation Successful Report 


7 


First Steps 


Pacific C Compiler 96 
113

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! 


7.5 Going Further 
Congratulations! You have compiled and run a program in an embedded system. Having achieved this 
you have taken the most difficult step. Let's move on now to a more complex program. Run PPD and 
open the file luctest. c. Now select Make/ New project and set memory addresses etc. just as before. At 
the source file list, you will have luctest. c entered automatically. Press Enter to step to a new line and 
type serial. c, then ESC to exit the list This program is a test for the serial port. The module serial. c 
contains a simple driver for the 80C188EB serial port, which is called by the code in luctest. c. If you 
need a custom powerup routine, add it to the source file list also. If your 80C188EB is not using a 40MHz 
crystal, edit serial. c appropriately. If you are not using an 80C188EB, you will need to modify serial. c 
to driver whatever serial port you do have. 


Now make the program with F5 or Make/ Make. Program into an EPROM and run it, with a dumb 
terminal or terminal program on your PC connected to the serial port You should see a pattern of characters 
displayed, followed by a prompt. Type one line of text at the prompt and press Enter, and the characters 
will be echoed back as hex bytes. 


If this is successful, you have a working serial port, and can move onto implementing Lucifer in your 
board, to enable you to download and debug programs without burning EPROMS. 


7.6 Implementing Lucifer 
Included in the LUCIFER directory are two target monitors for Lucifer; one is for the 80C188EB, and 
the other is for a generic 8086 type processor with a Zilog SCC serial port. If your target board does not 
use either of these configurations you will need to generate your own target program, using one of these 
as a starting point. If using the 8086/ SCC target program (TARGET86. C) you will probably still need to 
edit it to set port addresses, baud rate etc. 


7 


Chapter 7 -ROM Development with Pacific C 


97 
114

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. 


7.7 Debugging with Lucifer 
There is a separate chapter that details the commands to Lucifer, and these will not be repeated here. 
On-line help is also available from within Lucifer. When compiling a user program for use with Lucifer, 
you should choose ROM and RAM addresses that lie within the RAM available in your system. For 
example, if you had 64K bytes of RAM from location zero, Lucifer would normally use the top 100h 
bytes, and addresses below 400h should be reserved for interrupts, so addresses from 400h to FF00 are 
available. A good strategy is to set the RAM address to 400h, and RAM size to a value you know is big 
enough for your program's data and stack (400h as a size is good for most small programs). Then set the 
ROM address to the sum of the RAM size and address, e. g. 800h. The code will extend up from there 
towards the top of RAM. Check a link map or the psect map provided after compilation to ensure that 
the code does not overlap the Lucifer RAM area at the top. 


After debugging your program, you need only relink it with different addresses to put it into ROM. Have 
fun! 


7 


Debugging with Lucifer 


Pacific C Compiler 98 
115

7 
Chapter 7 -ROM Development with Pacific C 


99 
116

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. 


8.2 Relocation and Psects 
The fundamental task of the linker is to combine several relocatable object files into one. The object files 
are said to be relocatable since the files have sufficient information in them so that any references to 
program or data addresses (e. g. the address of a function) within the file may be adjusted according to 
where the file is ultimately located in memory after the linkage process. Thus the file is said to be 
relocatable. Relocation may take two basic forms; relocation by name, i. e. relocation by the ultimate 
value of a global symbol, or relocation by psect, i. e. relocation by the base address of a particular section 
of code, for example the section of code containing the actual excutable instructions. 


8 


Introduction 


Pacific C Compiler 100 
117

8.3 Program Sections 
Any object file may contain bytes to be stored in memory in one or more program sections, which will 
be referred to as psects. These psects represent logical groupings of certain types of code bytes in the 
program. In general the compiler will produce code in three basic types of psects, although there will be 
several different types of each. The three basic kinds are text psects, containing executable code, data 
psects, containing initialized data, and bss psects, containing uninitialized but reserved data. 


The difference between the data and bss psects may be illustrated by considering two external variables; 
one is initialized to the value 1, and the other is not initialized. The first will be placed into the data psect, 
and the second in the bss psect. The bss psect is always cleared to zeros on startup of the program, thus 
the second variable will be initialized at run time to zero. The first will however occupy space in the 
program file, and will maintain its initialized value of 1 at startup. It is quite possible to modify the value 
of a variable in the data psect during execution, however it is better practice not to do so, since this leads 
to more consistent use of variables, and allows for restartable and romable programs. 


For more information on the particular psects used in a specific compiler, refer to the appropriate 
machine-specific chapter. 


8.4 Local Psects 
Most psects are global, i. e. they are referred to by the same name in all modules, and any reference in 
any module to a global psect will refer to the same psect as any other reference. Some psects are local, 
which means that they are local to only one module, and will be considered as separate from any other 
psect even of the same name in another module. Local psects can only be referred to at link time by a 
class name, which is a name associated with one or more psects via a CLASS= directive in assembler 
code. 


8.5 Global Symbols 
The linker handles only symbols which have been declared as global to the assembler. From the C source 
level, this means all names which have storage class external and which are not declared as static. These 
symbols may be referred to by modules other than the one in which they are defined. It is the linker's job 
to match up the definition of a global symbol with the references to it. Other symbols (local symbols) are 
passed through the linker to the symbol file, but are not otherwise processed by the linker. 


8.6 Link and load addresses 
The linker deals with two kinds of addresses; link and load addresses. Generally speaking the link address 
of a psect is the address by which it will be accessed at run time. The load address, which may or may 
not be the same as the link address, is the address at which the psect will start within the output file (hex 


8 


Chapter 8 -Linker Reference Manual 


101 
118

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: 


HLINK 1 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.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 


8 


Operation 


Pacific C Compiler 102 
1 In earlier versions of Pacific C the linker was called LINK. EXE 
119

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. 


Option Effect 
-8 Use 8086 style segment: offset address form 
-A psect= low-high,... Specify address ranges for a psect 
-C psect= class Specify a class name for a global psect 
-C baseaddr Produce binary output file based at baseaddr 
-D symfile Produce old-style symbol file 
-F Produce .OBJ file with only symbol records 
-G spec Specify calculation for segment selectors 
-H symfile 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 
-M mapfile Generate a link map in the named file 
-O outfile Specify name of output file 
-P spec Specify psect addresses and ordering 
-S psect= max Specify maximum address for a psect 
-U symbol Pre-enter symbol in table as undefined 
-V avmap Use file avmapto generate an Avocet format symbol file 
-W warnlev Set warning level (-10 to 10) 
-W width Set map file width (> 10) 
-X Remove any local symbols from the symbol file 
-Z Remove trivial local symbols from symbol file 


Table 8-1; Linker options 
8 


Chapter 8 -Linker Reference Manual 


103 
120

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 
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 


Operation 


Pacific C Compiler 104 
121

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 SEGMENTSsection summarizes major memory groupings. This will typically show RAMand 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.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: 


-P psect= lnkaddr/ ldaddr, psect= lnkaddr/ ldaddr,... 


8 


Chapter 8 -Linker Reference Manual 


105 
122

Linker command line: 
-z -Mmap -pvectors= 00h, text, strings, const, im2vecs -pbaseram= 00h \ 
-pramstart= 08000h, data/ im2vecs, bss/., stack= 09000h -pnvram= bss, heap \ 
-oC:\ TEMP\ l. obj C:\ HT-Z80\ LIB\ rtz80-s. obj hello. obj \ 
C:\ HT-Z80\ LIB\ z80-sc. lib 


Object code version is 2. 4 
Machine type is Z80 


Name Link Load Length Selector 
C:\ HT-Z80\ LIB\ rtz80-s. obj 
vectors 0 0 71 
bss 8000 8000 24 
const FB FB 1 0 
text 72 72 82 
hello. obj text F4 F4 7 


C:\ HT-Z80\ LIB\ z80-sc. lib 
powerup. obj vectors 71 71 1 


TOTAL Name Link Load Length 
CLASS CODE 
vectors 0 0 72 
const FB FB 1 
text 72 72 89 


CLASS DATA 
bss 8000 8000 24 


SEGMENTS Name Load Length Top Selector 
vectors 000000 0000FC 0000FC 0 
bss 008000 000024 008024 8000 


Figure 8-1; Example map file 
8 


Operation 


Pacific C Compiler 106 
123

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 
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. 


8 


Chapter 8 -Linker Reference Manual 


107 
124

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.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. 


8.8 Invoking the Linker 
The linker is called HLINK, and normally resides in the BIN subdirectory of the compiler installation 
directory. It may be invoked with no arguments, in which case it will prompt for input from standard 
input. If the standard input is a file, no prompts will be printed. This manner of invocation is generally 
useful if the number of arguments to LINK is large. Even if the list of files is too long to fit on one line, 


8 


Invoking the Linker 


Pacific C Compiler 108 
125

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 


8 


Chapter 8 -Linker Reference Manual 


109 
126

Chapter 9 
Librarian Reference Manual 
9.1 Introduction 
Pacific Cincorporates a librarian, to permit the building and maintaining of object code libraries. Alibrary 
is a file comprising several object modules. Combining them into one file offers several advantages: 


q Fewer files to link; the linker command line can be shortened considerably by using a few libraries 
rather than several object files. 


q Faster linking; because there are fewer files to open, and because the linker reads a directory at the 
beginning of the library, it will link faster from a library than from multiple object files. 


q Saving of disk space; combining object files into a library will reduce disk space because of the 
granular nature of filesystem allocation. 


q Conditional linking; when linking from a library, the linker will link only those modules that define 
currently undefined but referenced symbols. If separate object files are specified, they will be linked 
unconditionally. 


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 
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. 


9 


Pacific C Compiler 109 
127

9.2.2 Updating a library 
The r command is also used when replacing or appending modules to a library. If a listed module already 
exists in the library, it will be replaced with the new object module, but will retain its position in the 
library. Any listed object files that do not already exist in the library will be appended to it. These will 
always appear after any existing modules in the library. Once the library is created, the only way to change 
the ordering is to delete the module and append it to the end. 


9. 2. 3 Deleting library modules 
To delete a module from a library, use the d command, e. g. 


LIBR d test. lib file2.obj 
This will delete module file2. obj from the library. 


9.2.4 Extracting a module 
Although the main use of libraries is to allow the linker to use them, it is sometimes required to extract 
a module from a library to an object file. The x command will extract modules. If any object modules are 
listed, they will be extracted. If no object modules are listed, the entire contents of the library will be 
extracted into invidivual object modules. This can be useful if you want to re-order a library. You can 
extract all modules and re-create the library with a specified ordering. 


9.2.5 Listing a library 
The m command will list the contents of a library by module name. If any object files are listed on the 
command line, only those modules will be included in the listing, otherwise the entire contents will be 
listed. 


The s command will list all global symbols, defined and referenced, in either specified modules, or all 
modules if none are specified. In the symbol listing, a letter D will indicate that the symbol is defined in 
that module, while a letter U will indicate that it is undefined (referenced only) in that module. 


9.3 Library ordering 
Earlier versions of the linker would search a library only once, and thus the ordering of modules within 
the library was important, since if a module in the library referenced another earlier in the same library, 
the earlier module would not be linked. The current linker version corrects this problem by searching 
each library encountered repeatedly until no more references can be satisfied from that library. This means 
that the library ordering is not critical. However, a very badly ordered library can result in additional link 
time, and the linker will warn about a badly ordered library. In practice it is unlikely that a randomly 
ordered library will trigger this warning. 


9 


Chapter 9 -Librarian Reference Manual 


110 
128

9.4 Creating libraries from PPD 
It is possible to create a library using PPD. See the PPD manual for more details. 


9 


Creating libraries from PPD 


Pacific C Compiler 111 
129

9 
Chapter 9 -Librarian Reference Manual 


112 
130

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 
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. 


A 


Pacific C Compiler 113 
131

#if sizeof() error, no type specified 
Sizeof() was used in a preprocessor #if expression, but no type was specified. The argument to sizeof() 
in a preprocessor expression must be a valid simple type, or pointer to a simple type. 
#if sizeof, unknown type * 
An unknown type was used in a preprocessor sizeof(). The preprocessor can only evaluate sizeof() 
with basic types, or pointers to basic types. 
#if value stack overflow 
The preprocessor filled up its expression evaluation stack in a #if expression. Simplify the expression 
-it probably contains too many parenthesized subexpressions. 
#if, #ifdef, or #ifndef without an argument 
The preprocessor directives #if, #ifdef and #ifndef must have an argument. The argument to #if should 
be an expression, while the argument to #ifdef or #ifndef should be a single name. 
#include syntax error 
The syntax of the filename argument to #include is invalid. The argument to #include must be a valid 
file name, either enclosed in double quotes ("") or angle brackets (<>). For example: #include" afile. h" 
#include< otherfile. h> Spaces should not be included, and the closing quote or bracket must be present. 
There should be nothing else on the line. 
'. ' expected after '.. ' 
The only context in which two successive dots may appear is as part of the ellipsis symbol, which 
must have 3 dots. 
'case' not in switch 
A case statement has been encountered but there is no enclosing switch statement. A case statement 
may only appear inside the body of a switch statement. 
'default' not in switch 
A label has been encountered called "default" but it is not enclosed by a switch statement. The label 
"default" is only legal inside the body of a switch statement. 
( expected 
An opening parenthesis was expected here. This must be the first token after a while, for, if, do or 
asm keyword. 
) expected 
A closing parenthesis was expected here. This may indicate you have left out a parenthesis in an 
expression, or you have some other syntax error. 
, expected 
A comma was expected here. This probably means you have left out the comma between two 
identifiers in a declaration list. It may also mean that the immediately preceding type name is 
misspelled, and has thus been interpreted as an identifier. 
-s, too few values specified in * 
The list of values to the preprocessor -S option is incomplete. This should not happen if the 
preprocessor is being invoked by the compiler driver or HPD. 


A 


Appendix A -Error Messages 


114 
132

-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. 
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. 


A 


Pacific C Compiler 115 
133

array dimension redeclared 
An array dimension has been declared as a different non-zero value from its previous declaration. It 
is acceptable to redeclare the size of an array that was previously declared with a zero dimension, but 
not otherwise. 
array index out of bounds 
An array is being indexed with a constant value that is less than zero, or greater than or equal to the 
number of elements in the array. 
assertion 
An internal error has occured in the compiler. Contact HI-TECH technical support. 
assertion failed: * 
This is an internal error. Contact HI-TECH Software technical support. 
attempt to modify const object 
Objects declared "const" may not be assigned to or modified in any other way.. 
auto variable * should not be qualified 
An auto variable should not have qualifiers such as "near" or "far" associated with it. Its storage class 
is implicitly defined by the stack organization. 
bad #if ... defined() syntax 
The defined() pseudo-function in a preprocessor expression requires its argument to be a single name. 
The name must start with a letter. It should be enclosed in parentheses. 
bad '-p' format 
The "-P" option given to the linker is malformed. 
bad -a spec: * 
The format of a -A specification, giving address ranges to the linker, is invalid. The correct format 
is: 


-Aclass= low-high 
where class is the name of a psect class, and low and high are hex numbers. 
bad -m option: * 
The code generator has been passed a -M option that it does not understand. This should not happen 
if it is being invoked by a standard compiler driver. 
bad -q option * 
The first pass of the compiler has been invoked with a -Q option, to specify a type qualifier name, 
that is badly formed. 
bad arg * to tysize 
This is an internal error that should not happen. If this occurs, re-install the compiler from the original 
distribution disks, as it could represent a corrupted executable file. 
bad arg to im 
The opcode "IM" only takes the constants 0, 1 or 2 as an argument. 


A 


Appendix A -Error Messages 


116 
134

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 addressin-aspec 
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. 


A 


Pacific C Compiler 117 
135

bad low address in -a spec 
The low 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 mod '+ ' for how = * 
Internal error -Contact HI-TECH. 
bad non-zero node in call graph 
The linker has encountered a top level node in the call graph that is referenced from lower down in 
the call graph. This probably means the program has indirect recursion, which is not allowed when 
using a compiled stack. 
bad object code format 
The object code format of this object file is invalid. This probably means it is either truncated, 
corrupted, or not a HI-TECH object file. 
bad op * to revlog 
This is an internal code generator error. Contact HI-TECH technical support with full details of the 
code that caused this error. 
bad op * to swaplog 
This is an internal code generator error. Contact HI-TECH technical support with full details of the 
code that caused this error. 
bad op: * 
This is caused by an error in the intermediate code file. You may have run out of disk (or RAMdisk) 
space for temporary files. 
bad operand 
This operand is invalid. Check the syntax. 
bad origin format in spec 
The origin format in a -p option is not a validly formed decimal, octal or hex number. A hex number 
must have a trailing H. 
bad pragma * 
The code generator has been passed a "pragma" directive that it does not understand. 
bad record type * 
This indicates that the object file is not a valid HI-TECH object file. 
bad relocation type 
This is an internal assembler error. Contact HI-TECH technical support with full details of the code 
that caused this error. is 
bad ret_ mask 
This is an internal code generator error. Contact HI-TECH technical support with full details of the 
code that caused this error. 
bad segment fixups 
This is an obscure message from objtohex that is not likely to occur in practice. 


A 


Appendix A -Error Messages 


118 
136

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. Ahex 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 
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 


A 


Pacific C Compiler 119 
137

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. 
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. 


A 


Appendix A -Error Messages 


120 
138

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 
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. 


A 


Pacific C Compiler 121 
139

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'tuse a string in an #if 
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. 


A 


Appendix A -Error Messages 


122 
140

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 
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. 


A 


Pacific C Compiler 123 
141

constant relational expression 
There is a relational expression that will always be true or false. This may be because e. g. you are 
comparing an unsigned number with a negative value, or comparing a variable with a value greater 
than the largest number it can represent. 
control line * within macro expansion 
A preprocessor control line (one starting with a #) has been encountered while expanding a macro. 
This should not happen. 
declaration of * hides outer declaration 
An object has been declared that has the same name as an outer declaration (i. e. one outside and 
preceding the current function or block). This is legal, but can lead to accidental use of one variable 
when the outer one was intended. 
declarator too complex 
This declarator is too complex for the compiler to handle. Examine the declaration and find a way to 
simplify it. If the compiler finds it too complex, so will anybody maintaining the code. 
def[ bmsf] in text psect 
The assembler file supplied to the optimizer is invalid. 
default case redefined 
There is only allowed to be one "default" label in a switch statement. You have more than one. 
deff not supported in cp/ m version 
The CP/ M hosted assembler does not support floating point. 
degenerate signed comparison 
There is a comparision of a signed value with the most negative value possible for this type, such that 
the comparision will always be true or false. E. g. 


char c; 
if( c >= -128) 
will always be true, because an 8 bit signed char has a maximum negative value of -128. 
degenerate unsigned comparison 
There is a comparision of an unsigned value with zero, which will always be true or false. E. g. 


unsigned char c; 
if( c >= 0) 
will always be true, because an unsigned value can never be less than zero. 
digit out of range 
A digit in this number is out of range of the radix for the number, e. g. using the digit 8 in an octal 
number, or hex digits A-F in a decimal number. An octal number is denoted by the digit string 
commencing with a zero, while a hex number starts with "0X" or "0x". 


A 


Appendix A -Error Messages 


124 
142

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. 
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. 


A 


Pacific C Compiler 125 
143

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 
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. 


A 


Appendix A -Error Messages 


126 
144

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. 
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. 


A 


Pacific C Compiler 127 
145

floating exponent too large 
The exponent of the floating point number is too large. For the Z80 the largest floating point exponent 
is decimal 19. 
floating number expected 
The arguments to the "DEFF" pseudo-op must be valid floating point numbers. 
formal parameter expected after # 
The stringization operator # (not to be confused with the leading # used for preprocessor control lines) 
must be followed by a formal macro parameter. If you need to stringize a token, you will need to 
define a special macro to do it, e. g. 


#define __ mkstr__( x) #x 
then use __ mkstr__( token) wherever you need to convert a token into a string. 
function * appears in multiple call graphs: rooted at * 
This function can be called from both main line code and interrupt code. Use the reentrant keyword, 
if this compiler supports it, or recode to avoid using local variables or parameters, or duplicate the 
function. 
function * is never called 
This function is never called. This may not represent a problem, but space could be saved by removing 
it. If you believe this function should be called, check your source code. 
function body expected 
Where a function declaration is encountered with K& R style arguments (i. e. argument names but no 
types inside the parentheses) a function body is expected to follow. 
function declared implicit int 
Where the compiler encounters a function call of a function whose name is presently undefined, the 
compiler will automatically declare the function to be of type "int", with unspecified (K& R style) 
parameters. If a definition of the function is subsequently encountered, it is possible that its type and 
arguments will be different from the earlier implicit declaration, causing a compiler error. The solution 
is to ensure that all functions are defined or at least declared before use, preferably with prototyped 
parameters. If it is necessary to make a forward declaration of a function, it should be preceded with 
the keywords "extern" or "static" as appropriate. 
function does not take arguments 
This function has no parameters, but it is called here with one or more arguments. 
function is already 'extern'; can't be 'static' 
This function was already declared extern, possibly through an implicit declaration. It has now been 
redeclared static, but this redeclaration is invalid. If the problem has arisen because of use before 
definition, either move the definition earlier in the file, or place a static forward definition earlier in 
the file, e. g. 


static int fred( void); 


A 


Appendix A -Error Messages 


128 
146

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 
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. 


A 


Pacific C Compiler 129 
147

illegal '# ' directive 
The compiler does not understand the "#" directive. It is probably a misspelling of a pre-processor 
"#" directive. 
illegal -o flag 
This -o flag is illegal. A-o option to the linker must have a filename. There should be no space between 
the filenam and the -o, e. g. 


-ofile. obj 
illegal -p flag 
The -p flag needs stuff after it. This is used for defining psect mapping to the linker. 
illegal character * 
This character is illegal. 
illegal character * decimal) in #if 
The #if expression had an illegal character. Check the line for correct syntax. 
illegal character * in #if 
There is a character in a #if expression that has no business being there. Valid characters are the letters, 
digits and those comprising the acceptable operators. 
illegal conversion 
This expression implies a conversion between imcompatible types, e. g. a conversion of a structure 
type into an integer. 
illegal conversion between pointer types 
A pointer of one type (i. e. pointing to a particular kind of object) has been converted into a pointer 
of a different type. This will usually mean you have used the wrong variable, but if this is genuinely 
what you want to do, use a typecast to inform the compiler that you want the conversion and the 
warning will be suppressed. 
illegal conversion of integer to pointer 
An integer has been assigned to or otherwise converted to a pointer type. This will usually mean you 
have used the wrong variable, but if this is genuinely what you want to do, use a typecast to inform 
the compiler that you want the conversion and the warning will be suppressed. 
illegal conversion of pointer to integer 
A pointer has been assigned to or otherwise converted to a integral type. This will usually mean you 
have used the wrong variable, but if this is genuinely what you want to do, use a typecast to inform 
the compiler that you want the conversion and the warning will be suppressed. 
illegal flag * 
This flag is unrecognized. 
illegal function qualifier( s) 
A qualifier such as "const" or "volatile" has been applied to a function. These qualifiers only make 
sense when used with an lvalue (i. e. an expression denoting memory storage). Perhaps you left out a 
star ("*") indicating that the function should return a pointer to a qualified object. 


A 


Appendix A -Error Messages 


130 
148

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 
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". 


A 


Pacific C Compiler 131 
149

implict signed to unsigned conversion 
A signed number is being assigned or otherwise converted to a larger unsigned type. Under the ANSI 
"value preserving" rules, this will result in the signed value being first sign-extended to a signed 
number the size of the target type, then converted to unsigned (which involves no change in bit 
pattern). Thus an unexpected sign extension can occur. To ensure this does not happen, first convert 
the signed value to an unsigned equivalent, e. g. if you want to assign a signed char to an unsigned int, 
first typecast the char value to "unsigned char". 
inappropriate 'else' 
An "else" keyword has been encountered that cannot be associated with an "if" statement. This may 
mean there is a missing brace or other syntactic error. 
inappropriate break/ continue 
A "break" or "continue" statement has been found that is not enclosed in an appropriate control 
structure. "continue" can only be used inside a "while", "for" or "do while" loop, while "break" can 
only be used inside those loops or a "switch" statement. 
include files nested too deep 
Macro expansions and include file handling have filled up the assembler's internal stack. The 
maximum number of open macros and include files is 30. 
incompatible intermediate code version; should be * 
The intermediate code file produced by P1 is not the correct version for use with this code generator. 
This is either that incompatible versions of one or more compilers have been installed in the same 
directory, or a temporary file error has occured leading to corruption of a temporary file. Check the 
setting of the TEMP environment variable. If it refers to a long path name, change it to something 
shorter. 
incomplete * record body: length = * 
An object file contained a record with an illegal size. This probably means the file is truncated or not 
an object file. 
incomplete record 
The object file passed to objtohex is corrupted. 
incomplete record: * 
An object code record is incomplete. This is probably due to a corrupted or invalid object module. 
Re-compile the source file, watching for out of disk space errors etc. 
incomplete record: type = * length = * 
This indicates that the object file is not a valid HI-TECH object file, or that it has been truncated, 
possibly due to running out of disk or RAMdisk space. 
inconsistent storage class 
A declaration has conflicting storage classes. Only one storage class should appear in a declaration. 
inconsistent type 
Only one basic type may appear in a declaration, thus combinations like "int float" are illegal. 
index offset too large 
An offset on a Z80 indexed addressing form must lie in the range -128 to 127. 


A 


Appendix A -Error Messages 


132 
150

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. 
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. 


A 


Pacific C Compiler 133 
151

line too long 
This line is too long. It will not fit into the compiler's internal buffers. It would require a line over 
1000 characters long to do this, so it would normally only occur as a result of macro expansion. 
local illegal outside macros 
The "LOCAL" directive is only legal inside macros. It defines local labels that will be unique for each 
invocation of the macro. 
local psect '* ' conflicts with global psect of same name 
A local psect may not have the same name as a global psect. 
logical type required 
The expression used as an operand to "if", "while" statements or to boolean operators like ! and && 
must be a scalar integral type. 
long argument required 
A long argument is required for this format specifier. Check the number and order of format specifiers 
and corresponding arguments. 
macro * wasn't defined 
A macro name specified in a -U option to the preprocessor was not initially defined, and thus cannot 
be undefined. 
macro argument after % must be absolute 
The argument after % in a macro call must be absolute, as it must be evaluated at macro call time. 
macro argument may not appear after local 
The list of labels after the directive "LOCAL" may not include any of the formal parameters to the 
macro. 
macro expansions nested too deep 
Macro expansions in the assembler are nested too deep. The limit is 30 macros and include files nested 
at one time. 
macro work area overflow 
The total length of a macro expansion has exceeded the size of an internal table. This table is normally 
8192 bytes long. Thus any macro expansion must not expand into a total of more than 8K bytes. 
member * redefined 
This name of this member of the struct or union has already been used in this struct or union. 
members cannot be functions 
A member of a structure or a union may not be a function. It may be a pointer to a function. The 
correct syntax for a function pointer requires the use of parentheses to bind the star ("*") to the pointer 
name, e. g. "int (* name)();". 
metaregister * can't be used directly 
This is an internal compiler error. Contact HI-TECH Software technical support. 


A 


Appendix A -Error Messages 


134 
152

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 * 
Acolon 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. 
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: 


A 


Pacific C Compiler 135 
153

#pragma inline func_ name 
where func_ name is the name of a function which is to be expanded to inline code. This pragma has no 
effect except on functions specially recognized by the code generator. 
missing name after pragma 'printf_ check' 
The pragma 'printf_ check', which enable printf style format string checking for a function, requires 
a function name, e. g. 


#pragma printf_ check sprintf 
missing number after % in -p option 
The % operator in a -p option (for rounding boundaries) must have a number after it. 
missing number after * in -p option 
The -p option has a missing number after a % sign. 
missing number after pragma 'pack' 
The pragma 'pack' requires a decimal number as argument. For example 


#pragma pack( 1) 
will prevent the compiler aligning structure members onto anything other than one byte boundaries. Use 
this with caution as some processors enforce alignment and will not operate correctly if word fetches are 
made on odd boundaries (e. g. 68000, 8096). 
mod by zero in #if, zero result assumed 
A modulus operation in a #if expression has a zero divisor. The result has been assumed to be zero. 
module has code below file base of * 
This module has code below the address given, but the -C option has been used to specify that a binary 
output file is to be created that is mapped to this address. This would mean code from this module 
would have to be placed before the beginning of the file! Check for missing psect directives in 
assembler files. 
multi-byte constant * isn't portable 
Multi-byte constants are not portable, and in fact will be rejected by later passes of the compiler (this 
error comes from the preprocessor). 
multiple free: * 
This is an internal compiler error. Contact HI-TECH Software technical support. 
multiply defined symbol * 
This symbol has been defined in more than one place in this module. 
near function should be static 
A near function in the bank switched model should be static, as it cannot be called from another 
module. 
nested #asm directive 
It is not legal to nest #asm directives. Check for a missing or misspelt #endasm directive. 


A 


Appendix A -Error Messages 


136 
154

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 
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. 


A 


Pacific C Compiler 137 
155

non-prototyped function declaration: * 
A function has been declared using old-style (K& R) arguments. It is preferable to use prototype 
declarations for all functions. If the function has no arguments, declare it as e. g. "int func( void)". 
non-scalar types can't be converted 
You can't convert a structure, union or array to anything else. You can convert a pointer to one of 
those things, so perhaps you left out an ampersand ("&"). 
non-void function returns no value 
A function that is declared as returning a value has a "return" statement that does not specify a return 
value. 
not a member of the struct/ union * 
This identifier is not a member of the structure or union type with which it used here. 
not a variable identifier: * 
This identifier is not a variable; it may be some other kind of object, e. g. a label. 
not an argument: * 
This identifier that has appeared in a K& R stype argument declarator is not listed inside the 
parentheses after the function name. Check spelling. 
object code version is greater than * 
The object code version of an object module is higher than the highest version the linker is known to 
work with. Check that you are using the correct linker. 
object file is not absolute 
The object file passed to objtohex has relocation items in it. This may indicate it is the wrong object 
file, or that the linker or objtohex have been given invalid options. 
only functions may be qualified interrupt 
The qualifier "interrupt" may not be applied to anything except a function. 
only functions may be void 
A variable may not be "void". Only a function can be "void". 
only lvalues may be assigned to or modified 
Only an lvalue (i. e. an identifier or expression directly denoting addressable storage) can be assigned 
to or otherwise modified. A typecast does not yield an lvalue. To store a value of different type into 
a variable, take the address of the variable, convert it to a pointer to the desired type, then dereference 
that pointer, e. g. "*( int *)& x = 1" is legal whereas "( int) x = 1" is not. 
only modifier l valid with this format 
The only modifier that is legal with this format is l (for long). 
only modifiers h and l valid with this format 
Only modifiers h (short) and l (long) are legal with this printf() format specifier. 
only register storage class allowed 
The only storage class allowed for a function parameter is "register". 
oops! -ve number of nops required! 
An internal error has occured. Contact HI-TECH. 


A 


Appendix A -Error Messages 


138 
156

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 farmemory 
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 nearmemory 
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 
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. 


A 


Pacific C Compiler 139 
157

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 
Apointer 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 
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. 


A 


Appendix A -Error Messages 


140 
158

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 
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. 


A 


Pacific C Compiler 141 
159

record too long 
This indicates that the object file is not a valid HI-TECH object file. 
record too long: * 
An object file contained a record with an illegal size. This probably means the file is corrupted or not 
an object file. 
recursive function calls: 
These functions (or function) call each other recursively. One or more of these functions has statically 
allocated local variables (compiled stack). Either use the reentrant keyword (if supported with this 
compiler) or recode to avoid recursion. 
recursive macro definition of * 
The named macro has been defined in such a manner that expanding it causes a recursive expansion 
of itself! 
redefining macro * 
The macro specified is being redefined, to something different to the original definition. If you want 
to deliberately redefine a macro, use #undef first to remove the original definition. 
redundant & applied to array 
The address operator "&" has been applied to an array. Since using the name of an array gives its 
address anyway, this is unnecessary and has been ignored. 
refc == 0 
Internal error -Contact HI-TECH. 
regused -bad arg to g 
Internal error -Contact HI-TECH. 
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. 
relocation offset * out of range * 
An object file contained a relocation record with a relocation offset outside the range of the preceding 
text record. This means the object file is probably corrupted. 
relocation too complex 
The complex relocation in this expression is too big to be inserted into the object file. 
remsym error 
Internal error. Contact HI-TECH technical support. 
rept argument must be >= 0 
The argument to a "REPT" directive must be greater than zero. 
seek error: * 
The linker could not seek when writing an output file. 
segment * overlaps segment * 
The named segments have overlapping code or data. Check the addresses being assigned by the "-P" 
option. 


A 


Appendix A -Error Messages 


142 
160

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 
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. 


A 


Pacific C Compiler 143 
161

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: * 
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. 
thisis 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". 


A 


Appendix A -Error Messages 


144 
162

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 
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. 


A 


Pacific C Compiler 145 
163

too many include directories 
A maximum of 7 directories may be specified for the preprocessor to search for include files. 
too many initializers 
There are too many initializers for this object. Check the number of initializers against the object 
definition (array or structure). 
too many macro parameters 
There are too many macro parameters on this macro definition. 
too many nested #* statements 
#if, #ifdef etc. blocks may only be nested to a maximum of 32. 
too many nested #if statements 
#if, #ifdef etc. blocks may only be nested to a maximum of 32. 
too many psect class specifications 
There are too many psect class specifications (-C options) 
too many psect pragmas 
Too many "pragma psect" directives have been used. 
too many psects 
There are too many psects! Boy, what a program! 
too many qualifier names 
There are too many qualifier names specified. 
too many relocation items 
Objtohex filled up a table. This program is just way too complex! 
too many segment fixups 
There are too many segment fixups in the object file given to objtohex. 
too many segments 
There are too many segments in the object file given to objtohex. 
too many symbols 
There are too many symbols for the assemblers symbol table. Reduce the number of symbols in your 
program. If it is the linker producing this error, suggest changing some global to local symbols. 
too many symbols in * 
There are too many symbols in the specified function. Reduce the size of the function. 
too many temporary labels 
There are too many temporary labels in this assembler file. The assembler allows a maximum of 2000 
temporary labels. 
too much indirection 
A pointer declaration may only have 16 levels of indirection. 
too much pushback 
This error should not occur, and represents an internal error in the preprocessor. 
type conflict 
The operands of this operator are of incompatible types. 


A 


Appendix A -Error Messages 


146 
164

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. 
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 


A 


Pacific C Compiler 147 
165

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. 
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". 


A 


Appendix A -Error Messages 


148 
166

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: * 
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. 


A 


Pacific C Compiler 149 
167

variable may be used before set: * 
This variable may be used before it has been assigned a value. Since it is an auto variable, this will 
result in it having a random value. 
void function cannot return value 
A void function cannot return a value. Any "return" statement should not be followed by an 
expression. 
while expected 
The keyword "while" is expected at the end of a "do" statement. 
work buffer overflow * 
An internal preprocessor buffer has been filled. This buffer has a size of 4096 bytes. 
write error (out of disk space?) * 
Probably means that the hard disk or RAM disk is full. 
write error on * 
A write error occured on the named file. This probably means you have run out of disk space. 
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. 
wrong number of macro arguments for * -* instead of * 
A macro has been invoked with the wrong number of arguments. 
{ expected 
An opening brace was expected here. 
} expected 
A closing brace was expected here. 


A 


Appendix A -Error Messages 


150 
168

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 
The type and nature of the return value of the function (if any) is given. Information on error returns is 
also included. 


B 


Pacific C Compiler 152 
169

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. 


B 


Appendix B -Library Functions 


153 
170

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> 


/* print acos() values for -1 to 1 in degrees */ 
main() 
{ 
float i, a; 


for( i = -1.0;i <1.0 ;i += 0.1) { 
a = acos( i)* 180.0/ 3.141592; 
printf(" acos(% f) = %f degrees\ n", i, a); 
} 
} 


RETURN VALUE 
An angle in radians, in the range 0 to 2p. 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 


B 


ACOS 


Pacific C Compiler 154 
171

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; 
int tm_ wday; 
int tm_ yday; 
B 


Appendix B -Library Functions 


155 
172

int tm_ isdst; 
}; 


SEE ALSO 
ctime, time, gmtime, localtime, time 


B 


ASCTIME 


Pacific C Compiler 156 
173

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; 


for( i = -1.0;i <1.0 ;i += 0.1) { 
a = asin( i)* 180.0/ 3.141592; 
printf(" asin(% f) = %f degrees\ n", i, a); 
} 
} 


RETURN VALUE 
An angle in radians, in the range -p/ 2 to +p/ 2. Where the argument value is outside the domain -1 to 1, 
the return value will be zero. 


SEE ALSO 
sin, cos, tan 


B 


Appendix B -Library Functions 


157 
174

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); 
} 


B 


ASSERT 


Pacific C Compiler 158 
175

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 p ¤2 to -pi ¤2 such 
that sin(e)şx. 


SEE ALSO 
tan, asin, acos, atan2 


B 


Appendix B -Library Functions 


159 
176

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 */ 


if(!( fp = fopen(( fname = "test. fil"), "w"))) 
exit( 1); 
atexit( rmfile); 
} 


RETURN VALUE 
Atexit() returns zero if the registration succeeds, nonzero if it fails. 
SEE ALSO 
exit 
B 


ATEXIT 


Pacific C Compiler 160 
177

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 


B 


Appendix B -Library Functions 


161 
178

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 


B 


ATOI 


Pacific C Compiler 162 
179

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 


B 


Appendix B -Library Functions 


163 
180

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); 
i++; 
} 
qsort( values, i, sizeof values[ 0], val_ cmp); 


B 


BSEARCH 


Pacific C Compiler 164 
181

vp = bsearch(" fred", values, i, sizeof values[ 0], 
val_ cmp); 
if(! vp) 
printf(" Item 'fred' was not found\ n"); 
else 
printf(" Item 'fred' has value %d\ n", vp-value); 
} 


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 


B 


Appendix B -Library Functions 


165 
182

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 */ 


ptr = calloc( 20, sizeof( struct test)); 
if(! ptr) 
printf(" Failed\ n"); 
else 
free( ptr); 
} 


RETURN VALUE 
A pointer to the block is returned, or 0 if the memory could not be allocated. 
SEE ALSO 
brk, sbrk, malloc, free 


B 


CALLOC 


Pacific C Compiler 166 
183

CEIL SYNOPSIS 
#include <math. h> 
double ceil( double f) 


DESCRIPTION 
This routine returns the smallest whole number not less than f. 


B 


Appendix B -Library Functions 


167 
184

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 


B 


CGETS 


Pacific C Compiler 168 
185

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 


B 


Appendix B -Library Functions 


169 
186

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 


B 


CHDRV 


Pacific C Compiler 170 
187

CHMOD SYNOPSIS 
#include <stat. h> #include <unixio. h> 
int chmod( char * name, int mode) 


DESCRIPTION 
This function changes the file attributes (or modes) of the named file. The argument name may be any 
valid file name. The mode argument may include all bits defined in stat. h except those relating to the 
type of the file, e. g. S_ IFDIR. 


EXAMPLE 
#include <stat. h> 
#include <stdio. h> 
#include <unixio. h> 


/* make a file read-only */ 
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 
stat, creat B 


Appendix B -Library Functions 


171 
188

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> 


/* create an empty file */ 
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 


B 


CLOSE 


Pacific C Compiler 172 
189

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 


B 


Appendix B -Library Functions 


173 
190

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; 


for(i =0 ;i <= 180.0 ;i += 10) 
printf(" sin(% 3.0f) = %f, cos = %f\ n", 
i, sin( i* C), cos( i* C)); 
} 


RETURN VALUE 
A double in the range -1 to +1. 
SEE ALSO 
sin, tan, asin, acos, atan 


B 


COS 


Pacific C Compiler 174 
191

COSH, SINH, TANH SYNOPSIS 
#include <math. h> 
double cosh( double f) 
double sinh( double f) 
double tanh( double f) 


DESCRIPTION 
These functions implement the hyperbolic trig functions. 


B 


Appendix B -Library Functions 


175 
192

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 


B 


CPUTS 


Pacific C Compiler 176 
193

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 


B 


Appendix B -Library Functions 


177 
194

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 


B 


CTIME 


Pacific C Compiler 178 
195

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; 


/* disable interrupts around access 
to count, to ensure consistency */ 


di(); 
val = count; 
ei(); 
return val; 
} B 


Appendix B -Library Functions 


179 
196

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; 


B 


DIV 


Pacific C Compiler 180 
197

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; 
}; 


struct SREGS { 
unsigned int es; 
unsigned int cs; 
unsigned int ss; 


B 


Appendix B -Library Functions 


181 
198

unsigned int ds; 
}; 


SEE ALSO 
int86, int86x, intdos, intdosx 


B 


DRIVER 


Pacific C Compiler 182 
199

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 
-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 


B 


Appendix B -Library Functions 


183 
200

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. 
SEE ALSO 
dup 


B 


DUP2 


Pacific C Compiler 184 
201

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 


B 


Appendix B -Library Functions 


185 
202

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; 


for( f = 0.0 ;f <=5 ;f += 1.0) 
printf(" e to %1.0f = %f\ n", f, exp( f)); 
} 


SEE ALSO 
log, log10, pow 


B 


EXP 


Pacific C Compiler 186 
203

FABS SYNOPSIS 
#include <math. h> 
double fabs( double f) 


DESCRIPTION 
This routine returns the absolute value of its double argument. 
SEE ALSO 
abs 


B 


Appendix B -Library Functions 


187 
204

FARMALLOC, FARFREE, FARREALLOC SYNOPSIS 
#include <stdlib. h> 
far void * farmalloc( size_ t size); 
void farfree( far void * vp); 


DESCRIPTION 
In small and medium models, pointers are by default 16 bit near pointers that refer to the DS register. 
The maximum amount of memory that can be accessed with default pointers is 64K. To allocate more 
memory, the function farmalloc() can be used. It returns a far pointer (32 bits in segment: offset form) to 
memory allocated at the end of the current program's memory. Memory allocated with farmalloc() should 
be freed with farfree() when no longer required. 


Farrealloc() is the far equivalent of realloc(), i. e. it will alter the size of a block, copying it if necessary, 
and returning a pointer to the new block. 


Memory allocated with these routines can not be used where near memory is required, i. e. it cannot be 
used as an argument to a library routine which expects a default pointer. There are however far versions 
of some useful routines in the library. 


The maximum size of a single block that can be allocated with farmalloc() is 64K, since it must lie within 
one segment. 


EXAMPLE 
#include <stdlib. h> 
#include <stdio. h> 
main() 
{ 
far char * x; 
int i; 


for(i =0 ;i != 10 ;i++) { 
if(!( x = farmalloc( 32768))) 
break; 
i++; 
} 
printf(" allocated %ld Kbytes in 32K blocks\ n", i* 32768L); 
} 


NOTE 
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. 


B 


FARMALLOC, FARFREE, FARREALLOC 


Pacific C Compiler 188 
205

SEE ALSO 
farstrcpy, farmemcpy, malloc, free, realloc 


B 


Appendix B -Library Functions 


189 
206

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> 


far char buf[ 80]; 
far char buf2[ 80]; 


main() 
{ 
int i; 


farmemset( buf2, 0x7F, 80); 
for(i =0 ;i != 80 ;i++) 
buf[ i] = i; 
farmemcpy( buf2, buf, 80); 
printf(" buf2[ 10] = %d\ n", buf2[ 10]); 
} 


RETURN VALUE 
The destination buffer pointer is returned. 
SEE ALSO 
farmalloc, memcpy, memset B 


FARMEMCPY, FARMEMSET 


Pacific C Compiler 190 
207

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 


B 


Appendix B -Library Functions 


191 
208

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; 


/* 3 is the device AUX */ 
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 


B 


FDOPEN 


Pacific C Compiler 192 
209

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 


B 


Appendix B -Library Functions 


193 
210

FFIRST, FNEXT SYNOPSIS 
#include <stat. h> 
struct dirbuf * ffirst( char *); 
struct dirbuf * fnext( void); 


DESCRIPTION 
These two functions provide a means of finding DOSfiles 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 */ 
}; 


B 


FFIRST, FNEXT 


Pacific C Compiler 194 
211

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 


B 


Appendix B -Library Functions 


195 
212

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 


B 


FGETC 


Pacific C Compiler 196 
213

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]; 


while( fgets( buffer, sizeof buffer, stdin)) 
fputs( buffer, stdout); 
} 


RETURN VALUE 
A successful fgets() will return its first argument; NULL is returned on end-of-file or error. 


B 


Appendix B -Library Functions 


197 
214

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 


FILENO 


Pacific C Compiler 198 
215

FLOOR SYNOPSIS 
#include <math. h> 
double floor( double f) 


DESCRIPTION 
This routine returns the largest whole number not greater than f. 


B 


Appendix B -Library Functions 


199 
216

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 


FOPEN 


Pacific C Compiler 200 
217

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 


B 


Appendix B -Library Functions 


201 
218

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 


B 


FPRINTF 


Pacific C Compiler 202 
219

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 


B 


Appendix B -Library Functions 


203 
220

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 


B 


FPUTC 


Pacific C Compiler 204 
221

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 


B 


Appendix B -Library Functions 


205 
222

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; 


i = fread( buf, 1, sizeof( buf), stdin); 
printf(" Read %d bytes\ n", 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 


B 


FREAD 


Pacific C Compiler 206 
223

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 */ 


ptr = calloc( 20, sizeof( struct test)); 
if(! ptr) 
printf(" Failed\ n"); 
else 
free( ptr); 
} 


SEE ALSO 
malloc, calloc 


B 


Appendix B -Library Functions 


207 
224

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]; 


if(! freopen(" test. fil", "r", stdin)) 
perror(" test. fil"); 
if( gets( buf)) 
puts( buf); 
} 


RETURN VALUE 
It either returns the stream argument, if successful, or NULL if not. See fopen() for more information. 
SEE ALSO 
fopen, fclose 


B 


FREOPEN 


Pacific C Compiler 208 
225

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. Iffis 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 


B 


Appendix B -Library Functions 


209 
226

FSCANF SYNOPSIS 
#include <stdio. h> 
int fscanf( FILE * stream, char * fmt, ...) 


DESCRIPTION 
This routine performs formatted input from the specified stream. Seescanf() for a full description of the 
behaviour of the routine. 


EXAMPLE 
#include <stdio. h> 


main() 
{ 
int i; 


printf(" Enter a number: "); 
fscanf( stdin, "% d", &i); 
printf(" Read %d\ n", 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 


B 


FSCANF 


Pacific C Compiler 210 
227

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; 


/* open file for read/ write */ 
fp = fopen(" test. fil", "r+"); 
if(! fp) 
exit( 1); 
fseek( fp, 0L, 2); /* seek to end */ 
fputs(" Another line!\ n", fp); 
fclose( fp); 
} 


RETURN VALUE 
EOF is returned if the positioning request could not be satisfied, otherwise zero. 


B 


Appendix B -Library Functions 


211 
228

SEE ALSO 
lseek, fopen, fclose, ftell 


B 


FSEEK 


Pacific C Compiler 212 
229

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 


B 


Appendix B -Library Functions 


213 
230

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 


B 


FWRITE 


Pacific C Compiler 214 
231

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(), andis 
defined in stdio. h. 


EXAMPLE 
#include <stdio. h> 


main() 
{ 
int i; 


while(( i = getc( stdin)) != EOF) 
putchar( i); 
} 


RETURN VALUE 
EOF will be returned on end-of-file or error. 


B 


Appendix B -Library Functions 


215 
232

GETCH, GETCHE, UNGETCH SYNOPSIS 
#include <conio. h> 
char getch( void) 
char getche( void) 
void ungetch( char) 


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; 


while(( c = getche()) != '\ n') 
continue; 
} 


SEE ALSO 
cgets, cputs 


B 


GETCH, GETCHE, UNGETCH 


Pacific C Compiler 216 
233

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 


B 


Appendix B -Library Functions 


217 
234

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 


B 


GETCWD 


Pacific C Compiler 218 
235

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 


B 


Appendix B -Library Functions 


219 
236

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. 


B 


GETENV 


Pacific C Compiler 220 
237

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. 


B 


Appendix B -Library Functions 


221 
238

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 


B 


GETIVA 


Pacific C Compiler 222 
239

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]; 


printf(" Type a line: "); 
if( gets( buf)) 
puts( buf); 
} 


RETURN VALUE 
It returns its argument, or NULL on end-of-file. 
SEE ALSO 
fgets, freopen, puts 


B 


Appendix B -Library Functions 


223 
240

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 


B 


GETW 


Pacific C Compiler 224 
241

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); 
} 


DATA TYPES 
typedef long time_ t; struct tm { 
int tm_ sec; 
int tm_ min; 


B 


Appendix B -Library Functions 


225 
242

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 


B 


GMTIME 


Pacific C Compiler 226 
243

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. Theinregs 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. Thexversions 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> 


/* Check available BIOS extended memory */ 
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 
struct WORDREGS { unsigned int ax; 
unsigned int bx; 
unsigned int cx; 


B 


Appendix B -Library Functions 


227 
244

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; 
}; 


struct SREGS { 
unsigned int es; 
unsigned int cs; 
unsigned int ss; 
unsigned int ds; 
}; 


SEE ALSO 
segread, intdos, intdosx 


B 


INT86, INT86X 


Pacific C Compiler 228 
245

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. Thex 
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; 
unsigned int di; 
unsigned int cflag; 
unsigned int psw; 
}; 


B 


Appendix B -Library Functions 


229 
246

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 


B 


INTDOS, INTDOSX 


Pacific C Compiler 230 
247

ISALNUM, ISALPHA, ISDIGIT, ISLOWER et. al. SYNOPSIS 
#include <ctype. h> 
isalnum( char c) 
isalpha( char c) 
isascii( char c) 
iscntrl( char c) 
isdigit( char c) 
islower( char c) 
isprint( char c) 
isgraph( char c) 
ispunct( char c) 
isspace( char c) 
isupper( char c) 
isalnum( char c) 


DESCRIPTION 
These macros, defined in ctype. h, test the supplied character for membership in one of several overlapping 
groups of characters. Note that all except isascii are defined for c 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 
#include <ctype. h> 
#include <stdio. h> 


main() 


B 


Appendix B -Library Functions 


231 
248

{ 
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 


B 


ISALNUM, ISALPHA, ISDIGIT, ISLOWER et. al. 


Pacific C Compiler 232 
249

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. 


B 


Appendix B -Library Functions 


233 
250

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"); 
} 


B 


ISNEC98 


Pacific C Compiler 234 
251

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 


B 


Appendix B -Library Functions 


235 
252

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 


B 


LDEXP 


Pacific C Compiler 236 
253

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 
div B 


Appendix B -Library Functions 


237 
254

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; 
int tm_ mon; 
int tm_ year; 
int tm_ wday; 


B 


LOCALTIME 


Pacific C Compiler 238 
255

int tm_ yday; 
int tm_ isdst; 
}; 


SEE ALSO 
ctime, asctime, time 


B 


Appendix B -Library Functions 


239 
256

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 suchthate10 sup x =f . 


EXAMPLE 
#include <math. h> 
#include <stdio. h> 


main() 
{ 
double f; 


for( f = 1.0 ;f <= 10.0 ;f += 1.0) 
printf(" log(% 1.0f) = %f\ n", f, log( f)); 
} 


RETURN VALUE 
Zero if the argument is negative. 
SEE ALSO 
exp, pow 


B 


LOG, LOG10 


Pacific C Compiler 240 
257

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"); 
inner(); 
printf(" inner returned -bad!\ n"); 
} 


B 


Appendix B -Library Functions 


241 
258

RETURN VALUE 
Longjmp never returns. 
SEE ALSO 
setjmp 


B 


LONGJMP 


Pacific C Compiler 242 
259

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; 


fd = open(" test. fil", 1); /* open for write */ 
if( fd < 0) 
exit( 1); 
lseek( fd, 0L, 2); /* seek to end */ 
write( fd, "more stuff\ r\ n", 12); 
close( fd); 
} 


RETURN VALUE 
-1 is returned on error, the resulting location otherwise. 
SEE ALSO 
open, close, read, write 


B 


Appendix B -Library Functions 


243 
260

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 


MALLOC 


Pacific C Compiler 244 
261

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> 


unsigned int ary[] = { 
1, 5, 0x6789, 0x23 
}; 


main() 
{ 
char * cp; 


cp = memchr( ary, 0x89, sizeof ary); 
if(! cp) 
printf(" not found\ n"); 
else 
printf(" Found at offset %u\ n", cp -(char *) ary); 
} 


RETURN VALUE 
A pointer to the first byte matching the argument if one exists; NULL otherwise. 
SEE ALSO 
strchr 
B 


Appendix B -Library Functions 


245 
262

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. 


SEE ALSO 
strncpy, strncmp, strchr, memset, memchr 


B 


MEMCMP 


Pacific C Compiler 246 
263

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]; 


memset( buf, 0, sizeof buf); 
memcpy( buf, "a partial string", 10); 
printf(" buf = '% s'\ n", buf); 
} 


RETURN VALUE 
Memcpy() returns its first argument. 
SEE ALSO 
strncpy, strncmp, strchr, memset 


B 


Appendix B -Library Functions 


247 
264

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 


B 


MEMMOVE 


Pacific C Compiler 248 
265

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]; 


strcpy( abuf, "This is a string"); 
memset( abuf, 'x', 5); 
printf(" buf = '% s'\ n", abuf); 
} 


SEE ALSO 
strncpy, strncmp, strchr, memcpy, memchr 


B 


Appendix B -Library Functions 


249 
266

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 


B 


MKDIR 


Pacific C Compiler 250 
267

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 
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 


B 


Appendix B -Library Functions 


251 
268

pun: Accesses the punch device -write only 
rdr: Accesses the reader device -read only 
con: Accesses the system console -read/ write 


File names may be in any case -they are converted to upper case during processing of the name. 
MS-DOS filenames may be any valid MS-DOS 2. xx filename, e. g. 
fred. nrk A:\ HITECH\ STDIO. H 


The special device names (e. g. CON, LST) are also recognized. These do not require (and should not 
have) a trailing colon. 


EXAMPLE 
#include <stdio. h> 
#include <stdlib. h> 
#include <unixio. h> 


main() 
{ 
int fd; 


fd = open(" test. fil", 1); /* open for write */ 
if( fd < 0) 
exit( 1); 
lseek( fd, 0L, 2); /* seek to end */ 
write( fd, "more stuff\ r\ n", 12); 
close( fd); 
} 


SEE ALSO 
close, fopen, fclose, read, write, creat 


B 


OPEN 


Pacific C Compiler 252 
269

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 


B 


Appendix B -Library Functions 


253 
270

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; 


for( f = 1.0 ;f <= 10.0 ;f += 1.0) 
printf(" pow( 2, %1.0f) = %f\ n", f, pow( 2, f)); 
} 


SEE ALSO 
log, log10, exp 


B 


POW 


Pacific C Compiler 254 
271

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. 
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. 


B 


Appendix B -Library Functions 


255 
272

o x X u dInteger 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: "); 
vprintf( s, ap); 
putchar('\ n'); 
va_ end( ap); 


B 


PRINTF, VPRINTF 


Pacific C Compiler 256 
273

} 
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 


B 


Appendix B -Library Functions 


257 
274

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> 


char * x = "this is a string"; 
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 


B 


PUTC 


Pacific C Compiler 258 
275

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> 


char * x = "this is a string"; 
main() 
{ 
char * cp; 


cp =x; 
while(* x) 
putch(* x++); 
putch('\ n'); 
} 


SEE ALSO 
cgets, cputs, getch, getche 


B 


Appendix B -Library Functions 


259 
276

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> 


char * x = "this is a string"; 
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 


B 


PUTCHAR 


Pacific C Compiler 260 
277

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 


B 


Appendix B -Library Functions 


261 
278

PUTW SYNOPSIS 
#include <stdio. h> 
int putw( int w, FILE * stream) 


DESCRIPTION 
Putw() copies the word wto 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 


B 


PUTW 


Pacific C Compiler 262 
279

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; 


qsort( aray, sizeof aray/ sizeof aray[ 0], 
sizeof aray[ 0], sortem); 
for(i =0 ;i != sizeof aray/ sizeof aray[ 0] ; i++) 
printf("% d\ t", aray[ i]); 
putchar('\ n'); 
} 


NOTE 
The function parameter must be a pointer to a function of type similar to: 


B 


Appendix B -Library Functions 


263 
280

int func( const void *, const void *) 
i. e. it must accept two const void * parameters, and must be prototyped. 


B 


QSORT 


Pacific C Compiler 264 
281

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 


B 


Appendix B -Library Functions 


265 
282

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; 


/* read from stdin */ 
i = read( 0, buf, sizeof( buf)); 
printf(" Read %d bytes\ n", 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 


B 


READ 


Pacific C Compiler 266 
283

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 


B 


Appendix B -Library Functions 


267 
284

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 


B 


REMOVE 


Pacific C Compiler 268 
285

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 


B 


Appendix B -Library Functions 


269 
286

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]; 


if(! freopen(" test. fil", "r", stdin)) 
exit( 1); 
gets( buf); 
printf(" got '% s'\ n", buf); 
rewind( stdin); 
gets( buf); 
printf(" Got '% s' again\ n", buf); 
} 


RETURN VALUE 
Areturn value of -1 indicates that the attempt was not successful, perhaps because the streamis associated 
with a non-random access file such as a character device. 


SEE ALSO 
fseek, ftell 


B 


REWIND 


Pacific C Compiler 270 
287

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 


B 


Appendix B -Library Functions 


271 
288

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 


B 


SBRK 


Pacific C Compiler 272 
289

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 dSkip 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 fromthe 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 
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. B 


Appendix B -Library Functions 


273 
290

EXAMPLE 
scanf("% d %s", &a, &s) 
with input " 12s" 
will assign 12 to a, and "s" to s. 


scanf("% 3cd %lf", &c, &f) 
with input " abcd -3.5" 
will assign " abc" to c, and -3.5 to f. 


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 


B 


SCANF, VSCANF 


Pacific C Compiler 274 
291

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 


B 


Appendix B -Library Functions 


275 
292

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 


SETJMP 


Pacific C Compiler 276 
293

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; 


/* set a large buffer for stdout */ 
setvbuf( stdout, buffer, _IOFBF, sizeof buffer); 
for(i =0 ;i != 2000 ; i++) 
if(( i % 100) == 0) 
printf(" i = %4d\ n", i); 
else 
for(j =0 ;j != 1000 ; j++) 


B 


Appendix B -Library Functions 


277 
294

continue; 
} 


NOTE 
If the buf argument is null, then the size is ignored. 
SEE ALSO 
fopen, freopen, fclose 


B 


SETVBUF, SETBUF 


Pacific C Compiler 278 
295

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> 


static far interrupt void 
brkintr( void) 
{ 
exit(-1); 
} 


#define BRKINT 0x23 
#define BRKINTV (( far isr *)( BRKINT * 4)) 


void 
set_ trap( void) 
{ 
set_ vector( BRKINTV, brkintr); 
} 


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. 


B 


Appendix B -Library Functions 


279 
296

SEE ALSO 
di(), ei(), ROM_ VECTOR, RAM_ VECTOR, CHANGE_ VECTOR 


B 


SET_ VECTOR 


Pacific C Compiler 280 
297

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(). Thesig 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); 
} 
signal( SIGINT, catch); 
for(i =0 ;; i++){ 
printf("% 6d\ r", i); 


B 


Appendix B -Library Functions 


281 
298

} 
} 


SEE ALSO 
exit 


B 


SIGNAL 


Pacific C Compiler 282 
299

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; 


for(i =0 ;i <= 180.0 ;i += 10) 
printf(" sin(% 3.0f) = %f, cos = %f\ n", 
i, sin( i* C), cos( i* C)); 
} 


SEE ALSO 
cos, tan, asin, acos, atan 


B 


Appendix B -Library Functions 


283 
300

SPAWNL, SPAWNV, SPAWNVE SYNOPSIS 
#include <sys. h> 
int spawnl( char * n, char * argv0, ...); 
int spawnle( char * n, char * argv0, ...); 
int spawnv( char * n, char ** v) 
int spawnve( char * n, char ** v, char ** e) 
int spawnvp( char * n, char ** v) 
int spawnlp( char * n, char * argv0, ...); 


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() 
{ 
spawnlp(" mem", "mem", NULL); 


B 


SPAWNL, SPAWNV, SPAWNVE 


Pacific C Compiler 284 
301

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 


B 


Appendix B -Library Functions 


285 
302

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 


B 


SPRINTF 


Pacific C Compiler 286 
303

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; 


for(i =0 ;i <= 20.0 ;i += 1.0) 
printf(" square root of %. 1f = %f\ n", i, sqrt( i)); 
} 


SEE ALSO 
exp 


B 


Appendix B -Library Functions 


287 
304

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(). Onthe 
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 


B 


SRAND 


Pacific C Compiler 288 
305

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 


B 


Appendix B -Library Functions 


289 
306

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; 
{ 
struct stat sb; 


if( argc > 1) { 


B 


STAT 


Pacific C Compiler 290 
307

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 


B 


Appendix B -Library Functions 


291 
308

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; 


strcpy( buffer, "Start of line"); 
s1 = buffer; 
s2 = " ... end of line"; 
strcat( s1, s2); 
printf(" Length = %d\ n", strlen( buffer)); 
printf(" string = \"% s\"\ n", buffer); 
} 


RETURN VALUE 
The value of s1 is returned. 
SEE ALSO 
strcpy, strcmp, strncat, strlen 


B 


STRCAT 


Pacific C Compiler 292 
309

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 


B 


Appendix B -Library Functions 


293 
310

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; 


if(( i = strcmp(" ABC", "ABc")) < 0) 
printf(" ABC is less than ABc\ n"); 
else if( i > 0) 
printf(" ABC is greater than ABc\ n"); 
else 
printf(" ABC is equal to ABc\ n"); 
} 


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 


STRCMP 


Pacific C Compiler 294 
311

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; 


strcpy( buffer, "Start of line"); 
s1 = buffer; 
s2 = " ... end of line"; 
strcat( s1, s2); 
printf(" Length = %d\ n", strlen( buffer)); 
printf(" string = \"% s\"\ n", buffer); 
} 


RETURN VALUE 
The destination buffer pointer s1 is returned. 
SEE ALSO 
strncpy, strlen, strcat, strlen 


B 


Appendix B -Library Functions 


295 
312

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; 


strcpy( buffer, "Start of line"); 
s1 = buffer; 
s2 = " ... end of line"; 
strcat( s1, s2); 
printf(" Length = %d\ n", strlen( buffer)); 
printf(" string = \"% s\"\ n", buffer); 
} 


B 


STRLEN 


Pacific C Compiler 296 
313

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; 


strcpy( buffer, "Start of line"); 
s1 = buffer; 
s2 = " ... end of line"; 
strncat( s1, s2, 5); 
printf(" Length = %d\ n", strlen( buffer)); 
printf(" string = \"% s\"\ n", buffer); 
} 


RETURN VALUE 
The value of s1 is returned. 
SEE ALSO 
strcpy, strcmp, strcat, strlen 


B 


Appendix B -Library Functions 


297 
314

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 


B 


STRNCMP 


Pacific C Compiler 298 
315

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; 


strncpy( buffer, "Start of line", 6); 
s1 = buffer; 
s2 = " ... end of line"; 
strcat( s1, s2); 
printf(" Length = %d\ n", strlen( buffer)); 
printf(" string = \"% s\"\ n", buffer); 
} 


RETURN VALUE 
The destination buffer pointer s1 is returned. 
SEE ALSO 
strcpy, strcat, strlen, strcmp 


B 


Appendix B -Library Functions 


299 
316

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 


B 


STRRCHR 


Pacific C Compiler 300 
317

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 


B 


Appendix B -Library Functions 


301 
318

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; 


for(i =0 ;i <= 180.0 ;i += 10) 
printf(" tan(% 3.0f) = %f\ n", 
i, tan( i* C)); 
} 


SEE ALSO 
sin, cos, asin, acos, atan 


B 


TAN 


Pacific C Compiler 302 
319

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 


B 


Appendix B -Library Functions 


303 
320

TOLOWER, TOUPPER, TOASCII SYNOPSIS 
#include <ctype. h> char toupper( int c); 
char tolower( int c); 
char toascii( int c); 
char c; 


DESCRIPTION 
Toupper() converts its lower case alphabetic argument to upper case, tolower() performs the reverse 
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. 


B 


TOLOWER, TOUPPER, TOASCII 


Pacific C Compiler 304 
321

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 


B 


Appendix B -Library Functions 


305 
322

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 


B 


UNLINK 


Pacific C Compiler 306 
323

VA_ START, VA_ ARG, VA_ END SYNOPSIS 
#include <stdarg. h> 
void va_ start( va_ list ap, parmN); 
type va_ arg( ap, type); 
void va_ end( va_ list ap); 


DESCRIPTION 
These macros are provided to give access in a portable way to parameters to a function represented in a 
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); 
} 


main() 
{ 


B 


Appendix B -Library Functions 


307 
324

pf( 3, "Line 1", "line 2", "line 3"); 
} 


B 


VA_ START, VA_ ARG, VA_ END 


Pacific C Compiler 308 
325

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 


B 


Appendix B -Library Functions 


309 
326

_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 


B 


_DOS_ GETFTIME 


Pacific C Compiler 310 
327

_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 


B 


Appendix B -Library Functions 


311 
328

_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> 


main( argc, argv) 
char ** argv; 
{ 


B 


_GETARGS 


Pacific C Compiler 312 
329

extern char ** _getargs(); 
extern int _argc_; 


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. 


B 


Appendix B -Library Functions 


313 
330

_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; 


blk1 = _xms_ alloc( 1); /* get 1Kb */ 
blk2 = _xms_ alloc_ bytes( 2048); /* get 2Kb */ 
printf(" blk1 = %4.4X, blk2 = %4.4X\ n", 
blk1, blk2); 
if (blk1 != 0) 
_xms_ dispose( blk1); 
if (blk2 != 0) 
_xms_ dispose( 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 


_XMS_ ALLOC, _XMS_ ALLOC_ BYTES 


Pacific C Compiler 314 
331

SEE ALSO 
_xms_ dispose, _xms_ malloc, _xms_ resize, _xms_ resize_ bytes 


B 


Appendix B -Library Functions 


315 
332

_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; 


handle = _xms_ alloc( 10); /* get 10Kb */ 
printf(" handle = %4.4X\ n", handle); 
if (handle) 
_xms_ dispose( 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_ DISPOSE 


Pacific C Compiler 316 
333

_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; 
SEE ALSO 
_driver, _driverx, _xms_ installed 
B 


Appendix B -Library Functions 


317 
334

_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> 


#define SIZE 8192 
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); 
} else B 


_XMS_ FLUSH 


Pacific C Compiler 318 
335

printf(" Unable to use XMS!\ n"); 
} 


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 


B 


Appendix B -Library Functions 


319 
336

_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; 


handle = _xms_ alloc( 1); /* grab 1K block */ 
if (handle) { 
addr = _xms_ lock( handle); 
_xms_ info( handle, &info); 
printf(" Handle = %4.4X\ n", handle); 
printf(" Address = %8.8lX\ n", addr); 
printf(" Lock count = %d\ n", info. lock_ count); 
printf(" Free handles = %d\ n", info. free_ handles); 
_xms_ unlock( handle); 
_xms_ dispose( handle); 
} else 
printf(" Couldn't allocate XMS\ n"); 
} 


RETURN VALUE 
Integer, 1 on success, 0 on failure. 


B 


_XMS_ INFO 


Pacific C Compiler 320 
337

DATA TYPES 
typedef unsigned int _XMS_ HANDLE; struct _XMS_ INFO { 
unsigned char lock_ count; 
unsigned char free_ handles; 
}; 


SEE ALSO 
_xms_ lock, _xms_ unlock 


B 


Appendix B -Library Functions 


321 
338

_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 


B 


_XMS_ INSTALLED 


Pacific C Compiler 322 
339

_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. Alock 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; 


handle = _xms_ alloc( 1); /* grab 1K block */ 
if (handle) { 
addr = _xms_ lock( handle); 
printf(" Block address = %8.8lX\ n", addr); 
_xms_ unlock( handle); 
_xms_ dispose( handle); 
} else 
printf(" Couldn't allocate XMS\ n"); 
} 


RETURN VALUE 
Unsigned long, the physical address of the block on success, 0 on failure. 
DATA TYPES 
typedef unsigned int _XMS_ HANDLE; 
SEE ALSO 
_xms_ info, _xms_ unlock 


B 


Appendix B -Library Functions 


323 
340

_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 


_XMS_ MEMAVAIL 


Pacific C Compiler 324 
341

SEE ALSO 
_xms_ info, _xms_ version 


B 


Appendix B -Library Functions 


325 
342

_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 


B 


_XMS_ MEMSET 


Pacific C Compiler 326 
343

_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 */ 
move. src. ptr = buf; 
move. dst_ handle = handle; /* XMS */ 
move. dst. offset = 0; 
if (!_ xms_ move(& move)) { 


B 


Appendix B -Library Functions 


327 
344

printf(" Store to XMS failed!\ n"); 
_xms_ dispose( handle); 
exit( 1); 
} 
strcpy( buf, "THIS IS A DIFFERENT STRING!!!!"); 
move. count = sizeof( buf); 
move. src_ handle = handle; /* XMS */ 
move. src. offset = 0; 
move. dst_ handle = 0; /* conventional memory */ 
move. dst. ptr = buf; 
if (!_ xms_ move(& move)) { 
printf(" Retrieve from XMS failed!\ n"); 
_xms_ dispose( handle); 
exit( 1); 
} 
printf(" Retrieved '% s' from XMS\ n", buf); 
_xms_ dispose( handle); 
exit( 0); 
} 


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_ MOVE 


Pacific C Compiler 328 
345

_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> 


static char test[] = "This is a test string!"; 
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 
typdef unsigned int _XMS_ HANDLE; 


B 


Appendix B -Library Functions 


329 
346

SEE ALSO 
_xms_ write 


B 


_XMS_ READ 


Pacific C Compiler 330 
347

_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) 


unsigned char _xms_ driver_ realloc; 


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; 


handle = _xms_ alloc( 32); /* grab 32Kb */ 
if (handle) { 
new = _xms_ resize( handle, 16); 
printf(" old handle = %4.4X\ n", handle); 
printf(" new handle = %4.4X\ n", new); 
if (new) 
_xms_ dispose( new); 
else 
_xms_ dispose( handle); 
} else 
printf(" Unable to allocate XMS\ n"); 
} 


RETURN VALUE 
An _XMS_ HANDLE on success, 0 on failure. 


B 


Appendix B -Library Functions 


331 
348

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. 


B 


_XMS_ RESIZE, _XMS_ RESIZE_ BYTES 


Pacific C Compiler 332 
349

_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; 


handle = _xms_ alloc( 1); /* grab 1K block */ 
if (handle) { 
addr = _xms_ lock( handle); 
printf(" Block address = %8.8lX\ n", addr); 
_xms_ unlock( handle); 
_xms_ dispose( handle); 
} else 
printf(" Couldn't allocate XMS\ n"); 
} 


RETURN VALUE 
Integer, 1 on success, 0 on failure. 
DATA TYPES 
typedef unsigned int _XMS_ HANDLE; 
SEE ALSO 
_xms_ info, _xms_ lock 
B 


Appendix B -Library Functions 


333 
350

_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; 
unsigned char rev_ major; 
unsigned char rev_ minor; 


B 


_XMS_ VERSION 


Pacific C Compiler 334 
351

unsigned char hma_ exists; 
}; 


SEE ALSO 
_xms_ info, _xms_ memavail 


B 


Appendix B -Library Functions 


335 
352

_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> 


static char test[] = "This is a test string!"; 
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 
typedef unsigned int _XMS_ HANDLE; 


B 


_XMS_ WRITE 


Pacific C Compiler 336 
353

SEE ALSO 
_xms_ flush, _xms_ read 


B 


Appendix B -Library Functions 


337 
354

_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; 


handle = _xms_ zalloc( COUNT, sizeof( int)); 
if (handle) { 
printf(" handle = %4.4X\ n", handle); 
_xms_ dispose( handle); 
} else 
printf(" Couldn't allocate XMS\ n"); 
} 


RETURN VALUE 
Integer, 1 on success, 0 on failure. 
DATA TYPES 
typedef unsigned int _XMS_ HANDLE; 


B 


_XMS_ ZALLOC 


Pacific C Compiler 338 
355

B 
Appendix B -Library Functions 


339 
356

Index 
! 
32 
bit, 64 
80186, 56 
80286, 56 
80386, 56 
80486, 56 
8086, 55, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 
100 
80C188EB, 87 
_DOS_ GETFTIME, 309 
_EXIT, 310 
_GETARGS, 311 
_XMS_ ALLOC, _XMS_ ALLOC_ BYTES, 313 
_XMS_ DISPOSE, 315 
_XMS_ DRIVER, 316 
_XMS_ FLUSH, 317 
_XMS_ INFO, 319 
_XMS_ INSTALLED, 321 
_XMS_ LOCK, 322 
_XMS_ MEMAVAIL, 323 
_XMS_ MEMSET, 325 
_XMS_ MOVE, 326, 327 
_XMS_ READ, 328, 329 
_XMS_ RESIZE, _XMS_ RESIZE_ BYTES, 330, 331 
_XMS_ UNLOCK, 332 
_XMS_ VERSION, 333 
_XMS_ WRITE, 335 
_XMS_ ZALLOC, 337 


A 
ACOS, 153 
address 
arithmetic, 78 
link, 49 


load, 49, 50 
argc, 78 
argument 
passing, 45 
arguments 
to, 44 
argv, 77, 78 
arrays 
displaying, 84 
as86 
options, 55, 56, 57 
pseudo, 67 
pseudo-ops, 61, 62, 63, 64, 65, 66, 67, 68, 69 
ASCTIME, 154, 155 
ASIN, 156 
assembler, 55, 56, 58, 60, 62, 64, 66, 68, 70, 
72, 74, 76 
compatibility, 55 
interface, 46 
listing, 56 
output, 56 
ASSERT, 157 
ATAN, 158 
ATEXIT, 159 
ATOF, 160 
ATOI, 161 
ATOL, 162 
AUTOEXEC. BAT, 3 


B 
baud rate , 96 
bp, 44 
branch, 57 
BSEARCH, 163 


1 


Pacific C Compiler 339 
357

C 
CALLOC, 165 
CEIL, 166 
CGETS, 167 
CHDIR, 168 
CHDRV, 169 
CHMOD, 170 
CLOSE, 171 
CLRERR, CLREOF, 172 
COM port, 96 
Command 
line, 77, 78 
compiler driver 
command line, 3 
CONFIG. SYS, 3 
constants, 59 
COS, 173 
COSH, SINH, TANH, 174 
CPUTS, 175 
CREAT, 176 
cross 
reference, 57 
CTIME, 177 


D 
data 
representation, 48 
DI, EI, 178 
DIV, 179 
Download , 96 
DRIVER, 180, 181 
DUP, 182 
DUP2, 183 


E 
environment variables 
PATH, 3 
TEMP, 1 
EPROM , 87 
EPROM programmer, 95 
error 
messages, 72, 73, 75 
EXIT, 184 
EXP, 185 
expressions, 59 
Extern 
functions, 81 


F 
FABS, 186 
far 
call, 57 
FARMALLOC, FARFREE, FARREAL-LOC, 
187 
FARMEMCPY, FARMEMSET, 189 
FCLOSE, 190 
FDOPEN, 191 
FEOF, FERROR, 192 
FFIRST, FNEXT, 193 
FFLUSH, 194 
FGETC, 195 
FGETS, 196 
FILENO, 197 
fixups, 53 
FLOOR, 198 
FOPEN, 199 
FPRINTF, 201, 202 
FPUTC, 203 
FPUTS, 204 
frame 
pointer, 84 
FREAD, 205 


1 


340 
358

FREE, 206 
FREOPEN, 207 
FREXP, 208 
FSCANF, 209 
FSEEK, 210, 211 
FTELL, 212 
function 
prototypes, 45 
FWRITE, 213 


G 
GETC, 214 
GETCH, GETCHE, UNGETCH, 215 
GETCHAR, 216 
GETCWD, 217 
GETDRV, 218 
GETENV, 219 
GETFREEMEM, 220 
GETIVA, 221 
GETS, 222 
getting started, 5 
GETW, 223 
GMTIME, 224, 225 


H 
heap, 45 


I 
include 
files, 57 
INSTALL program, 1 
installation, 1, 2, 3, 87, 95 
custom, 2, 91 
installation key, 2, 95 
INT86, INT86X, 226, 227 
INTDOS, INTDOSX, 228, 229 
Intel 


assembler, 55 
object, 56 
inter-segment 
call, 57 
interrupt vectors, 88, 94 
ISALNUM, ISALPHA, ISDIGIT, IS-LOWER 
et. al., 230, 231 
ISATTY, 232 
ISNEC98, 233 


J 
jump 
optimization, 55 


K 
KBHIT, 234 


L 
LDEXP, 235 
LDIV, 236 
Library 
functions, 81 
LINK, 3 
link address, 100 
linker, 99, 100, 102, 104, 106, 108 
linking, 48, 49, 51, 53 
listing 
width, 56 
load address, 100 
local 
data, 44 
symbols, 56 
LOCALTIME, 237 
LOG, LOG10, 239 
LONGJMP, 240, 241 
LSEEK, 242 


1 
Index 


Pacific C Compiler 341 
359

M 
main(), 43 
MALLOC, 243 
MEMCHR, 244 
MEMCMP, 245 
MEMCPY, 246 
MEMMOVE, 247 
memory 
allocation, 45 
Memory Model, 89 
memory organization , 88 
MEMSET, 248 
Microsoft 
assembler, 55 
object, 56 
MKDIR, 249 
MS-DOS, 53 
linker, 56 


N 
non-volatile RAM, 93 
numbers 
in linker options, 101 


O 
OPEN, 250, 251 
Optimisation , 94 
options 
linker, 101, 103, 105 


P 
PACC, 6 
PACC. EXE, 3 
PACKING. LST, 1 
PATH environment variable, 3 


peek(), 46 
PERROR, 252 
pointers, 48 
POW, 253 
powerup routine, 92 
PRINTF, VPRINTF, 254, 255 
Processor Type, 91 
prototypes 
function, 45 
psect, 49, 59, 61 
flags, 63, 64 
linking, 99 
PUTC, 257 
PUTCH, 258 
PUTCHAR, 259 
PUTS, 260 
PUTW, 261 


Q 
QSORT, 262, 263 


R 
RAM 
non-volatile, 93 
RAND, 264 
READ, 265 
REALLOC, 266 
reboot 
after installation, 3 
reloc=, 50 
relocatable 
code, 59 
relocation, 99 
REMOVE, 267 
RENAME, 268 
reset address, 88 
REWIND, 269 
RMDIR, 270 


1 


342 
360

ROM 
code, 48 
ROM Development, 87 
run-time startups, 87 
runtime 
organization, 43, 44, 46, 48, 50, 52, 54 
startup, 43 


S 
SBRK, 271 
SCANF, VSCANF, 272, 273 
segment, 49 
SEGREAD, 274 
serial number, 2, 95 
serial port , 88 
serial. c, 96 
SET_ VECTOR, 278, 279 
SETJMP, 275 
SETVBUF, SETBUF, 276, 277 
SIGNAL, 280, 281 
signatures, 47 
SIN, 282 
size 
error, 57 
Source File List, 94 
SPAWNL, SPAWNV, SPAWNVE, 283 
SPRINTF, 285 
SQRT, 286 
SRAND, 287 
SSCANF, 288 
stack, 45 
frame, 43 
STAT, 289 
STRCAT, 291 
STRCHR, 292 
STRCMP, 293 
STRCPY, 294 
STRLEN, 295 
STRNCAT, 296 
STRNCMP, 297 


STRNCPY, 298 
STRRCHR, 299 
symbols, 57 
global, 100 
SYSTEM, 300 


T 
TAN, 301 
temporary 
labels, 58 
TIME, 302 
TOLOWER, TOUPPER, TOASCII, 303 


U 
undefined 
symbols, 55 
UNGETC, 304 
UNLINK, 305 


V 
VA_ START, VA_ ARG, VA_ END, 306, 307 


W 
WRITE, 308 


1 
Index 


Pacific C Compiler 343 
361

1 
344 
362

1 
363

Introduction 
Quick Start Guide 
Using PPD 
Runtime Organization 
8086 Assembler Reference Manual 
Lucifer-A Source Level Debugger 
Rom Development with Pacific C 
Linker Reference Manual 
Librarian Reference Manual 
Error Messages 
Library Functions 


2 
3 
4 
5 
6 
7 
8 
9 
A 
B 


1 
364

1 
365

Pacific C for DOS, 2nd printing, April 1995 
Copyright ă 1995 HI-TECH Software 


1 
366


i'm sorry,
Attachment Brent Metzler.vcf does not look
        like a PDF filewhile processing part or all of your message.