VERSION 2.5
────────────────────────────────────────────────────────────────────────────
MICROSOFT CORPORATION
Information in this document is subject to change without notice and does
not represent a commitment on the part of Microsoft Corporation. The
software described in this document is furnished under a license agreement
or nondisclosure agreement. The software may be used or copied only in
accordance with the terms of the agreement. It is against the law to copy
the software on any medium except as specifically allowed in the license or
nondisclosure agreement. No part of this manual may be reproduced or trans-
mitted in any form or by any means, electronic or mechanical, including
photocopying and recording, for any purpose without the express written
permission of Microsoft.
(C) Copyright Microsoft Corporation, 1988, 1990. All rights reserved.
Printed and bound in the United States of America.
Microsoft, MS, MS-DOS, CodeView, QuickC, and XENIX are
registered trademarks and Windows is a trademark of Microsoft Corporation.
COMPAQ is a registered trademark of Compaq Computer Corporation.
Hercules is a registered trademark and InColor is a trademark
of Hercules Computer Technology.
Intel is a registered trademark of Intel Corporation.
IBM is a registered trademark of International Business
Machines Corporation.
Table of Contents
────────────────────────────────────────────────────────────────────────────
Introduction
About This Manual
Elsewhere in This Package
Key to Document Conventions
PART I Tool Kit Tutorial
────────────────────────────────────────────────────────────────────────────
Chapter 1 Creating Executable Programs
1.1 Compiling and Linking: An Overview
1.2 Using the QCL Command
1.3 Specifying File Names
1.4 Controlling Compiling and Linking with QCL Options
1.4.1 Compiling without Linking
1.4.2 Compiling Only Modified Functions
1.4.3 Optimizing Programs
1.4.4 Naming Output Files
1.4.5 Turning Off Language Extensions
1.4.6 Debugging and Syntax Checking
1.4.7 Controlling the Preprocessor
1.4.8 Compiling for Specific Hardware
1.4.9 Choosing Memory Models
1.4.10 Controlling the Linking Process
1.4.11 Other QCL Options
1.5 Invoking the Linker Directly: The QLINK Command
1.5.1 Giving Input to the QLINK Command
1.5.2 QLINK Options
Chapter 2 Maintaining Software Libraries with LIB
2.1 Why Use a Library?
2.2 The LIB Command
2.3 Listing the Contents of a Library
2.4 Modifying the Contents of a Library
2.4.1 Modifying the Library
2.4.2 Adding a Module
2.4.3 Deleting a Module
2.4.4 Replacing a Module
2.4.5 Copying and Moving Modules from a Library
2.5 Creating a New Library
2.6 Other Ways of Using LIB
Chapter 3 Maintaining Programs with NMAKE
3.1 How NMAKE Works
3.2 Building a Simple Description File
3.2.1 Description Blocks
3.2.2 The CC Macro
3.3 Invoking NMAKE
3.3.1 Invoking NMAKE from the DOS Command Line
3.3.2 Invoking NMAKE with a Response File
3.4 NMAKE Options
3.4.1 Controlling Input
3.4.2 Controlling Execution
3.4.3 Controlling Output
3.5 Building Complex Description Files
3.5.1 Using Special Characters to Modify Commands
3.5.2 Using Macros
3.5.3 Using Inference Rules
3.5.4 Using Directives
3.6 Other NMAKE Features
PART II Reference to QuickC Tools
────────────────────────────────────────────────────────────────────────────
Chapter 4 QCL Command Reference
4.1 The QCL Command Line
4.2 How the QCL Command Works
4.3 QCL Options
4.3.1 /A Options (Memory Models)
4.3.2 /batch (Compile in Batch Mode)
4.3.3 /c (Compile without Linking)
4.3.4 /C (Preserve Comments during Preprocessing)
4.3.5 /D (Define Constants and Macros)
4.3.6 /E (Copy Preprocessor Output to Standard Output)
4.3.7 /EP (Copy Preprocessor Output to Standard Output)
4.3.8 /F (Set Stack Size)
4.3.9 /Fe (Rename Executable File)
4.3.10 /Fm (Create Map File)
4.3.11 /Fo (Rename Object File)
4.3.12 /FP Options (Select Floating-Point-Math Package)
4.3.13 /G0, /G1, /G2 (Generate Instructions for 8086, 80186,
or 80286 Processor)
4.3.14 /Gc, /Gd (Use FORTRAN/Pascal or C Calling Convention)
4.3.15 /Ge, /Gs (Turn Stack Checking On or Off)
4.3.16 /Gi (Use Incremental Compilation)
4.3.17 /Gr (Register Calling Convention)
4.3.18 /Gt (Set Data Threshold)
4.3.19 /Gw,
/GW (Generate Code for Windows(tm) Function Calls)
4.3.20 /HELP (List the Compiler Options)
4.3.21 /I (Search Directory for Include Files)
4.3.22 /J (Change Default char Type)
4.3.23 /Lc, Lr (Compile for Real Mode)
4.3.24 /Li (Link Incrementally)
4.3.25 /Ln (Link without C Run-Time Startup Code)
4.3.26 /ND, /NT (Name the Data or Code Segments)
4.3.27 /nologo (Suppress Display of Sign-On Banner)
4.3.28 /O Options (Optimize Program)
4.3.29 /P (Create Preprocessor-Output File)
4.3.30 /Ta, /Tc (Specify Assembly Language or C Source File)
4.3.31 /U, /u (Remove Predefined Names)
4.3.32 /V (Set Version String)
4.3.33 /W, /w (Set Warning Level)
4.3.34 /X (Ignore Standard Include Directory)
4.3.35 /Ze, /Za (Enable or Disable Language Extensions)
4.3.36 /Zi, /Zd (Compile for Debugging)
4.3.37 /Zl (Remove Default-Library Name from Object File)
4.3.38 /Zp (Pack Structure Members)
4.3.39 /Zr (Check Pointers)
4.3.40 /Zs (Check Syntax Only)
4.3.41 Giving Options with the CL Environment Variable
4.4 Controlling Stack and Heap Allocation
Chapter 5 QLINK
5.1 Overview
5.2 Invoking QLINK
5.2.1 Command Line
5.2.2 Prompts
5.2.3 Response File
5.2.4 How QLINK Searches for Libraries
5.3 QLINK Memory Requirements
5.4 QLINK Options
5.4.1 /BA (Running in Batch Mode)
5.4.2 /CO (Link for Debugging)
5.4.3 /CP (Set the Maximum Allocation Space)
5.4.4 /DO (Order Segments)
5.4.5 /DS (Load Data at High Address)
5.4.6 /E (Pack Executable Files)
5.4.7 /F (Optimize Far Calls)
5.4.8 /HE (View the Options List)
5.4.9 /HI (Place Executable in High Memory)
5.4.10 /INC (Prepare for ILINK)
5.4.11 /INF (Display Linker-Process Information)
5.4.12 /LI (Include Line Numbers in Map File)
5.4.13 /M (List Public Symbols)
5.4.14 /NOD (Ignore Default Libraries)
5.4.15 /NOE (Ignore Extended Dictionary)
5.4.16 /NOF (Disable Far-Call Optimization)
5.4.17 /NOG (Preserve Compatibility)
5.4.18 /NOI (Employ Case Sensitivity)
5.4.19 /NOL (Suppress Sign-On Banner)
5.4.20 /NON (Order Segments without Nulls)
5.4.21 /NOP (Disable Segment Packing)
5.4.22 /O (Set the Overlay Interrupt)
5.4.23 /PACKC (Pack Contiguous Segments)
5.4.24 /PACKD (Pack Contiguous Data)
5.4.25 /PADC (Pad Code Segments)
5.4.26 /PADD (Pad Data Segments)
5.4.27 /PAU (Pause during Linking)
5.4.28 /SE (Set Maximum Number of Segments)
5.4.29 /ST (Set Stack Size)
5.4.30 /T (Create a .COM File)
5.5 Linker Operation
5.5.1 Alignment of Segments
5.5.2 Frame Number
5.5.3 Order of Segments
5.5.4 Combined Segments
5.5.5 Groups
5.5.6 Fixups
5.6 Using Overlays
5.6.1 Restrictions on Overlays
5.6.2 Overlay-Manager Prompts
7.1 Overview of NMAKE
7.1.1 Using a Command Line to Invoke NMAKE
7.2 NMAKE Description Files
7.2.1 Description Blocks
7.2.2 Comments
7.2.3 Macros
7.2.4 Inference Rules
7.2.5 Directives
7.2.6 Pseudotargets
7.3 Command-Line Options
7.4 Using a Response File to Invoke NMAKE
7.5 The TOOLS.INI File
7.6 In-Line Files
7.7 NMAKE Operations Sequence
Appendix A Exit Codes
A.1 Exit Codes with NMAKE
A.2 Exit Codes with DOS Batch Files
A.3 Exit Codes for Programs
A.3.1 QLINK Exit Codes
A.3.2 LIB Exit Codes
A.3.3 NMAKE Exit Codes
Appendix B Working with QuickC Compiler Memory Models
B.1 Near, Far, and Huge Addressing
B.2 Using the Standard Memory Models
B.2.1 Creating Tiny-Model Programs
B.2.2 Creating Small-Model Programs
B.2.3 Creating Medium-Model Programs
B.2.4 Creating Compact-Model Programs
B.2.5 Creating Large-Model Programs
B.2.6 Creating Huge-Model Programs
B.3 Using the _near, _far, and _huge Keywords
B.3.1 Library Support for _near, _far, and _huge
B.3.2 Declaring Data with _near, _far, and _huge
B.3.3 Declaring Functions with the _near and _far Keywords
B.3.4 Pointer Conversions
Appendix C Hardware-Specific Utilities
C.1 Fixing Keyboard Problems with FIXSHIFT
C.2 Using Hercules Graphics
C.2.1 Support for Cards and Display Characteristics
C.2.2 The MSHERC Driver
C.2.3 Using a Mouse
C.2.4 Setting Hercules Graphics Mode
C.3 The Mouse Driver
The Microsoft(R) QuickC(R) Compiler Tool Kit is a set of utility programs
that you can use to develop your own programs outside the QuickC integrated
environment. These tools include
■ QCL, the Microsoft QuickC compiler, which compiles QuickC source
programs and invokes QLINK (see below) to link object files
■ QLINK, the QuickC linker, which combines object files that you've
created with the Microsoft QuickC compiler (or any other Microsoft
language product) into executable programs
■ LIB, the Microsoft Library Manager, which combines object files into
libraries
■ NMAKE, the Microsoft Program-Maintenance Utility, which maintains
large programs that consist of separate modules
■ The special-purpose utilities, including MSHERC (which provides
support for Hercules(R) graphics adapters) and FIXSHIFT (which fixes a
bug in certain keyboards that makes them incompatible with QuickC and
some other programs)
The Tool Kit provides an alternative to the QuickC environment by letting
you compile and link from the command line. You may find that it's easiest
to use the integrated environment during the early stages of program
development, when you're still tinkering with programs and you need to
compile, run, and debug programs fast. Then, when you're fine-tuning and
maintaining your code, use the tools from the Tool Kit for additional
control and flexibility.
Microsoft documentation uses the term "OS/2" to refer to the OS/2
systems─Microsoft Operating System/2 (MS(R) OS/2) and IBM(R) OS/2.
Similarly, the term "DOS" refers to both the MS-DOS(R) and IBM Personal
Computer DOS operating systems. The name of a specific operating system is
used when it is necessary to note features that are unique to that system.
────────────────────────────────────────────────────────────────────────────
About This Manual
If you're new to Microsoft language products, this book will teach you how
to get the most out of the tools provided in this package. Experienced users
of Microsoft languages will be able to find information about existing
utilities quickly, as well as learn about the utilities provided with QuickC
(including the NMAKE utility and the hardware-specific support utilities
documented in Appendix C, "Hardware-Specific Utilities").
Part 1 of the manual is a tutorial that illustrates the ways you'll use the
QCL, QLINK, LIB, and NMAKE utilities for everyday programming work. Each
chapter describes the most common options of each utility.
Part 2 is a reference to the Tool Kit. Each chapter describes a tool in
detail, showing the syntax of the command line and describing all of the
tool's options and their effects.
Appendixes of this manual list the exit codes returned by each tool, explain
the use of QuickC memory models, describe the MSHERC and FIXSHIFT utilities,
and describe the error messages associated with each tool.
Following the appendixes is a glossary, which defines the terms introduced
in this manual, as well as other C-specific terms you may find helpful.
Elsewhere in This Package
As you're reading this manual, you may want to refer to other manuals or
online documentation for information about other parts of the product. This
manual assumes that you've installed the QuickC compiler software as
described in Up and Running. If you haven't yet installed the software,
install it now.
Read C for Yourself if you're new to C programming and want to learn how to
write C programs. That manual includes an appendix that summarizes the C
language and common C library routines.
Insert the disk titled "Learning the QuickC Environment" and type learn if
you want to learn how to use the QuickC integrated environment. The lesson
titled "Basic Skills" shows how to get online help for any command or option
within the environment or for any part of the C language or run-time
library.
Key to Document Conventions
This book uses the following document conventions:
Examples Description
────────────────────────────────────────────────────────────────────────────
STDIO.H, PATH, C:\BIN, QCL, Uppercase letters indicate file names,
NMAKE, DX, _TEXT segment names, registers, and terms used
at the DOScommand level.
_cdecl, int, printf, alloc_text, Boldface letters indicate C keywords,
#undef, DosCreateThread operators,
language-specific characters, and
library functions, as well as OS/2
functions.
QCL A.C B.C C.OBJ This font is used for examples, user
input, program output, and error
messages in text.
if (expression) Italic letters indicate placeholders for
statement1 information you must supply, such as a
file name. Italics are also occasionally
used for emphasis in the text.
«option» Items inside double square brackets are
optional.
#pragma pack {1 | 2} Braces and a vertical bar indicate a
choice among two or more items. You must
choose one of these items unless double
square brackets surround the braces.
QCL options «file...» Three dots following an item indicate
that more items having the same form may
appear.
while() A column of three dots tells you that
{ part of the example program has been
. intentionally omitted.
.
.
}
CTRL+ENTER Small capital letters are used for the
names of keys on the keyboard. When you
see a plus sign (+) between two key
names, you should hold down the first
key while pressing the second. The
carriagereturn key, sometimes appearing
as a bent arrow on the keyboard, is
called ENTER.
Color Graphics The first time an acronym is used, it is
Adapter (CGA) often spelled out.
"argument" Quotation marks enclose a new term the
first time it is defined in text.
PART I Tool Kit Tutorial
────────────────────────────────────────────────────────────────────────────
The Microsoft QuickC Compiler Tool Kit is divided into two parts. Part 1 is
a tutorial designed to get you started with the QuickC tools. It does not
cover the tools in detail, but instead gives you a "quick start" on the
options and procedures that you are most likely to need. If you are new to
the QuickC Compiler, consult Part 1 to learn how to use the Tool Kit and to
become familiar with the most useful options of each tool. After you've
gained some experience with the tools, turn to Part 2, "Reference to QuickC
Tools," for the "nuts and bolts" of each tool.
Part 1 starts with QCL and LINK, the fundamental tools you must use to
create executable programs outside the QuickC environment. It goes on to the
Library Manager (LIB), with which you can create libraries of compiled code.
The part concludes with NMAKE, a program-maintenance utility that helps you
automate the process of rebuilding software.
Version 2.5 of the Microsoft QuickC Compiler environment is designed for
maximum convenience and efficiency. If you prefer, however, you can also
create programs from the DOS command line. The QuickC Compiler provides two
programs for this purpose: QCL and QLINK.
This chapter introduces the basic concepts and the most common options of
the QCL and QLINK commands. See Chapter 4, "QCL Command Reference," in Part
2 of this manual for a complete description of all the QCL options (listed
alphabetically). See Chapter 5, "QLINK," also in Part 2, for a complete
explanation of how QLINK works.
1.1 Compiling and Linking: An Overview
The first step in creating a QuickC program is to enter the source code
using an editor and save it in a file. This file is known as a C "source
file." You can enter separate parts of the program in different source files
and compile these source files separately.
Once you've saved your C source file(s), two steps are required to convert
it to an executable file:
1. Compiling. During this step, the QuickC compiler converts the C source
files to object files. An object file contains binary code but is not
yet in execut-able form.
2. Linking. During this step, the linker takes the object files created
during compilation, combines them with standard libraries plus any
other object files and libraries you specify, and creates an
executable file that can be run under DOS.
You can use the QCL command to perform both compiling and linking. On the
QCL command line, give the names of any C source files that you want to
compile and the names of any additional object files or libraries that you
want to link. As an example, consider the following simple command:
QCL SAMPLE.C EXAMPLE.C
This command tells QCL to compile and link the source files SAMPLE.C and
EXAMPLE.C. The QCL command performs these two steps:
1. QCL compiles the source files SAMPLE.C and EXAMPLE.C and creates
object files. The object files created by QCL have the same base name
as the source files, plus the extension .OBJ.
2. The linker links the object files that were created in the compiling
step with the default library, SLIBCE.LIB. (QLINK uses this particular
library because there are no command-line options that specify
otherwise. See Section 4.3.1, "/A Options," for the names of the other
possible libraries.) QLINK then creates the final executable file,
SAMPLE.EXE, giving it the base name of the first source file specified
on the command line (SAMPLE), plus the extension .EXE.
The two steps described above are illustrated in Figure 1.1.
(This figure may be found in the printed book.)
Figure 1.1 and the command it illustrates give a simple demonstration of
what QCL can do. You can also use QCL to compile and link any combination of
source files, object files, and additional libraries. The following section
explains the syntax of the QCL command, which you can use to control more
complex compile/link operations.
1.2 Using the QCL Command
The QCL command, which you'll use for most compiling and linking operations,
has the following format:
(This figure may be found in the printed book.)
The items in italics are different pieces of input (described below) that
you must give on the QCL command line:
■ The options are QCL options, which control some aspect of the
compiling or linking process. They may appear anywhere on the command
line and in most cases affect any files that appear later on the
command line. The most commonly used QCL options are described in
Section 1.4, "Controlling Compiling and Linking with QCL Options." See
Chapter 4, "QCL Command Reference," for complete information on all
QCL options.
■ The sourcefiles are the names of the C source files that you are
compiling. Normally, these file names have .C extensions.
■ The objfiles are the names of additional object files that you want to
link into your program. QCL compiles the source files, then links the
resulting object files with objfiles. For example, given the command
QCL MAIN.C AUX.OBJ
QCL compiles MAIN.C, creating the object file MAIN.OBJ. QCL then tells
the linker to link MAIN.OBJ and AUX.OBJ to create the executable file
named MAIN.EXE.
If you give a file name with any extension other than .C or .LIB, or
with no extension, QCL assumes you are giving it the name of an object
file. For example, in the command
QCL OBJECT1 OBJECT2.OBJ
the QCL command assumes OBJECT1 has the .OBJ extension and tells the
linker to link OBJECT1.OBJ and OBJECT2.OBJ.
■ The libraries are the names of libraries that you want to link with.
These names must have .LIB extensions.
Ordinarily, you don't need to give a library name unless your program
calls functions that are stored in libraries other than the standard
combined C libraries (which you created during installation). If you
use libraries created
by a company other than Microsoft, or if you have created a private
library of functions and your program calls functions in this library,
you must give the private-library name on the QCL command line. For
example, the command
QCL MAIN.C MYLIB.LIB
tells QCL to compile MAIN.C, creating the object file MAIN.OBJ. Then
QCL tells the linker to link MAIN.OBJ with functions in the default
combined library SLIBCE.LIB and the MYLIB.LIB library given on the
command line.
■ The linkoptions are linker options, which control some aspects of the
linking process. Linker options are described in Section 1.4.10,
"Controlling the Linking Process."
■ If you're not sure that your program will fit in available memory, you
can indicate that certain parts of the program will become "overlays."
That is, they will be stored on disk and read into
memory─overlaid─only when needed. To specify overlays, enclose the
modules you want to overlay in parentheses on the QCL command line.
For example, the command
QCL RESIDNT.C (ONCALL.C) MAIN.C
creates a program named RESIDNT.EXE with an overlay module named
ONCALL.OBJ. Whenever control passes to ONCALL.OBJ, it is read into
memory from disk. (See Section 5.6, "Using Overlays," for more
information about overlays and restrictions on their use.)
1.3 Specifying File Names
A DOS file name has two parts: the "base name," which includes up to eight
characters before the period (.), and the "extension," which includes the
period and up to three characters following the period. The extension
identifies the type of the file. The QCL command uses the extension of each
file name to determine how to process the corresponding file, as explained
in Table 1.1.
Uppercase and lowercase
In file names, any combination of uppercase and lowercase letters is legal.
For example, SHUTTLE.C and Shuttle.c represent the same file.
Path names
Any file name can include a path name. When a file name includes a path
name, QCL assumes the file to be in that path. You can supply either a full
path name or a partial path name. A full path name includes a drive name and
one or more directory names. A partial path name is the same as a full path
name but omits the drive name, which QCL assumes to be the current drive.
If you don't give a path name, QCL assumes that all source and object files
given on the command line are in the current directory.
Examples
QCL MAIN.C AUX.C OBJECT1.OBJ OBJECT2 OBJECT3.MOD
This command line compiles the files MAIN.C and AUX.C, creating object files
named MAIN.OBJ and AUX.OBJ. These object files are then linked with the
object files OBJECT1.OBJ, OBJECT2.OBJ, and OBJECT3.MOD to form an executable
file named MAIN.EXE (since the base name of the first file on the command
line is MAIN). Note that QCL assumes the extension .OBJ for OBJECT2 because
no extension is given on the command line.
QCL TEAPOT.C \MSG\ERROR C:\GRAPHICS\GRAPHICS.LIB
This command line tells QCL to compile the file TEAPOT.C and to link the
resulting object file with \MSG\ERROR.OBJ and the library GRAPHICS.LIB. QCL
assumes the extension .OBJ for the file \MSG\ERROR because none was
specified. It looks for the library in the \GRAPHICS directory on drive C:.
Table 1.1 Interpretation of File Extensions
╓┌──────────────────────────────┌─────────────┌──────────────────────────────╖
Extension Assumed Type Processing
────────────────────────────────────────────────────────────────────────────
C C source QCL compiles the file.
OBJ Object QCL tells the linker to link
the file.
LIB Library The linker links this library
with the object files QCL
created from source files and
the object files given on the
command line.
Any other extension or none Object QCL tells the linker to link
the file. You must end the
file name with a period (.)
if the file name has no
Extension Assumed Type Processing
────────────────────────────────────────────────────────────────────────────
if the file name has no
extension. Otherwise, QCL
assumes the extension .OBJ.
1.4 Controlling Compiling and Linking with QCL Options
The QCL command offers a variety of options that control the compiling and
linking processes and modify the files created during each stage. For
example, you can specify QCL options to rename output files, to control the
operation of the QuickC preprocessor, to take advantage of an 80286
processor or a math coprocessor, or to optimize your program for speed or
size.
QCL options can begin with either a forward slash ( / ) or a dash (-). In
this book, the slash is used.
────────────────────────────────────────────────────────────────────────────
Important
Except as noted, QCL options are case sensitive, so you must use the exact
combination of uppercase and lowercase letters shown in this book.
────────────────────────────────────────────────────────────────────────────
Some QCL options require arguments. For example, you may be required to give
a number or a file name as part of a QCL option. For some options, you must
put a space between the option and the argument; for others, you must place
the argument immediately after the option. The description of each option
gives its exact syntax.
The following sections list the most commonly used QCL options by type. See
Chapter 4, "QCL Command Reference," for a complete list of QCL options or
for more information about the effects of an option described in this
chapter.
Help with QCL options
If you need help with QCL options, use the following command:
QCL /HELP
This command displays a list of commonly used QCL options with a brief
description of each option. Unlike other QCL options, /HELP is not case
sensitive; you can type any combination of lowercase and uppercase letters.
1.4.1 Compiling without Linking
When you compile with the /c option, QCL compiles the source files you give
on the command line but ignores any object files or libraries that you give
on the command line. Because QCL does not invoke the linker when you give
this option, it does not create an executable file.
You can use this option in the following cases:
■ To compile separate modules that you want to put in a library using
the LIB utility (described in Chapter 2 of this book)
■ To link in a separate step as described later in this chapter (for
example, in an NMAKE file)
Example
QCL /c SPELL.C THESRS.C
The example above compiles the C source files SPELL.C and THESRS.C, creating
the object files SPELL.OBJ and THESRS.OBJ. Because the /c option keeps QCL
from invoking the linker, this command doesn't create an executable file.
1.4.2 Compiling Only Modified Functions
The /Gi option allows you to compile programs much faster than usual. It
speeds compilation by telling QCL to compile only the parts of each C source
file that have changed since the file was last compiled. This process is
called "incremental compilation."
Information about the incremental compilation of each source file is
maintained in an MDT (Module Description Table) file. One MDT file can
contain this information for more than one source file.
If you give a file-name argument following the /Gi option, the compiler
writes the change information for all the source files into that single MDT
file. Do not put spaces between the /Gi option and the file name.
If you specify the /Gi option without a file name, the compiler creates an
MDT file for each C source file that you give on the command line. Each MDT
file has the base name of the source file and the .MDT extension.
Generally, when you compile with /Gi, only the changed functions in each C
source file are recompiled. The entire file is recompiled only if a change
affects the entire program.
See Section 4.3.16 in Part 2, "Reference to QuickC Tools," for details about
incremental compilation and the /Gi option.
Example
QCL /GiASC.MDT alpha.c num.c
The example above compiles the changed portions of the files ALPHA.C and
NUM.C. It creates a single .MDT file named ASC.MDT into which it writes
change information for both source files.
1.4.3 Optimizing Programs
"Optimizing" a program is the process of making the program, or a part of
the program, as fast or as small as possible. The following QCL options can
help with this process:
Option Effect
────────────────────────────────────────────────────────────────────────────
/O, /Ot Optimizes the program for execution time
rather than code size. The compiler
makes the executable file faster, but it
does not make the file size as small as
possible.
/Ol Optimizes loops in your program. This
option makes the executable file run
faster.
/Gs Turns off stack-checking routines in
your program. This option reduces the
size of the executable file, but it may
cause stack-overflow errors to go
undetected.
/Ox Performs all possible speed
optimizations. This option combines the
effects of the /Ot, /Ol, and /Gs
options.
/Od Does not optimize your program. This
option speeds compilation, although it
may result in a slightly slower
executable file.
You may combine the /O options on the command line, specifying more than one
letter following /O. For instance, /Olt optimizes loops and execution time.
If the letters conflict, QCL uses the last one in the list.
1.4.4 Naming Output Files
Use the following options to name the object and executable files that QCL
creates. Note that file names must immediately follow the options, with no
intervening spaces.
Option Effect
────────────────────────────────────────────────────────────────────────────
/Foobjfile Gives the name objfile to the object
file. You can give more than one /Fo
option; each option applies to the next
C source-file name on the command line.
For example,
QCL /FoOBJ1 SRC1.C SRC2.C
compiles SRC1.C, creating an object file
named OBJ1.OBJ, then compiles SRC2.C,
creating an object file named SRC2.OBJ.
If you give objfile without an extension,
QCL automatically appends the .OBJ
extension to the file name. If you give
a complete path name with objfile, QCL
creates the object file in that path.
For example,
QCL /Fo\MODS\OBJ1.OBJ SRC1.C
compiles SRC1.C, creating an object file
named OBJ1.OBJ in the \MODS directory.
If you give only a drive or directory
specification, the specification must
end with a backslash ( \ ) so that QCL
can distinguish it from a file name.
/Feexefile Gives the name exefile to the executable
file. If you give exefile without an
extension, QCL automatically appends the
.EXE extension to the file name. If you
give a complete path name with exefile,
QCL creates the executable file in that
path. If you give a path specification
without a file name, the path
specification must end with a backslash
( \ ) so that QCL can distinguish it
from a file name.
If you don't tell it otherwise, QCL names output files as follows:
Type of File Default
────────────────────────────────────────────────────────────────────────────
Object Same base names as the original C source
files with extensions of .OBJ. For
example, if you compile a C source file
named LEX.C, QCL creates an object file
named LEX.OBJ.
Executable Same base name as the first file name on
the command line plus an extension of
.EXE. For example,
QCL LEX.C GENCOD.OBJ OPTIMIZ
creates an executable file named LEX.EXE
by compiling LEX.C (creating LEX.OBJ),
then linking LEX.OBJ, GENCOD.OBJ, and
OPTIMIZ.OBJ.
1.4.5 Turning Off Language Extensions
QuickC supports keywords and syntax that are additions to the standard C
language. The /Za option tells the compiler to treat such Microsoft-specific
keywords as ordinary identifiers and to display error messages if your
programs use any other extended-language features.
Compile with the /Za option if you plan to port your programs to
environments that don't recognize Microsoft extensions to the C language, or
if you want to ensure that your programs are strictly compatible with the
ANSI (American National Standards Institute) definition of the C language.
Microsoft extensions include the _near, _far, _huge, _cdecl, _fortran, and
_pascal keywords, as well as several usages of standard C constructs that
are not defined in the ANSI standard. (See Section 4.3.35, "/Ze, /Za," in
Part 2 for more information about these extensions.)
1.4.6 Debugging and Syntax Checking
Several QCL options are useful when you want the compiler to check the
syntax of your program, or when you want to track down logic errors using
the debugger built into the QuickC environment (or other Microsoft
debuggers). These options fall into three categories:
1. Checking syntax
2. Setting warning levels
3. Compiling for a debugger
1.4.6.1 Checking Syntax
If you want to make sure that your program is free from syntax errors
without compiling and linking the program, compile it with the /Zs option.
This option tells the QCL command to display error messages if your program
has syntax errors. QCL doesn't create object or executable files.
1.4.6.2 Setting Warning Levels
You may get warning messages during compilation if your program has problems
that aren't serious enough to stop the compiling process. You can easily
identify a warning message because it begins with the word "warning" and has
"C4" as the first two characters in the error number.
The "warning level" options, /w and /W0 through /W4, allow you to suppress
warning messages for certain classes of problems. In general, the lower the
warning level, the less strict the compiler is about flagging possible
errors in your program. You might want to use a lower warning level if
you're intentionally using the flexibility of C in some operations and you
want to suppress warnings about these operations.
The warning-level options are described below:
Option Effect
────────────────────────────────────────────────────────────────────────────
/W0, /w Turns off all warning messages.
/W1 Displays severe warning messages. (This
is the level of warnings you get by
default.)
/W2 Displays all /W1 warnings plus warnings
for problems such as functions without a
declared return type, functions that
have a return type other than void and
don't have a return statement, and data
conversions that cause loss of precision.
/W3 Displays all /W2 warnings, plus warnings
for function calls that precede their
function prototypes in the source code.
/W4 Displays all /W3 warnings, plus warnings
for any non-ANSI constructs. The /W4
option is similar to the /Za option,
which gives error messages and aborts
the compilation if non-ANSI features are
used.
/WX Treats all warnings as fatal errors. If
there are any warning messages, the
compilation aborts and no object file is
produced.
Appendix D lists all warning messages in order of error number. The
description of each message indicates the warning level that must be set in
order for the message to appear.
1.4.6.3 Compiling for a Debugger
You must compile your program with one or more of the following QCL options
if you plan to debug it within the QuickC environment or with another
Microsoft debugger:
Option Effect
────────────────────────────────────────────────────────────────────────────
/Zi Puts information needed for debugging
into the program. Use /Zi if you plan to
debug your program with the QuickC
debugger or with the Microsoft
CodeView(R) window-oriented debugger
provided with other Microsoft language
products.
/Zd Puts limited symbolic information in the
object file. Use /Zd if you plan to
debug your program with SYMDEB, the
Microsoft Symbolic Debug Utility that
was shipped with earlier versions of
Microsoft language products.
/Zr Checks for null or out-of-range pointers
in your program. Optional if you plan to
debug with the QuickC debugger.
1.4.7 Controlling the Preprocessor
The QCL command provides several options that control the operation of the
QuickC preprocessor. These options allow you to define macros and manifest
(symbolic) constants from the command line, change the search path for
include files, and stop compilation of a source file after the preprocessing
stage to produce a preprocessed source-file listing.
1.4.7.1 Defining Constants
The C preprocessor directive #define defines a name for a constant or for C
program text. Wherever the name appears in your program, the preprocessor
substitutes the text you've defined for that name.
You can use the /D option to define constants from the QCL command line.
This option has the form
/Didentifier=string
or
/Didentifier=number
The identifier is the name you're defining; string or number is the text or
numeric value that is substituted for the name. The string must be in double
quotation marks if it includes spaces.
You can leave off the equal sign and the string or number. If you do, the
identifier is defined and its value is set to 1. You can use this format
when you need to define an identifier but do not care what its value is. For
example, /DCREATE defines an identifier named CREATE and sets it equal to 1.
If you've defined a number for identifier, you can "turn off" the definition
by using the following form of the /D option:
/Didentifier=
When you compile with this form, the identifier is no longer defined within
your program and no value is substituted for it.
QCL allows you to define up to 15 constants using the /D option for each
constant. You may be able to define as many as 20, depending on the other
options you specify. (See Section 1.4.7.4, "Removing Predefined
Identifiers," for more information about the number of constants you are
allowed to define.)
1.4.7.2 Searching for Include Files
The QuickC preprocessor directive
#include filename
tells the QuickC preprocessor to insert the contents of filename in your
source program, beginning at the line where the directive appears. Include
files pro-vided with Microsoft QuickC contain prototypes of standard C
library functions and the constants used by these functions. If filename is
enclosed in angle brackets (< >), the preprocessor looks for the file in the
directories given by the INCLUDE environment variable. If filename is
enclosed in quotation marks (" "), the preprocessor looks for the file first
in the current directory and then in the directories specified by the
INCLUDE variable. (Enter the SET command at the DOS prompt to see the
INCLUDE variable and the directories it specifies.)
Use the following options to override the usual search order without
changing the value of the INCLUDE variable:
Option Effect
────────────────────────────────────────────────────────────────────────────
/X Tells the preprocessor not to search for
include files in the directory given by
the INCLUDE variable.
/I directory Tells the compiler to search the given
directory for include files before it
searches the directories given by the
INCLUDE environment variable. You can
give more than one /I option, each
specifying a directory. Directories are
searched in the order in which they
appear on the command line.
1.4.7.3 Creating Preprocessor Listings
If you want to see output from the QuickC preprocessor, give one or more of
the following options on the QCL command line:
Option Effect
────────────────────────────────────────────────────────────────────────────
/E Writes preprocessor output to the
standard output device (your screen,
unless you redirect output to another
device or to a file). The /E option also
inserts #line directives in the output.
The #line directives renumber the lines
of the preprocessed file so that, if you
recompile the preprocessed file, the
errors generated during later stages of
processing refer to the original source
file rather than to the preprocessed
file.
/P Writes preprocessor output to a file and
inserts #line directives in the output
file. The preprocessor gives the file
the base name of your C source file and
an extension of .I.
/EP Writes preprocessed output to the
standard output device but does not
insert #line directives.
/C Leaves comments in the preprocessed
output. Normally, the preprocessor
strips comments from the source file.
This option has an effect only if you
also give the /E, /P, or /EP option.
1.4.7.4 Removing Predefined Identifiers
The QuickC compiler automatically defines certain identifiers, which
represent conditions such as the current operating system or memory model.
Your programs may use these identifiers along with the QuickC preprocessor
directives #if, #ifdef, #ifndef, #else, #elif, and #endif to tell the
compiler to "conditionally compile" portions of the program. For example,
the #ifdef directive tells the compiler to compile subsequent code only if a
given identifier is defined. Similarly, the #ifndef directive tells the
compiler to compile subsequent code only if a given identifier is not
defined. (For more information about preprocessor directives, see Chapter 7,
"Preprocessor Directives," in C For Yourself.)
The predefined identifiers are as follows: _QC, MSDOS, M_I86, M_I86mM,
M_I8086, M_I286, NO_EXT_KEYS, and _CHAR_UNSIGNED. (For more information on
how and when these identifiers are defined, see Table 4.5, "Predefined
Names," in Section 4.3.31.) If you don't use these identifiers for
conditional compilation, you might want to remove their definitions from the
program. For each predefined identifier that you remove, you can define an
additional identifier (over the default limit of 15) with the /D option on
the QCL command line.
The following options turn off predefined identifiers:
Option Effect
────────────────────────────────────────────────────────────────────────────
/U identifier Turns off the definition of identifier
/u Turns off the definition of all
predefined identifiers
1.4.8 Compiling for Specific Hardware
QuickC creates executable programs that run on any processor in the 8086
family, including the 8086/8088, 80186, 80286, 80386, and 80486.
If your programs will always run on machines with 80186 or 80286 or higher
processors, or on machines with coprocessors, you can compile your programs
with the following options to take advantage of the specific hardware
configuration:
Option Effect
────────────────────────────────────────────────────────────────────────────
/G1 Uses the 80186 instruction set for your
program. You cannot run the program on
machines with 8088 or 8086 processors.
/G2 Uses the 80286 instruction set for your
program. You cannot run the program on
machines with 8088, 8086, or 80186
processors.
/FPi87 Handles math for floating-point types (
float and double) by generating
instructions for an 8087 or 80287 math
coprocessor. This reduces the size of
your program; however, the program must
be run on a system with a coprocessor
present.
The /G2 and /FPi87 options are the most commonly used options for
hardware-specific compilation, but others are available. See Sections 4.3.12
and 4.3.13 for details.
1.4.9 Choosing Memory Models
The "memory model" your program uses determines how many 64K (kilobytes)
segments the compiler allocates for its data and code. Ordinarily, you don't
need to choose the memory model explicitly if your program's code can fit
into one 64K segment and your program's data can fit into one 64K segment.
This memory allocation, called the small memory model, is the default used
by the QCL command.
If your program exceeds the default limit for code or data, you must use one
of the other memory models. The following list summarizes the options for
the memory model:
Option Effect
────────────────────────────────────────────────────────────────────────────
/AT Tiny model: provides one 64K segment for
both data and code. The compiler
produces a .COM file instead of a .EXE
file.
/AS Small model: provides one 64K segment
for data and one 64K segment for code.
No one data item can exceed 64K. This is
the most efficient model for QuickC
programs. QCL uses this option
automatically if you don't give a
memory-model option, so you never need
to give this option explicitly.
/AM Medium model: provides one 64K segment
for data and multiple 64K segments for
code. No one data item can exceed 64K.
This is the most efficient model if your
program exceeds the 64K default limit
for code.
/AC Compact model: provides multiple 64K
segments for data and one 64K segment
for code. No one data item can exceed
64K. This is the most efficient model if
your program exceeds the 64K default
limit for data.
/AL Large model: provides multiple 64K
segments for data and for code. No one
data item can exceed 64K.
/AH Huge model: same as large model, except
that individual data items can be larger
than 64K.
Although memory models give you additional flexibility in dealing with large
programs, you must use them with care to avoid problems in your programs.
See Section 4.3.1 or Appendix B for further information about the use of
memory models.
1.4.10 Controlling the Linking Process
Several QCL options control the linking process rather than the compiling
process. You've already encountered one of these options: the /Fe option,
which renames the executable file. Here are the others:
Option Effect
────────────────────────────────────────────────────────────────────────────
/Fm «mapfile» Creates a map file showing program
segments in order of appearance in the
program. If you give mapfile without an
extension, QCL automatically appends the
.MAP extension to the file name. If you
give a complete path name with mapfile,
QCL creates the map file in that path.
For example,
QCL /Fm\MODS\MAP1.MAP SRC1.C
compiles and links SRC1.C, creating a
map file named MAP1.MAP in the \MODS
directory. If the path specification
lacks a file name, it must end with a
backslash ( \ ) to distinguish it from a
file name.
The mapfile argument is optional; if you
don't specify a new name, the linker
gives the map file the same base name as
the executable file, with an extension
of .MAP. For example,
QCL /Fm MOD1.C MOD2.C
creates an executable file named
MOD1.EXE and a map file named MOD1.MAP.
/F number Sets the stack size to the given number
of bytes. The number may be in decimal,
octal, or hexadecimal. (As in C programs,
octal numbers start with the prefix 0
and hexadecimal numbers with the prefix
0x.) If you don't give this option, the
executable file uses a 2K stack. Use
this option if your program gets
stack-overflow errors at run time.
See Sections 4.3.8 - 4.3.10 for detailed information on these options and on
map files.
The /link option
Another way of controlling the linking process is to use the /link option on
the QCL command line. The /link option allows you to specify QLINK command
options─not QCL options─without invoking the linker separately. On the QCL
command line, the /link option must follow the source and object files and
all QCL options. QCL passes directly to the linker the options that follow
/link. These options are described in Section 1.5.2, as well as in Section
5.4.
Example
QCL /FPi87 /Fm SRC1.C SRC2 /link /INF
In the example, the /Fm and /FPi87 options apply to the QCL command and the
/INF option applies only to the linker. As a result of this command line,
QCL compiles SRC1.C to run on an 8087 or 80287 processor, then passes
SRC1.OBJ and SRC2.OBJ to the linker. The /Fm option to QCL causes the linker
to create a map file named SRC1.MAP. The /INF option, which applies only to
the linker and not to QCL, causes the linker to display information about
the linking process.
1.4.11 Other QCL Options
QCL supports a large number of options besides the ones already described,
which control all aspects of the compilation process. Some of the more
commonly used options are described below:
Option Effect
────────────────────────────────────────────────────────────────────────────
/Gc Calling-convention option. Uses the
FORTRAN/Pascal naming and calling
conventions for functions in the program.
Compile with this option if you want to
call routines that use the Microsoft
Pascal or Microsoft FORTRAN calling
conventions or if you need to save space
in the executable file. (See Section
4.3.14 for more information about the
effects of this option.)
/Gt«number» Threshold option. Tells the compiler to
allocate data items larger than number
in a new data segment. If you give this
option with no number, QCL allocates
items larger than 256 bytes in their own
segment. If you don't give this option,
QCL allocates items larger than 32,767
bytes in their own segment.
This option applies if you compile with
the compact (/AC), large (/AL), or huge
(/AH) memory model. See Appendix B for
more information about memory models and
allocation.
/NTtextsegname Name-text-segment option. Assigns the
given name to the text segment. The
space is optional between /NT and
textsegname. The text segment contains
the program code for the entire program
(if you compile with the /AS option, the
/AT option, the /AC option, or no
memory-model option) or for the module
you are compiling (if you compile with
the /AM, /AL, or /AH option).
/Zl Library options. Tells the compiler not
to put the name of the appropriate
combined library in the object file. Use
this option to compile modules that you
want to put in a library with the LIB
utility.
/Zp«number» Pack option. Stores structure members
after the first on number-byte
boundaries. The number argument, if
given, may be 1, 2, or 4; if it isn't
given, QCL assumes a value of 2. This
option may reduce the size of executable
files, although it may also slow program
execution.
See Section 4.3 for descriptions of all the QCL options.
1.5 Invoking the Linker Directly: The QLINK Command
If you are building a large program composed of many source files, you may
prefer to compile the source files in one step, and then link the resulting
object files in a separate step. For example, in the first step, you would
compile your C source files as shown below:
QCL /c SOURCE1.C SOURCE2.C
Then, in the second step, you would link the resulting object files, plus
any additional object files or libraries, as shown below:
QCL SOURCE1 SOURCE2 GRAPHICS.LIB
As illustrated in the second step, if you give only object files or
libraries on the QCL command line, the QCL command simply passes the object
files and libraries to the linker.
Instead of using the QCL command to link, you can invoke the linker directly
by entering the QLINK command. Because the linker prompts you for any input
it needs, using QLINK makes it easier to specify file names and options; you
don't need to enter everything on the command line, although you may do so
if you wish.
The remainder of this section explains how to use the QLINK command to link
object files and libraries.
1.5.1 Giving Input to the QLINK Command
The simplest way to invoke the linker directly is to give the command
QLINK
If you don't give any other information on the command line, QLINK prompts
you for input. The following list shows how to respond to each prompt:
Prompt Response
────────────────────────────────────────────────────────────────────────────
Object Modules: The names of all object files that you
want to link, separated by plus signs.
If all the names do not fit on one line,
type a plus sign as the last character
on the line. QLINK repeats the prompt on
the next line, and you can type
additional object-file names.
Type a library name in response to this
prompt if you want to include the entire
library in the executable file. Make
sure the library name has an extension
of .LIB. (If you type the library name
in response to the "Libraries:" prompt
below, QLINK places in the executable
file only the library modules that are
called in your source files.)
Run File: The name of the executable file that you
want to create. If you press ENTER
without typing a name, QLINK uses the
base name of the first object file you
gave plus the extension .EXE. This name
is shown in brackets in the prompt.
List File: The name of the map file, which shows
segments in your program. If you press
ENTER without typing a name, QLINK
doesn't create a map file. If you enter
a name without an extension, QLINK adds
the .MAP extension automatically.
Libraries: The names of libraries other than the
standard combined libraries that you
want to link with the object files. If
you enter a library name without an
extension, QLINK assumes the extension
.LIB. If you enter more than one library
name, put a plus sign between each
library name and the next.
You can supply linker options as part of the response to any prompt. See
Section 1.5.2, "QLINK Options," for a list of commonly used options.
Input on the command line
If you prefer, you can give all your input to QLINK on the command line. The
QLINK command line has the form shown below:
(This figure may be found in the printed book.)
Commas must appear as shown above to separate the names of the different
files. You may type a semicolon to terminate the command line anywhere after
the list of object files. The semicolon tells QLINK to use defaults for the
remaining files. QLINK options may appear anywhere on the command line.
The prompts previously described correspond to the command line as follows:
"Object Modules" is equivalent to objfiles, "Run File" to exefile, "List
File" to mapfile, and "Libraries" to libraries.
Input in a response file
QLINK allows you one other alternative for providing input. You can enter
responses for all prompts in a file, then invoke QLINK with the following
command:
QLINK @responsefile
Replace responsefile with the name of the file that contains your responses.
The responses should look the same as if you were typing them in response to
prompts. For example, type all object-file names on the first line, the
executable-file name on the second line, and the map-file name on the third
line. Use a plus sign at the end of a line to continue a response on the
next line. Leave a blank line in the file if you want QLINK to use the
default for a prompt. Place QLINK options at the end of any response or
place them on one or more separate lines.
1.5.2 QLINK Options
QLINK options allow you to control the operation of the linker. If you're
using the QCL command to link, give these options after the /link option on
the command line. If you're using the QLINK command to link, these options
may appear anywhere on the command line. QLINK options must be preceded by a
slash.
Not all QLINK options are applicable to QuickC programs. Some options are
useful only for assembly-language programs. This section describes only the
options that are useful for QuickC programs. See Chapter 5, "QLINK," for a
complete list of options.
Case sensitivity
QLINK options are not case sensitive, so you can type any combination of
uppercase and lowercase letters for each option.
Abbreviations
Because some QLINK options have long names, QLINK allows you to abbreviate
each name. The abbreviation must include enough continuous letters to
distinguish the option from others. Letters that you can leave off are
surrounded by brackets in the following sections. In general, this book
refers to QLINK options by their shortest possible abbreviations.
Numerical parameters
Some QLINK options take numbers as parameters. You may specify the numbers
in decimal, hexadecimal, or octal. As in C programs, hexadecimal numbers are
identified by the prefix 0x and octal numbers by the prefix 0.
Help with QLINK options
If you need help with QLINK options, use the following command:
QLINK /help
The linker responds by displaying a list of all the available options.
1.5.2.1 Controlling the Linking Process with Options
Use the QLINK options described below to control the linking process:
Option Effect
────────────────────────────────────────────────────────────────────────────
/BA«TCH» Tells the linker to continue processing
if it can't find one of the files you've
given, rather than stop processing and
prompt you. Also prevents QLINK from
displaying its program banner and
echoing the contents of response files
on standard output.
Use this option in batch files or NMAKE
description files if you're building
large executable files and don't want
the linker to stop processing if it
can't find a file it needs.
/INC«REMENTAL» Prepares the program for subsequent
incremental linking, which links only
the object files that have changed since
the last link. This is significantly
faster than regular linking. The /PADC
and /PADD options, used for padding code
and data, should also be specified when
you use this option. This option is
incompatible with the tiny memory model
and with the /E (Pack .EXE file) option.
/INF«ORMATION» Tells the linker to display information
about the linking process, including the
linking phase and the name of each
object file being linked.
/M«AP» Includes a full public-symbol listing in
the map file.
/NOD«EFAULTLIBRARYSEARCH» «: Tells the linker not to search the
filename» standard C combined libraries to find C
library functions. If you use this
option, you should explicitly specify
the name of a standard combined library.
/PAU«SE» Tells the linker to pause before it
creates the executable file and to
display a message. This allows you to
insert a new disk to hold the executable
file.
If you're running on a machine without a
hard disk, you might want to create the
executable file on a different removable
disk. In this case, you would swap the
current disk for the new disk before
creating the executable file. If QLINK
displays the message
Temporary file tempfile has been
created.
Do not change diskette in drive letter.
you should terminate your link session,
copy the temporary file named tempfile
to the disk where you want to create the
executable file, and enter the QLINK
command again.
1.5.2.2 Optimizing the Executable File
The following QLINK options make the executable file faster, smaller, or
both:
Option Effect
────────────────────────────────────────────────────────────────────────────
/E«XEPACK» Compresses the executable file. This
option reduces the program's size and
load time. However, you cannot use the
QuickC or CodeView debugger to debug the
program.
/F«ARCALLTRANSLATION» Reduces the size of the executable file
and increases its speed by optimizing
far calls to procedures in the same
segment as the calling procedure.
/PACKC«ODE»«:number» Given with the /F option, improves the
efficiency of medium-, large-, and
huge-model programs by grouping
neighboring code segments.
/PACKD«ATA»«:number» Improves the efficiency of compact- and
large-model programs by grouping
neighboring data segments.
1.5.2.3 Modifying the Executable File
You can use the following QLINK options to modify the executable file (for
example, to specify the maximum number of segments or set the stack size):
Option Effect
────────────────────────────────────────────────────────────────────────────
/CP«ARMAXALLOC»:number Sets the maximum number of 16-byte
paragraphs needed by the program to
number. The number may be any decimal,
octal, or hexadecimal number in the
range 1- 65,535 decimal.
/SE«GMENTS»:number Sets the maximum number of segments a
program can have to number. The number
may be any value in the range 1-3,072
decimal. If you don't give this option,
a program may have no more than 128
segments.
/ST«ACK»:number Sets the stack size to number bytes. The
number may be any decimal, octal, or
hexadecimal number in
the range 1- 65,535 decimal. If
you don't give this option, the stack
is 2K.
1.5.2.4 Other QLINK Options
The QLINK options described in this chapter are those most typically used
when linking QuickC programs. The linker supports additional options,
including several that apply only to assembly-language programs. For
complete information on all QLINK options, see Chapter 5, "QLINK," in Part 2
of this manual.
Chapter 2 Maintaining Software Libraries with LIB
────────────────────────────────────────────────────────────────────────────
The Microsoft Library Manager (LIB) lets you create and maintain object-code
libraries. You can use the library manager to
■ List the contents of a library
■ Modify the contents of an existing library
■ Copy object code from the library
■ Create a new library
This chapter gives you an introduction to libraries and then explains how to
perform each of the tasks listed above.
2.1 Why Use a Library?
Object modules
An "object-code library" is an organized collection of object code; that is,
a library contains functions and data that are already assembled or compiled
and are ready for linking. The structure of a library supports the mass
storage of common procedures─procedures called by a variety of programs.
Each library consists of components. These components, called "object
modules" (or sometimes just "modules"), can be added, deleted, changed, or
copied. When you give the linker a library as input, the linker efficiently
scans the library and uses only the modules needed by the program.
Object-code libraries are typically used for one of three purposes:
1. To support high-level languages. Languages, including C, BASIC, and
FORTRAN, perform input/output and floating-point operations by calling
standard support routines. Because the support routines are available
in a library, the compiler never needs to regenerate code for these
routines. Libraries that contain standard support routines are called
"standard libraries."
2. To perform complex and specialized activities, such as data-base
management or advanced graphics. Libraries containing such routines
are often sold by third-party software vendors or are provided by the
makers of the compiler (in the case of graphics libraries for the
Microsoft QuickC Compiler).
3. To support your own work. If you have created routines that you find
useful for a variety of programs, you may want to put these routines
in a library. That way, these routines do not need to be recoded or
recompiled. You save development time by using work you have already
done.
2.2 The LIB Command
The LIB command has the form shown below:
(Please refer to the printed book.)
(This figure may be found in the printed book.)
The items in italics are different pieces of input (described below) that
you must give on the LIB command line:
■ The oldlibrary field gives the name of a library. Object-code
libraries typically have names that end with .LIB. You specify a
library in this field whenever you use LIB.
■ The options field specifies one or more LIB options. For most tasks,
you won't need to use any of these options. The options are described
in Chapter 6, "LIB," in Part 2 of this manual.
■ The commands field gives the commands that modify the contents of the
library. Commands are described in Section 2.4, "Modifying the
Contents of a Library."
■ The listfile field specifies a file into which LIB puts a list of the
library's contents. The next section tells how to list the contents of
a library.
■ The newlibrary field specifies a name for the modified library if the
commands you give change an existing library. See Section 6.1.1.5,
"Output Library," for more information on this field.
2.3 Listing the Contents of a Library
You can use LIB to obtain a symbol listing for any object-code library.
Listings are useful because they give the exact names of modules and of
"public symbols," which are names of functions and global variables that can
be referenced throughout the program. You may need a listing if you want to
modify a library, as described in the next section.
To list the contents of a library, you need to use only the oldlibrary field
and the listfile field. Use a semicolon (;) to terminate the command so that
LIB does not prompt you for additional input.
In the oldlibrary field, give the name of the library you want to examine.
You can enter a full path name or a file name without a path. If you do not
include a file extension, LIB assumes the default .LIB extension. Typically,
object-code libraries have a .LIB extension.
In the listfile field, give the name of the file in which you want the
listing to be placed. If you enter the name of a file that does not yet
exist, LIB creates the file. If you enter the name of a file that already
exists, LIB replaces the current contents of the file with the new listing.
For example, the following command line directs LIB to place a listing of
the contents of MYLIB.LIB into the file LISTING.TXT:
LIB MYLIB, LISTING.TXT;
The listing file summarizes the contents of the entire library. Each listing
file contains two kinds of information, in this order:
1. A list of public symbols with corresponding modules for each
2. A list of modules with corresponding symbols for each
Modules, which are basic to the operation of LIB, are discussed in the next
section. For a more detailed description of listing files, see Section
6.1.1.4, "Cross-Reference-Listing File," in Part 2 of this manual.
2.4 Modifying the Contents of a Library
You can use LIB to alter the contents of any object-code library. There are
a number of reasons why you might want to do so. For example, if you work
with higher-level-language libraries, you may want to replace a standard
routine with
your own version of the routine. Or you may want to add a new routine to the
standard library so your routine is available along with the standard
routines.
LIB operations involve "object files" and object modules:
Item Description
────────────────────────────────────────────────────────────────────────────
Object file An independent file containing object
code corresponding to one source file.
An object file normally has a .OBJ file
extension.
Object module A self-contained unit within a library,
consisting of one or more routines. An
object module in a library is in almost
all respects identical to the
corresponding object file. The object
module, however, has no file extension
or path because it is not a separate
file.
The sections that follow discuss both items extensively. Remember: a unit of
object code in a library is called an object module; the corresponding unit
of code outside a library is stored in a file called an object file.
2.4.1 Modifying the Library
To modify an object-code library, carry out the following steps:
1. To add or replace an object module, first compile or assemble the new
code. If the procedure you want to add is part of a program, copy the
source code into its own file and compile or assemble it separately.
2. Add, delete, or replace the module with the command line
LIB oldlibrary commands;
in which commands consists of one or more LIB commands that use the
syntax shown later in this section.
Note that in step 2 above, the command line does not use all the LIB fields.
You can, however, include a listfile if you want a file listing. You can
also use the newlibrary field to preserve old library contents. If you enter
a newlibrary, LIB places the updated library contents in newlibrary and
leaves the contents of oldlibrary unchanged. Otherwise, LIB updates the
contents of oldlibrary and saves the old contents in the file
oldlibrary.BAK.
You can use the library as input to the linker once the contents change. Any
routines you have added or replaced become part of the library and can be
called by your programs.
2.4.2 Adding a Module
To add an object file to a library, use the command
+file
in which file is the name of the object file you want to add as a module.
You can specify a complete path name for file if the object file is not in
the current directory. If the file-name extension is .OBJ, you can leave off
the extension; LIB assumes the .OBJ extension by default. LIB adds the
object module at the end of the library. The library contains only the base
name of the module without the .OBJ extension.
For example, the following command line adds the module PRINTOUT to the
library MYLIB.LIB, by copying the contents of the object file
\SOURCE\PRINTOUT.OBJ:
LIB MYLIB +\SOURCE\PRINTOUT;
You can also add the entire contents of one library to another by specifying
a library name for file. Remember to enter a complete file name (including
extension) because LIB assumes that files in the commands field have the
OBJ extension. For example, the following command line adds the complete
contents of the library SMALL.LIB to the library SUPER.LIB:
LIB SUPER +SMALL.LIB;
2.4.3 Deleting a Module
To delete an object module from a library, use the command
-module
in which module is the name of a module already stored in the library. For
example, the following command deletes the module DELETEME from the library
BIGLIB.LIB:
LIB BIGLIB -DELETEME;
2.4.4 Replacing a Module
To replace an object module within a library, use the command
- +module
in which module is the name of a module that is currently stored in the
library. The old copy of module is deleted from the library. The current
contents of module.OBJ are copied into the library. For example, to replace
the QuickC small-model library version of printf() with your own version,
execute these steps:
1. Write your own version of printf(), and compile or assemble it.
2. Make sure that the resulting object file is named PRINTF.OBJ and that
PRINTF.OBJ is located in the current directory. (If you look at a
listing of the library, you will see that the public symbol for the
printf() function is _printf(). The name of the module, however, is
printf(). If you have any doubt about the exact name of an object
module, get a listing of the library before trying to modify the
library.)
3. Issue the following command line:
LIB SLIBCE -+PRINTF;
You can combine any number of operations in the commands field. Spaces
between the commands are acceptable but not necessary. For example, the
following command line adds a new module (NEWFUN), replaces a current module
(OLDFUN), and deletes another current module (BYENOW):
LIB MYLIB +NEWFUN -+OLDFUN -BYENOW;
In the example above, the files NEWFUN.OBJ and OLDFUN.OBJ serve as input for
the modules NEWFUN and OLDFUN, respectively.
2.4.5 Copying and Moving Modules from a Library
You can extract any object module from a library. The extracted object
module is copied into a .OBJ file with the same name as the module. For
example, if you extract a module named OLDFUN, LIB copies it into the object
file named OLDFUN.OBJ. If a file with that name already exists, its contents
are overwritten.
To copy a module into a .OBJ file, use the command
*module
in which module is the name of the module you wish to copy from the library.
The module is placed in the file module.OBJ.
For example, the following command line copies the printf() module from the
Microsoft QuickC small-model library and places the contents of this module
into the object file PRINTF.OBJ:
LIB SLIBCE *PRINTF;
You can move a module out of a library with the following command:
-*module
Moving a module is similar to copying a module, in that LIB copies the
contents of the module into a file named module.OBJ. The move command (-*),
however, deletes the module from the library after copying it.
2.5 Creating a New Library
When you use LIB, creating a new object-code library is easy. You simply
combine two techniques:
1. In the oldlibrary field, enter the name of a file that does not yet
exist.
2. In the command field, use the add command (+file) to list entries for
the new library. (Technically, this step is not required; however, if
you do not use the add command, the library will be empty.)
For example, if the file NEWLIB.LIB does not yet exist, the following
command line creates this file:
LIB NEWLIB +MYPROC +MYFUN +PRINTIT;
The object files MYPROC, MYFUN, and PRINTIT provide the input for the new
library.
2.6 Other Ways of Using LIB
This chapter has covered the basic operations of the LIB utility so that you
can quickly begin to create and maintain your own libraries. For a complete
description of LIB, see Chapter 6, "LIB," in Part 2 of this manual. Some
additional features described in that chapter include the following:
■ How to make LIB case sensitive so that it treats Print and PRINT as
two different module names.
■ How to specify alignment of modules within a library.
■ How to let LIB prompt you for command fields, rather than requiring
you to enter them all on a single command line.
■ How to use a response file to give input to LIB. Response files are
useful for giving unusually long command lines or for giving the same
command line repeatedly.
Chapter 3 Maintaining Programs with NMAKE
────────────────────────────────────────────────────────────────────────────
The Microsoft Program-Maintenance Utility (NMAKE) helps to automate software
development and maintenance. Following instructions that you supply, NMAKE
determines whether a program is out-of-date and, if so, how to update it.
Your instructions list all the sources, include files, and libraries the
program depends on and specify the commands to update the program.
NMAKE, however, is not limited to updating programs. It can also perform
other actions, such as building distribution disks, cleaning up directories,
and so forth. Any procedure that requires the latest version of several
files is a good candidate for NMAKE. By using NMAKE for these operations
instead of performing them manually, you can avoid the headaches of invalid
source modules, old libraries, and forgotten include files.
You can use NMAKE in the following situations:
■ In program development, to update an executable file whenever any of
the source or object files has changed
■ In library management, to rebuild a library whenever any of the
modules in the library has changed
■ In a networking environment, to update the local copy of a file that
is stored on the network whenever the master copy has changed
This chapter describes what NMAKE does, defines the terms you need to
understand, and tells you how to use NMAKE to manage your QuickC Compiler
projects. For detailed information, see Chapter 7, "NMAKE," in Part 2 of
this manual.
3.1 How NMAKE Works
NMAKE relies on a "description file" (sometimes called a "makefile") to
determine which files to update, when to update them, and what operations to
perform. The description file for a QuickC program lists the source and
header files needed to build each object file, and all the object files
needed to build the executable program. The description file tells NMAKE
whether changes have been made to source, header, or object files. If source
or header files have been changed, NMAKE recompiles the object file; if any
object files have been changed, NMAKE relinks the program. The description
file also contains the QCL commands that must be executed to build the
object files and the program.
Description files are made of several elements:
■ Description blocks, which tell NMAKE how to build files. See Section
3.2.1, "Description Blocks," for further information.
■ Macros, similar to C macros, which provide a shorthand notation that
allows you to change certain values when the file is processed. See
Section 3.5.2, "Using Macros," for further information.
■ Inference rules, which tell NMAKE what to do in the absence of
explicit commands. See Section 3.5.3, "Using Inference Rules," for
further information.
■ Directives, which provide conditionals and other structuring
techniques. See Section 3.5.4, "Using Directives," for further
information.
A simple description block
All of these elements need not be present in every description file. For
many applications, a description file consisting of a single description
block is adequate. The example below shows a description file with only one
description block:
program.exe : program.obj sub1.obj #update program
QCL program.obj sub1.obj
The first line of the description block is called the "dependency line." It
identifies the "target" to be updated (PROGRAM.EXE) and the "dependents"
that make up the target (PROGRAM.OBJ, SUB1.OBJ). If any of the dependents
has changed since the target was last modified, NMAKE rebuilds the target.
When NMAKE executes this description, it checks the date on which each of
the object files was last modified. If either has been modified since the
executable program was created, NMAKE executes the second line, which is
called the "command line." The QCL command in the above example relinks the
program.
What about the C source files?
Note that the target is an executable file (.EXE) and its dependents are
object files (.OBJ). You might wonder why the C source files PROGRAM.C and
SUB1.C do not appear in the description block. The reason is that NMAKE
assumes that .OBJ files depend on C source files and knows that it must
compile PROGRAM.C and SUB1.C to create PROGRAM.OBJ and SUB1.OBJ. How and why
NMAKE works this way are advanced topics covered in Section 3.5.3, "Using
Inference Rules." You don't need to understand inference rules to create
description files and use NMAKE.
Of course, if you prefer, you can make your target-executable files depend
on the C source files and use the QCL command to compile and link the
sources. It is usually preferable, however, to list the object files as
dependents.
The next section in this chapter, "Building a Simple Description File,"
shows how to construct description files, such as the one above, that
consist of a single block.
3.2 Building a Simple Description File
Before you invoke NMAKE, you need to create a description file. Since a
description file is simply a text file, you can use any text editor
(including the one in the QuickC environment) to create one. NMAKE places no
restrictions on the name of the description file, but always looks for a
file named MAKEFILE in the current directory unless you tell it otherwise.
See Section 3.3, "Invoking NMAKE," for more information on how NMAKE
identifies the description file.
Depending on the size of the project you are maintaining, your description
file may contain one or more description blocks. This section describes the
components of a description block and shows you how to build description
files that consist only of description blocks.
3.2.1 Description Blocks
Description blocks are the basic elements of description files. A
description block tells NMAKE how to update a target from a group of
dependents. Every description block consists of a dependency line, any
number of command lines, and optional comments. Figure 3.1 shows the
components of a description block.
(This figure may be found in the printed book.)
3.2.1.1 Dependency Lines
A dependency line typically lists one target and one or more of its
dependents. A colon (:) separates the target from the dependents.
Targets
The name of the target goes at the beginning of the line, with no tabs or
spaces preceding it. NMAKE creates the target in the current directory
unless you include a drive and path specification in its name. A dependency
line may contain more than one target, but at least one space must separate
each pair of names. Below are some example target names:
test1.exe :
c:\cprogs\test1.exe :
test1.exe test2.exe :
The first example specifies the target TEST1.EXE in the current directory.
In the second, the target is built in the directory C:\CPROGS. The last
example lists two targets to be built from the same set of dependents.
Pseudotargets
All the targets shown above are executable files. A target, however, need
not be an executable file; in fact, it need not be a file at all. NMAKE
allows you to specify the following:
UPDATE :
In this case, UPDATE is considered a "pseudotarget" because it is not a file
but simply a label for a set of dependents and commands. Pseudotargets are
useful for updating directories and copying groups of files. NMAKE always
considers pseudotargets out-of-date.
Specifying dependents
List the names of the dependent files on the same line as the target but
after the colon. Separate the dependent names by one or more spaces. A
target can have any number of dependents. If the names of all the dependents
do not fit on one line, use a backslash ( \ ) to end the line and continue
the list on the next line. This is NMAKE's standard method of line
continuation.
Dependent names, like target names, can contain drive and path
specifications. If you do not include a drive or path specification, NMAKE
looks for the dependents in the current directory. For example:
The first example shows two dependents for MYCPROG.EXE. One of them is
MYCPROG.OBJ, for which NMAKE searches the current directory. The other is
GRAPHICS.OBJ, for which NMAKE searches the \PUBLIC\SRC directory. The second
example shows that the pseudotarget UPDATE depends on all the .C files in
the current directory and all the header files in the /INC directory.
Search paths for dependents
You can direct NMAKE to search for dependents in a sequence of other
directories by adding a search path enclosed in braces. NMAKE searches the
directories specified by the path if it cannot find the file in the current
directory. Separate each pair of directories in the path with a semicolon.
The backslash at the end of the path is optional. Consider the following:
This line lists two dependents for PROGRAM.EXE. The first, PROGRAM.OBJ, is
assumed to be in the current directory. For TABLES.OBJ, a search path is
specified. The search path causes NMAKE to look first in the current
directory, then in \ME\CWORK, and then in Q:\SRC until it finds the file. If
it cannot find the file, all is not lost; it relies on its inference rules
to build the file. (See Section 3.5.3 in this chapter for more information
on inference rules. For a more detailed description, see Section 7.2.4,
"Inference Rules.")
3.2.1.2 Command Lines
The command lines in a description block give the commands to be carried out
if a target is out-of-date with respect to any of its dependents. Commands
can be the names of programs, batch files, or any DOS commands─in short, any
command that can be issued on the DOS command line.
Rules for specifying commands
In the typical format of a description file, the commands are on separate
lines from the target and its dependents, one command per line. Each line
must start with one or more spaces or tab characters. If you forget the
space or tab, NMAKE assumes you are specifying a dependency line (or a
macro) and displays an error message. You may find it helpful to use a tab
to indent the line, making it easy to identify the commands that apply to
each target. (This book uses that convention.) For example:
The command line in the example above invokes QCL to link the two dependent
files into a single executable image.
If you prefer, however, you can put your commands on the same line as the
target and dependents. In that case, a semicolon must precede each command
to separate it from the previous item on the line, whether that item is a
dependent or another command. The following has the same effect as the
previous example:
If a command is too long to fit on one line, you can split it across two or
more lines with a backslash ( \ ), in the same way that you split a long
dependency list. For example:
Be sure that every line that is part of a command begins with a space or
tab.
3.2.1.3 Comments
You can put comments in your description files by using the number sign (#).
NMAKE ignores all the text between the number sign and the beginning of the
next line. Comments may appear anywhere in an NMAKE description file except
on a command line. You can place comment lines between the command lines,
but the number sign that starts the comment must be the first character on
the line with no spaces or tabs preceding it. The following example shows
the use of comments:
#makefile for program.exe
program.exe : program.obj sub1.obj sub2.obj
qcl program.obj sub1.obj sub2.obj
# program
The first comment documents the purpose of the file. The second causes NMAKE
to treat the word program as a comment. When NMAKE executes this
description, it will rebuild PROGRAM.EXE but will not run it.
3.2.1.4 Escape Characters
Some characters, such as the number sign (#), have a special meaning when
they appear in an NMAKE description file. If you want NMAKE to interpret a
character literally, and not with its special NMAKE meanings, you must
precede the character with the caret (^). The caret is an "escape
character," which means that when it immediately precedes a special
character, it causes the character to lose its special meaning.
For example, the number sign (#) denotes the start of a comment. To use it
in a file name, you must precede it with a caret to "escape" its special
meaning, as follows:
winning^#.txt
NMAKE interprets the example as the file name winning#.txt .
The following characters have special significance to NMAKE, so you must
precede them with a caret whenever you want NMAKE to interpret them
literally:
# ( ) $ ^ \ { } ! @
NMAKE ignores a caret that precedes any other character. In addition, carets
that appear within quotation marks are not treated as escape characters.
Examples
Assume you are developing a program named HANDLE. Your directories are
organized so that all your source files and object files are stored under
the current directory and your include files are in the \INC directory.
Consider the following description file:
The dependency line say that HANDLE.EXE should be updated if any of three
files change. Two of these files (MAIN.OBJ and COMM.OBJ) are object files;
the third (COMM.H) is an include file. If NMAKE determines that it must
create a new version of the target, it executes the QCL command. The QCL /Fe
option specifies the name HANDLE.EXE for the executable program. NMAKE
executes the new version of HANDLE.EXE after creating it.
If the current directory contains only the files for HANDLE.EXE, and none
for any other programs, the description file could be rewritten as follows:
NMAKE expands the wild cards in the dependent names when it starts to build
the target.
3.2.2 The CC Macro
The sample description files presented so far have contained only
description blocks─no macros, directives, or inference rules. For the most
part, you can get by without any of these features.
Before you use NMAKE with QuickC, however, you need to know about one
particular macro, CC. The predefined macro CC tells NMAKE which C compiler
to use when it tries to create .OBJ files from .C files. Recall that NMAKE
knows that .OBJ files depend on .C files, which is why only .OBJ files
appear in the examples up to this point. NMAKE implicitly compiles .C files
into .OBJ files, using the compiler specified by the CC macro.
As you may be aware, NMAKE is provided with both Microsoft C Professional
Development System and QuickC. For that reason, CC is predefined to invoke
the C compiler included with the Professional Development System, CL. You
must redefine CC to invoke QCL, the QuickC compiler.
To redefine the CC macro, add this line at the top of your description file:
CC = qcl
No spaces or tabs can precede CC; it must be the first item on the line. The
spaces around the equal sign are optional.
Continuing with the example in Section 3.2.1.4, the description file would
look like the following:
This description block has the same effect as the earlier ones, except that
if any .OBJ files in the current directory must be updated from .C files, it
ensures that NMAKE will use the QuickC compiler to do it. The QCL command in
the example is independent of the CC macro; the command line explicitly
invokes QuickC to link the object files into an executable file.
Redefining CC in the TOOLS.INI file
As an alternative, you can redefine CC in TOOLS.INI, the
tools-initialization file. The TOOLS.INI file contains environment variables
and initial (default) settings for various utility programs. You may already
have a TOOLS.INI file; if not, you can create one with any text editor.
Items that apply to NMAKE appear in the file following the [nmake] tag. To
change the definition of the CC macro, add the following line after the tag:
CC=qcl
Whenever you invoke NMAKE, the utility looks for TOOLS.INI first in the
current directory and then in the directory specified by the INIT
environment variable. To see what INIT is set to, type the SET command at
DOS command level.
3.3 Invoking NMAKE
You can invoke NMAKE in either of two ways:
1. By giving the NMAKE command and all options, macros, and targets on
the DOS command line
2. By giving the NMAKE command and the name of a response file that
contains all the options, macros, and targets
This section describes both methods.
3.3.1 Invoking NMAKE from the DOS Command Line
Under most circumstances you'll probably issue the NMAKE command from the
DOS command line. The command has the following format:
(This figure may be found in the printed book.)
The items in italics are optional arguments and are described below:
■ The options modify the action of the NMAKE command. The most commonly
used NMAKE options are described in the section titled "NMAKE
Options"; the complete set is covered in Chapter 7.
■ The macrodefinitions give text to replace macro names in the
description file. Section 3.5.2, "Using Macros," introduces macros and
explains how and when to use them. See Section 7.2.3, "Macros," for
details.
■ The targets field lists one or more targets for NMAKE to build. If you
do not specify a target, NMAKE builds only the first one in the file.
You can find more information on targets in Section 3.2.1,
"Description Blocks," and in Section 7.2.1. Because all the arguments
are optional, the simplest form of the NMAKE command is just
NMAKE
The default file MAKEFILE
When you invoke NMAKE with the preceding command, it looks in the current
directory for a file named MAKEFILE to use as the description file. If no
such file exists, it displays an error message.
You can specify an alternate description file by using the /F option,
described below in Section 3.4.1, "Controlling Input."
3.3.2 Invoking NMAKE with a Response File
For more complicated updates, and whenever the NMAKE command line exceeds
the DOS limit of 128 characters, you will need to create a response file.
The response file contains the options, targets, and macros you would type
on the DOS command line. It is not the same as the NMAKE description file;
instead, it is comparable to a QLINK or LIB response file.
To invoke NMAKE with a response file, issue the following command:
NMAKE @responsefile
For responsefile, use the name of the file that contains the options,
targets, and macros you would otherwise type on the NMAKE command line.
3.4 NMAKE Options
NMAKE provides a rich set of options that control the descriptions it reads
as input, the details of its execution, and the messages it displays on
output. The following sections describe some of the most useful NMAKE
options. Section 7.3 covers all the options in detail.
Options immediately follow the NMAKE command on the DOS command line and
precede the name of the description file, if you supply one. NMAKE accepts
options in uppercase or lowercase letters, with either a slash ( / ) or a
dash (-) to introduce each option. For example, -F, /F, -f, and /f all
represent the same option. In options that take file-name arguments, for
example, /F and /X, the file name and the option must be separated by a
space.
3.4.1 Controlling Input
You can specify the description file from which NMAKE will take its input
with the /F option. This option has the following form:
/F filename
If you specify the /F option, NMAKE uses filename as the name of the
description file. The space separating /F and filename is required. In place
of a file name, you can enter a dash (-) to tell NMAKE to read the
description from standard input, typically your keyboard.
If you omit the /F option, NMAKE looks for a file named MAKEFILE in the
current directory. If no such file exists, it displays an error message.
Unless you use the /F option, NMAKE always searches for the file MAKEFILE in
the current directory. Therefore, you should explicitly specify /F to avoid
unintentionally using MAKEFILE.
────────────────────────────────────────────────────────────────────────────
The following is an example of the /F option:
NMAKE /F hello.mak
This command invokes the NMAKE utility and specifies HELLO.MAK, in the
current directory, as the description file.
3.4.2 Controlling Execution
The following options change the way NMAKE interprets the description file:
Option Effect
────────────────────────────────────────────────────────────────────────────
/A Builds all of the targets requested,
even if they are not out-of-date.
/I Ignores exit codes returned by commands
executed within a description file.
NMAKE continues processing the
description file despite the errors.
/N Displays the commands from the
description file but does not execute
them. Use this option to determine which
targets are out-of-date without
rebuilding them. You can also use it in
debugging description files.
/T "Touches" any target files that are
outdated. Touching a file causes its
date of modification to be changed to
the current date. It has no effect on
the contents of the file.
3.4.3 Controlling Output
As NMAKE runs, it displays each command that it executes. It displays a
diagnostic message if it cannot find a file or command needed to complete a
description block or if any command returns an error. You can change the
type and number of messages that NMAKE returns by using the options below:
Option Effect
────────────────────────────────────────────────────────────────────────────
/C Suppresses the Microsoft copyright
message and all nonfatal or warning
messages.
/D Displays the modification date of each
target or dependent file when it checks
the date.
/P Prints all macro definitions and target
descriptions.
/S Executes "silently"; does not display
commands as they are executed.
/X filename Sends all error output to filename. A
space must separate /X from filename.
Specifying a dash (-) instead of a file
name sends error output to the standard
output device.
Examples
The following command invokes NMAKE with PHYSICS.MAK as the description
file:
NMAKE /F physics.mak /N
The /N option tells NMAKE to read, but not to execute, any of the commands
within the file PHYSICS.MAK. NMAKE checks the modification dates on the
files and displays the commands it would execute if the /N option were not
present. Use this option to find out ahead of time what files are
out-of-date so you can estimate how long a build might take. You can also
use it in debugging description files.
After using the /N option to check what NMAKE would do, you might invoke it
with the command line below:
NMAKE /F physics.mak /C /S
The /C option suppresses the NMAKE copyright message and any warning
messages. The /S option suppresses the display of commands. You will,
however, still see the copyright messages for any commands that NMAKE
invokes and the output those commands generate.
3.5 Building Complex Description Files
Most software projects can be maintained using the features already
described. However, description files for large projects may become
complicated and cumbersome, especially if each module is dependent on many
source and include files. Using NMAKE's advanced features, you can shorten
your description files and make them more powerful at the same time.
This section covers several of NMAKE's advanced features:
■ Special characters on command lines
■ Macros
■ Inference rules
■ Directives
Figure shows a more complicated description file than those presented so
far.
(This figure may be found in the printed book.)
3.5.1 Using Special Characters to Modify Commands
NMAKE recognizes three special characters that modify its treatment of
commands. These characters give you additional control over the execution of
individual commands, whereas NMAKE's options apply to all the commands in
the description file.
The characters go before the command name and can be separated from the name
by one or more spaces, though they need not be. At least one space or tab
must precede the character on the line. To use two or three special
characters with a single command, put them one after the other on the
command line. The special characters are as follows:
Character Action
────────────────────────────────────────────────────────────────────────────
Dash (-) Turns off error checking for the command
it precedes so that NMAKE continues
executing if an error occurs. A dash
followed by a number suspends error
checking for error levels at the number
and below.
At sign (@) Suppresses display of the command when
it is
executed.
Exclamation point (!) Causes the command to be executed
iteratively, once for each dependent
file, if it uses one of the macros for
dependent names. (The macros are
described in the Section 3.5.2.)
Note that the dash (-) has the same effect as the /I option. Also, the "at"
sign (@) is similar to the /S option.
Examples
beatles.exe : john.asm paul.c george.c ringo.c
-QCL /c paul.c george.c ringo.c
MASM john
QLINK john paul george ringo, beatles.exe;
In the example above, the dash preceding the QCL command means that NMAKE
will attempt to execute the MASM and QLINK commands even if errors occur
during compilation.
beatles.exe : john.asm paul.c george.c ringo.c
-@QCL /c paul.c george.c ringo.c
MASM john
@QLINK john paul george ringo, beatles.exe;
The description in this example has the same effect as that in the previous
example, except that neither the QCL nor the QLINK command is displayed when
it is executed.
3.5.2 Using Macros
You can use macros to streamline your description files. A "macro" is a name
that replaces other text in the description file in the same way that a
macro defined in a QuickC #define directive replaces other text in a
program. Wherever the name appears in the description file, NMAKE
substitutes the text associated with it. To change the meaning of the name,
you simply change the text assigned to it in the macro definition.
Macros are most useful in two situations:
1. To replace all or part of a file name so that a single NMAKE
description file can be used to update more than one program.
2. To supply options for commands within the NMAKE description file. For
example, you might define a macro to represent your usual debug
options for the QCL command. Then, to compile with a different set of
options, you need not edit the description file. You merely change the
macro definition.
NMAKE provides two types of macros: predefined macros and macros you define.
This section shows how to use them.
3.5.2.1 Defining Your Own Macros
A "macro definition" tells NMAKE what text to substitute for a macro. You
can put macro definitions in the description file, on the NMAKE command
line, or in your TOOLS.INI file. In the description file, each macro
definition must be on a separate line. On the command line, macro
definitions follow any NMAKE options and precede any targets. In the
TOOLS.INI file, macro definitions appear in a section following the [nmake]
tag, each on a separate line, as described previously in Section 3.2.2, "The
CC Macro."
No matter where you put them, macro definitions take the following form:
macroname = string
The macroname is the name you use in the description file. A macro name can
consist of any alphanumeric characters and the underscore ( _ ) character.
The string is the text that replaces the macro name when the description
file is processed.
Macros on the command line
On the NMAKE command line, white space cannot appear on either side of the
equal sign because it causes DOS to treat the macro name and its definition
as separate tokens. In addition, if string contains any embedded white
space, you must enclose it in double quotation marks, as follows:
my_macro="this string"
Alternatively, you can enclose the entire macro definition─macroname and
string─in double quotation marks. In that case, spaces can surround the
equal sign because DOS treats all the characters within quotation marks as a
single token. Thus, the following is also acceptable:
"my_macro = this string"
Macros in the description file
In a description file, define each macro on a new line. The definition must
start at the beginning of the line with no preceding white space. NMAKE
ignores any white space surrounding the equal sign. Quotation marks are
unnecessary as well; if you use them, they will become part of the string.
This example defines a macro named pname and another named t:
pname = mycprog.exe
t = this
To use a macro within a command or dependency line, specify its name in
parentheses preceded by a dollar sign ($), as follows:
$(macroname)
If you need to use a literal dollar sign in a description file, type it
twice ($$) or use the caret (^) escape character.
The lines below show how to refer to the macros defined in the previous
example. Note that if the name of a macro is only one character long, you
can omit the parentheses.
$(pname)
$t
Once you've defined a macro, the only way to remove its definition is to use
the !UNDEF directive. See Section 3.5.4, "Using Directives," for more
information.
Examples
A common use of macros is to specify the options for a command. For example,
the following description block uses the macro copts to represent QCL
options.
Assuming the description file is named PICTURE.MAK, the command line might
be the following:
NMAKE /F picture.mak copts="/C /P"
At execution time, NMAKE substitutes /C /P wherever $(copts) appears in
the description file. The result is the same as if the following description
were used:
Note that the /P option causes QuickC to create a preprocessor listing, and
the /C option retains the comments from the source files in the preprocessor
listing.
3.5.2.2 Predefined Macros
Some macros are predefined by NMAKE. You have already seen one of these, CC.
Some of the other predefined macros are described below. For a complete
list, see Section 7.2.3.3.
Macros for Program Names (CC, AS, MAKE) - The CC macro, already
introduced, represents the C compiler command that NMAKE executes to create
object files from C source files. The AS macro is similar. It stands for the
name of the assembler that NMAKE executes when it needs to create object
files from .ASM sources. Both of these macros are predefined by NMAKE. You
can change their definitions in the description file, in the TOOLS.INI file,
or on the NMAKE command line. Their default definitions are
CC = cl
AS = masm
These two macros are primarily used in inference rules. (See Section 3.5.3,
"Using Inference Rules," or Section 7.2.4, "Inference Rules," for more
information.)
The MAKE macro is defined as the command you use to invoke NMAKE. Use this
macro, rather than the NMAKE command itself, to invoke NMAKE recursively
within a description file. Recursion is typically used in building large
software projects, such as compilers, and frequently involves the use of
conditional directives. (An example of the recursive use of NMAKE appears
later in this chapter in Section 3.5.4.2, "Conditional Directives.")
Macros for Target Names ($@, $*) - The $@ macro represents the full name of
the target, and the $* macro represents the base name of the target, which
is the full name with the extension deleted. These two macros are typically
used in inference rules, but for the sake of discussion, this section will
show their use in description files.
Assume NMAKE is invoked with the following command:
NMAKE target=trees.exe
The command line supplies text for the macro target, which sets the full
name of the target to trees.exe. At execution time, NMAKE substitutes the
text for the macro as explained in Section 3.5.2. However, this file goes
one step further. Instead of repeating the user-defined $(target) macro as
the output of the QLINK command, it uses the predefined $@ macro. This macro
stands for the full name of the target and therefore has the same meaning as
$(target). Thus, the QLINK command links the object files into trees.exe.
In the last line of the file, the $* macro stands for the base name of the
target. This line causes trees.exe to be executed as a program.
NMAKE automatically substitutes for these macros. It picks up the target
name from its position on the dependency line in the description file. You
cannot assign a value to a predefined macro on the command line.
NMAKE provides additional predefined macros that you can use to specify
target names. See Section 7.2.3.3, "Predefined Macros," for details.
Macros for Dependent Names ($**, $?) - These macros signify the names of one
or more dependents. The $** macro represents the complete list of dependent
files for the target. The $? macro represents only the dependents that are
out-of-date relative to the target. These two macros are commonly used with
the special characters that modify commands to prevent NMAKE from doing any
more work than necessary.
The example below shows the description file from the previous section using
macros for the dependent names:
The first line of the example defines all the dependents for the target. On
the next line, the QLINK command links all the dependents, represented by
$**, into a single executable image. Finally, the target is run as a
program.
NMAKE provides additional predefined macros that you can use to specify
dependent names. See Section 7.2.3.3, "Predefined Macros," for details.
3.5.2.3 Precedence of Macro Definitions
Because macros can be defined in so many places, it is quite possible to
give a macro more than one definition. Sometimes this is desirable. For
instance, you may wish to override a macro definition for a single execution
of the description file.
NMAKE's precedence rules determine which macro definition it uses.
Precedence depends on where the macro is defined. Listed below is the order
of precedence from highest to lowest priority:
1. Macros defined on the NMAKE command line.
2. Macros defined in the description file and in files included in the
description file with the !INCLUDE directive (see Section 3.5.4,
"Using Directives").
3. Macros inherited from environment variables.
4. Macros defined in the TOOLS.INI file.
5. Macros defined by NMAKE, such as CC and AS.
Figure shows how macros defined on the command line take priority over
those in the description file.
In addition, you can force environment variables to override assignments in
the description file, using the /E option.
3.5.3 Using Inference Rules
Most of the description blocks shown so far in this chapter contain commands
to update the target from its dependents. Under certain conditions, however,
NMAKE will follow a set of rules, called "inference rules," to create the
target. Like macros, several inference rules are predefined, and NMAKE
allows you to define your own.
(This figure may be found in the printed book.)
If you supply a description block that does not contain any commands, or if
the dependents of your target do not exist, NMAKE relies on inference rules.
Whether predefined or user defined, inference rules are based on the
file-name extensions of the target and dependent files. In short, they tell
NMAKE how to create a file with a particular extension from a file with the
same base name and a different extension.
Below is a simple inference rule:
.c.exe :
QCL $*.c
This rule defines how to make a file with the .EXE extension from a file
with the same base name and the .C extension. The first line says that the
rule tells how to go from a file with the .C extension to a file with the
EXE extension. The second line gives the command that creates the .EXE
file─in this case, the QCL command. The $* macro represents the base name of
the target with the extension deleted.
An inference rule looks very similar to a description block, with two
exceptions:
1. An inference rule lists two file-name extensions instead of target
names.
2. Inference rules do not list dependents.
If the inference rule shown in the example above were in effect, NMAKE would
use it for the following description block:
zfile.exe : zfile.c
NMAKE applies the inference rule for three reasons:
1. The description block does not contain any commands.
2. The file-name extensions of the target file and its dependent match
those in the rule.
3. The base name of the target and dependent are the same.
The combination of the inference rule and the description block above has
the same effect as the following description block:
zfile.exe : zfile.c
QCL zfile.c
3.5.3.1 Predefined Inference Rules
NMAKE has three predefined inference rules. The predefined rules make use of
the default macros CC and AS, along with several of the predefined macros
that have already been presented.
From .C to .OBJ
One predefined rule builds .OBJ files from .C files:
.c.obj:
$(CC) $(CFLAGS) /c $*.c
When NMAKE applies this rule, it substitutes the current values of the
macros CC and CFLAGS for $(CC) and $(CFLAGS). (The CFLAGS macro lists
options for the C compiler.) It then looks for a C source file with the same
name as the target and compiles the source file without linking. This is the
rule NMAKE uses for the examples in this chapter that list .OBJ files─not C
source files─as dependents.
With the description block below, NMAKE would use this inference rule if it
needed to create or update one or more of the .OBJ files listed in the
dependency list:
menu.exe : menu.obj funcs.obj draw.obj
QLINK menu funcs draw;
If the current directory contains .C source files with the same base names
as the .OBJ files in the example, NMAKE compiles them according to the
inference rule.
From .C to .EXE
Another predefined rule, shown below, builds .EXE files from .C files:
.c.exe:
$(CC) $(CFLAGS) $*.c
This rule causes NMAKE to use the same files as the previous rule but to
link the output into an executable image. Continuing with the example, NMAKE
would use this rule if the description file contained the following:
menu.exe : menu.c
Note that the files FUNCS.C and DRAW.C are not shown here. NMAKE would not
create .EXE files for them because their base names are different from that
of the .EXE file that NMAKE is trying to create.
From .ASM to .OBJ
The third predefined rule builds .OBJ files from .ASM files:
.asm.obj:
$(AS) $(AFLAGS) $*;
This rule tells NMAKE to look for an assembly-language source file with the
same name as the target file and to invoke the Macro Assembler to create an
object file. (The AFLAGS macro lists options for the assembler command.)
NMAKE would use this inference rule under the same conditions as the first
rule. For example:
menu.exe : menu.obj funcs.obj draw.obj
QLINK menu funcs draw;
If the current directory contains .ASM files with the same base names as any
of the .OBJ files, NMAKE uses this final inference rule.
3.5.3.2 Defining Inference Rules
The predefined inference rules are adequate for most situations.
Nevertheless, NMAKE allows you to define your own inference rules in the
description file or in your TOOLS.INI file . You can also define them in a
separate file that you include in your description file. (See Section
3.5.4.1 for information on the !INCLUDE directive.) Inference rules cannot
be defined on the NMAKE command line.
To define an inference rule, use a statement in the following form :
fromext.toext: command .
The first line defines the types of files to which the rule applies. It
contains the extension of the "from" file first, and then the extension of
the "to" file. The second and subsequent lines give the commands that NMAKE
must execute to create a file with the "to" file extension from a file that
has the same base name and the "from" file extension. You can specify one or
more commands, just as in a description block.
Specifying a path for .fromext or .toext
Sometimes you may want to associate a directory with each type of file. For
instance, some programmers organize all their source files in one directory
and their object files in another. NMAKE allows you to precede each of the
extensions with a path, as follows:
{frompath}.fromext{topath}.toext
The example below shows a rule that starts with source files in one
directory and creates object files in a different directory:
{\usr\graphics\source}.c{\usr\graphics\obj}.obj
You can specify only one path for each extension. If you need to pull source
files from several different directories and place all the object files in
one directory, you must define a separate inference rule for each source
directory.
3.5.3.3 Precedence of Inference Rules
Like macros, inference rules can be defined in several places; the location
of an inference rule's definition establishes its precedence. NMAKE applies
inference rules in the following order, from highest to lowest priority:
1. Inference rules defined in the description file or in files included
in the description file by the !INCLUDE directive (described in
Section 3.5.4.1)
2. Inference rules defined in the TOOLS.INI file
3. Predefined inference rules
3.5.4 Using Directives
Directives provide additional control over the execution of commands, beyond
what you can do with macros and inference rules. Using directives, you can
■ Include the contents of another file in your description file
■ Conditionally execute a command or group of commands
■ Issue error messages from within a description file
In effect, directives let you build description files that act like DOS
batch files. Such description files are especially useful for large software
projects in which the work is divided among several people. A description
file can compile each source file, build any necessary libraries, and link
the entire program. If errors occur anywhere in the process, the description
file can issue diagnostic messages, possibly take corrective action, or
terminate execution.
Each directive begins on a new line in the description file. A directive
starts with an exclamation point (!) as the first character on the line.
NMAKE allows, but does not require, spaces between the name of the directive
and the exclamation point.
The sections that follow describe several of the NMAKE directives. For
information on all the directives, see Section 7.2.5.
3.5.4.1 The !INCLUDE Directive
The !INCLUDE directive is similar to the #include preprocessor directive in
QuickC. When NMAKE encounters !INCLUDE, it reads the contents of another
description file before continuing with the current description file. Use
the !INCLUDE directive to include a standard set of inference rules or
macros in your description files. For example:
!INCLUDE rules.mak
The !INCLUDE directive in this example tells NMAKE to begin reading from the
file RULES.MAK in the current directory and to evaluate the contents of
RULES.MAK as part of the current description file.
If you enclose the file name in angle brackets (<>), NMAKE searches for the
file in the directories specified by the INCLUDE environment variable.
The conditional directives allow you to specify blocks of commands to be
executed depending on the value of a constant expression. A conditional
block has the following form:
!IF expression statements !ELSE statements !ENDIF
If the value of expression is nonzero (true), NMAKE executes the statements
between the !IF directive and the !ELSE directive. If the value of the
constant expression is zero (false), NMAKE executes the statements between
the !ELSE directive and the !ENDIF directive.
Expressions
The expression may consist of integer constants, string constants, or
program invocations that return constants. Integer constants can use the C
unary operators for numerical negation (-), logical negation (!), and one's
complement arithmetic (~); or the C binary operators, including arithmetic
operators, bitwise operators, and logical operators. (See Table for a
complete list.) For string constants, only the equality (==) and inequality
(!=) operators are valid. You can use parentheses to group expressions
wherever necessary. Program invocations, when used in conditionals, must be
enclosed in square brackets.
Recursion
Conditional directives are commonly used to test whether a program executed
successfully. The program can be a DOS command, a program you have written,
or even NMAKE itself. In the following description block, note the use of
the $(MAKE) macro to invoke the program recursively:
$(target) : picture.obj fileio.obj error.obj
# Try to build pix.lib
!IF ![$(MAKE) /f pix.mak]
QLINK $**,$(target),,pix.lib;
COPY pix.lib \mylibs
!ELSE
#Build didn't work, so link with old version
QLINK $**,$(target),,\mylibs\pix.lib;
!ENDIF
In this case, the expression is the value returned by another invocation of
NMAKE. NMAKE, like many programs, returns the value 0 if it executes
successfully and a nonzero errorlevel code otherwise. This is the opposite
of the usual conditional test, which considers zero to be true and nonzero
to be false. Therefore, the !IF directive must test the logical negation of
the expression; that is, it uses the exclamation-point operator outside the
square brackets.
If the library pix.lib is built successfully, NMAKE executes the QLINK and
COPY commands on the two lines immediately following the !IF directive.
If the library cannot be built successfully, NMAKE executes the command
following the !ELSE directive. This command links all the dependents (named
by the special $** macro) with an old version of the library.
3.5.4.3 Testing for Macro Definitions (!IFDEF, !IFNDEF, !UNDEF)
The !IFDEF and !IFNDEF directives test whether a macro is defined and
execute a block of statements depending on the result. You use these two
directives with the !ELSE and !ENDIF directives to construct conditional
blocks, as described in the previous section.
The description block below shows the use of !IFDEF and !IFNDEF directives:
$(target) : picture.obj fileio.obj error.obj
# Macro $(newlib) is defined to use new pix.lib
!IFDEF newlib
QLINK $**,$(target),,pix.lib;
!ELSE
# Just link with existing version
QLINK $**,$(target),,\mylibs\pix.lib;
!ENDIF
When NMAKE encounters the !IFDEF directive, it checks whether or not newlib
has been defined. If so, it executes the QLINK command on the next line. If
not, it executes the QLINK command following the !ELSE directive.
NMAKE considers a macro to be defined if its name appears to the left of an
equal sign anywhere in the description file or on the NMAKE command line.
So, if the MAKEFILE file contains the above description, both of the
commands below would result in execution of the statements following the
!IFDEF directive:
NMAKE newlib=true target=eliot.exe
NMAKE newlib= target=eliot.exe
Even though the second command line sets newlib to the null string,
newlib is still considered defined because its name appears to the left of
the equal sign.
The !IFNDEF directive acts in exactly the same way as !IFDEF, except that
the statements following it are executed only if the macro is not defined.
Once you have defined a macro, the only way to remove its definition is to
use the !UNDEF directive. You might want to remove a macro definition before
including another file, as in the following example:
!UNDEF opts
!INCLUDE newlib.mak
The !UNDEF directive ensures that the macro opts is not defined when the
file NEWLIB.MAK is processed.
3.5.4.4 The !ERROR Directive
The !ERROR directive causes NMAKE to print some text, then quit processing
the description file. This directive is commonly used in conditionals to
terminate execution when fatal errors occur. For example, when NMAKE comes
across the conditional
!IF "$(continue)" == "n"
!ERROR Could not continue because of errors.
!ELSE
QLINK $**, $@;
!ENDIF
it tests the value of the continue macro. If continue holds the string
"n", NMAKE displays the text that follows the !ERROR directive then stops
execution. If continue holds any other value, NMAKE executes the QLINK
command that follows the !ELSE directive.
3.6 Other NMAKE Features
This chapter has covered a subset of NMAKE designed to get you started. In
addition to having the features described in this chapter, the NMAKE utility
lets you
■ Specify additional command-line options
■ Specify more than one set of dependents for a target
■ Create description files that build more than one target, and specify
the target to build at invocation
■ Use additional predefined macros
■ Substitute text within macros
■ Use additional directives
■ Generate response files for use with other programs
■ Use predefined pseudotargets, which provide special rules and
information
As you become more familiar with NMAKE, and as your software projects grow,
you will probably need to use some of these features. See Chapter 7 for more
information.
PART II Reference to QuickC Tools
────────────────────────────────────────────────────────────────────────────
Part 2 of the QuickC Tool Kit is a reference to the tools. Here you will
find complete information on all the options of the utilities. Refer to Part
2 when you have a specific question about one of the tools or when you've
gained experience with the utilities and need to know more about them.
The QCL, LINK, LIB, and NMAKE utilities are covered in greater detail in
Part 2 than in Part 1. In particular, these chapters describe additional
options that work with programs written in other languages (such as Pascal,
FORTRAN, and assembler) or with special hardware.
This chapter describes in detail the QCL command, which you can use to
compile and link QuickC Compiler programs. It explains the rules for giving
input on the QCL command line, describes the options to QCL in alphabetical
order, and shows how to change the stack space allocated to a program.
The chapter provides reference material for programmers who are familiar
with the Microsoft QuickC Compiler in general and the QCL command in
particular. If you are new to the QuickC Compiler, see Chapter 1, "Creating
Executable Programs," in Part 1 of this manual for an introductory approach.
The following list describes input to the QCL command:
Entry Meaning
────────────────────────────────────────────────────────────────────────────
option One or more QCL options; see Section 4.3,
"QCL Options," for descriptions.
file The name of one or more source files,
object files, or libraries. You must
specify at least one file name. QCL
compiles source files and passes the
names of the object files and libraries
to the linker.
lib One or more library names. QCL passes
the names of these libraries to the
linker for processing.
link-opt One or more of the linker options
described in
Chapter 5, "QLINK." The QCL command
passes
these options to the linker for
processing.
Maximum command-line length
You can specify any number of options, file names, and library names, as
long as the length of the command line does not exceed 128 characters.
Specifying file names
Any combination of uppercase and lowercase letters is legal in file names.
Any file name can include a full or partial path name. A full path name
includes a drive name and one or more directory names. A partial path name
omits the drive name, which QCL assumes to be the current drive. If you
don't specify any path name, QCL assumes the file is in the current
directory.
QCL determines how to process each file depending on its file-name
extension, as follows:
Extension Processing
────────────────────────────────────────────────────────────────────────────
C QCL assumes the file is a C source file
and compiles it.
OBJ QCL assumes the file is an object file
and passes its name to the linker.
LIB QCL assumes the file is a library and
passes its name to the linker. The
linker links this library with the
object files QCL created from source
files and the object files given on the
command line.
Any other extension QCL assumes the file is an object file
or no extension and passes its name to the linker.
4.2 How the QCL Command Works
The QCL command follows the procedure described below to create an
executable file from one or more C source files:
1. QCL compiles each source file, creating an object file for each. In
each object file, QCL places the name of the appropriate standard
combined library. The memory model and floating-point-math package
used to compile the program determine this library name. See Section
4.3.1, "/A Options," for more information on the library names.
2. QCL invokes the linker, passing the names of the object files it has
created plus any object files or libraries given on the command line.
QCL also specifies the options listed in the LINK environment
variable. If you use /link to specify linker options on the QCL
command line, these options apply as well. If conflicts occur, options
that follow /link override those in the LINK environment variable.
3. The linker links the object files and libraries named by QCL to create
a single executable file.
Before it creates the executable file, the linker resolves "external
references" in the object files. An external reference is a function
call in one object file that refers to a function defined in another
object file or in a library. To resolve an external reference, the
linker searches for the called function in the following locations in
the order shown:
a. The object files passed by QCL
b. The libraries given on the QCL command line, if any
c. The libraries named in the object files
Example
Assume that you are compiling three C source files: MAIN.C, MOD1.C, and
MOD2.C. Each file includes a call to a function defined in a different file:
■ MAIN.C calls the function named mod1() in MOD1.C and the function
named mod2() in MOD2.C.
■ MOD1.C calls the standard-library functions printf and scanf.
■ MOD2.C calls graphics functions named myline() and mycircle(),
which are defined in a library named MYGRAPH.LIB.
First, compile with a command line of the following form:
QCL MAIN.C MOD1.C MOD2.C /link MYGRAPH.LIB
QCL first compiles the C source files and creates the object files MAIN.OBJ,
MOD1.OBJ, and MOD2.OBJ. QCL then places the name of the standard library
SLIBCE.LIB in each object file.
Next, QCL passes the names of the C source files to the linker. Finally, the
linker resolves the external references as follows:
1. In MAIN.OBJ, the reference to the mod1() function is resolved using
the definition in MOD1.OBJ and the reference to the mod2() function
is resolved using the definition in MOD2.OBJ.
2. In MOD1.OBJ, the references to printf and scanf are resolved using the
definitions in SLIBCE.LIB. The linker uses this library because it
finds the library name within MOD1.OBJ.
3. In MOD2.OBJ, the references to myline and mycircle are resolved using
the definitions in MYGRAPH.LIB.
4.3 QCL Options
Options to the QCL command consist of either a forward slash ( / ) or a dash
(-) followed by one or more letters. Certain QCL options take arguments; in
some of these options, a space is required between the option and the
argument, and in others, no space is allowed. The spacing rules for the
options are given in their descriptions.
────────────────────────────────────────────────────────────────────────────
Important
QCL options (except for the /HELP option) are case-sensitive. For example,
/C and /c are two different options.
────────────────────────────────────────────────────────────────────────────
Command-line order
Options can appear anywhere on the QCL command line. With a few exceptions
(/c, /Fe), each QCL option applies to the files that follow it on the
command line and does not affect files preceding it on the command line.
You can also define QCL options in the CL environment variable; these
options are used every time you invoke QCL. (See Section 4.3.41, "Giving
Options with the CL Environment Variable.")
The remainder of this section describes all the QCL options in alphabetical
order. If an option can take one or more arguments, its format is shown
under an "Option" heading before its description. See Chapter 1, "Creating
Executable Programs," for descriptions of the various categories of QCL
options and the more commonly used options belonging to each category.
4.3.1 /A Options (Memory Models)
Every program's code and data are stored in blocks called "segments." The
memory model of the program determines the organization of these segments.
(See Section 4.3.26 and Appendix B for more information on segments.) The
memory model also determines what kind of executable file is generated. All
models produce a .EXE file, except for the tiny model which produces a .COM
file. QCL offers the memory-model options described in Table 4.1.
Table 4.1 Memory Models
╓┌───────────┌─────────────┌──────────────┌──────────────┌───────────────────╖
QCL Memory Data Code Long
Option Model Segments Segments Form
────────────────────────────────────────────────────────────────────────────
/AT Tiny One segment One segment none
for both data for both data
and code and code
/AS Small One One /Asnd
/AM Medium One One code /Alnd
segment per
module
QCL Memory Data Code Long
Option Model Segments Segments Form
────────────────────────────────────────────────────────────────────────────
module
/AC Compact Multiple data One /Asfd
segments;
data items
must be
smaller than
64K
/AL Large Multiple data One code /Alfd
segments; segment per
data items module
must be
smaller than
64K
/AH Huge Multiple data One code /Alhd
segments; segment per
QCL Memory Data Code Long
Option Model Segments Segments Form
────────────────────────────────────────────────────────────────────────────
segments; segment per
data items module
can be larger
than 64K
By default, the QuickC compiler uses the small memory model.
Uses of memory models
Generally, memory models with multiple code segments can accommodate larger
programs than can memory models with one code segment. Also, memory models
with multiple data segments can accommodate more data-intensive programs
than can memory models with one data segment. Programs with multiple code or
data segments, however, are usually slower than programs with a single code
or data segment. It is often more efficient to compile with the smallest
possible memory model and use the near, far, and huge keywords to override
the default addressing conventions for any data items or functions that
can't be accommodated in that model. (Consult Appendix B for more
information about these keywords and their interactions with standard memory
models.)
Customized memory models
QCL also supports customized memory models, in which different features from
standard memory models are combined. You specify a customized memory model
with the /Astring option, where string is composed of three letters that
specify the code pointer size, the data pointer size, and the stack and data
segment setup, respectively. All three letters must be present, but they can
appear in any order. The allowable letters appear in Table 4.2.
Table 4.2 Customized Memory Model Codes
╓┌───────────────┌─────────┌─────────────────────────────────────────────────╖
Group Code Description
────────────────────────────────────────────────────────────────────────────
Code pointers s Small
l Large
Data pointers n Near
f Far
h Huge
Segment setup d SS == DS
u SS != DS; DS loaded for each function entry
w SS != DS; DS not loaded at function entry
As examples, the customized representations of the standard memory models
appear in the last column of Table 4.1.
The segment setup codes can also be given as separate options, when used to
modify a standard memory model. For example, the options /AS /Au specify the
small model, plus they force DS to be loaded at function entry.
Memory models and default libraries
The memory-model and math options used to compile the program determine the
library that the linker searches to resolve external references. The library
name is mLIBCf.LIB, where the memory-model option determines m: S for small
(default) or tiny model, M for medium model, C for compact model, or L for
large or huge model. The math option (see Section 4.3.12, "/FP Options")
determines f: E for emulator (default) or 7 for 8087/80287 option.
4.3.2 /batch (Compile in Batch Mode)
The /batch option assumes that QCL is being executed from a batch file.
Normally, if QCL cannot find one of the programs needed to complete the
compilation, it displays a prompt requesting that the appropriate disk be
inserted. If you specify the /batch option, QCL simply terminates
compilation with an error.
4.3.3 /c (Compile without Linking)
The /c option tells the QCL command to compile all C source files given on
the command line, creating object files, but not to link the object files.
QCL does not produce an executable file. Regardless of its position on the
command line, this option applies to all source files on the command line.
Example
QCL FIRST.C SECOND.C /c THIRD.OBJ
This example compiles FIRST.C, creating the object file FIRST.OBJ, and
SECOND.C, creating the object file SECOND.OBJ. No processing is performed
with THIRD.OBJ because QCL skips the linking step.
4.3.4 /C (Preserve Comments during Preprocessing)
The /C (for "comment") option preserves comments during preprocessing. If
you don't specify this option, the preprocessor strips comments from a
source file since they do not serve any purpose in later stages of
compiling.
This option is valid only if the /E, /P, or /EP option is also used.
Example
QCL /P /C SAMPLE.C
This example produces a listing named SAMPLE.I. The listing file contains
the original source file, including comments, with all preprocessor
directives expanded or replaced.
4.3.5 /D (Define Constants and Macros)
Option
/D identifier «=«{string|number}»»
Use the /D option to define constants or macros for your source file.
The identifier is the name of the constant or macro. It may be defined as a
string or as a number. The string must be enclosed in quotes if it includes
spaces.
If you leave out both the equal sign and the string or number, the
identifier is assumed to be defined, and its value is set to 1. For example,
/DSET is sufficient to define a macro named SET with a value of 1.
Use the /D option in combination with the #if directive to conditionally
compile source files.
Removing definitions
If you have defined a numeric constant, using the equal sign with no number
removes the definition of that constant from the source file. For example,
to remove all occurrences of RELEASE, use the following option:
/DRELEASE=
Note that the identifier argument is case sensitive. For example, the /D
option above would have no effect on a constant named release that is
defined in the source file.
Defining macros and constants with the /D option has the same effect as
using a #define preprocessor directive at the beginning of your source file.
The identifier is defined until either an #undef directive in the source
file removes the definition or the compiler reaches the end of the file.
Duplicate definitions
If an identifier defined in a /D option is also defined within the source
file, QCL uses the definition on the command line until it encounters the
redefinition of the identifier in the source file, as illustrated in Figure
4.1.
(This figure may be found in the printed book.)
The /D option has the same effect as the Define text box in the QuickC
environment.
Example
#if !defined(RELEASE)
_nheapchk();
#endif
This code fragment calls a function to check the near heap unless the
constant RELEASE is defined. While the program is under development, you
can leave RELEASE undefined and perform heap checking to find bugs.
Assuming the program name is BIG.C, you would compile with the following
command:
QCL BIG.C
After you have found all of the bugs in the program, you can define RELEASE
in a /D option so that the program will run faster, as follows:
QCL /DRELEASE BIG.C
4.3.6 /E (Copy Preprocessor Output to Standard Output)
The /E option copies output from the preprocessor to the standard output
(usually your terminal). This output is identical to the original source
file except that all
preprocessor directives are carried out, macro expansions are performed, and
comments are removed. You normally use the /E option with the /C option (see
Section 4.3.4), which preserves comments in the preprocessed output. DOS
redirection can be used to save the output in a disk file.
The /E option also places a #line directive at the beginning and end of each
included file and around lines removed by preprocessor directives that
specify conditional compilation.
Use this option when you want to resubmit the preprocessed listing for
compilation. The #line directives renumber the lines of the preprocessed
file so that errors generated during later stages of processing refer to the
line numbers of the original source file rather than to the preprocessed
file.
The /E option suppresses compilation. QCL does not produce an object file or
map file, even if you specify the /Fo or /Fm option on the QCL command line.
Example
QCL /E /C ADD.C > PREADD.C
The command above creates a preprocessed file with inserted #line directives
from the source file ADD.C. The output is redirected to the file PREADD.C.
4.3.7 /EP (Copy Preprocessor Output to Standard Output)
The /EP option is similar to the /E option: it preprocesses the C source
file and copies preprocessor output to the standard output. Unlike the /E
option, however, the /EP option does not add #line directives to the output.
Preprocessed output is identical to the original source file except that all
preprocessor directives are carried out, macro expansions are performed, and
comments are removed. You can use the /EP option with the /C option (see
Section 4.3.4), which preserves comments in the preprocessed output.
The /EP option suppresses compilation; QCL does not produce an object file
or map file, even if you specify the /Fo or /Fm option on the QCL command
line.
Example
QCL /EP /C ADD.C
The command above creates a preprocessed file from the source file ADD.C. It
preserves comments but does not insert #line directives. The output appears
on the screen.
4.3.8 /F (Set Stack Size)
Option
/F number
The /F option sets the program stack size to number bytes, where number is a
hexadecimal number in the range 0001 to FFFF. Decimal and octal numbers are
not allowed. If you don't specify this option, a stack size of 2K is used by
default.
You may want to increase the stack size if your program gets stack-overflow
diagnostic messages. Conversely, if your program uses the stack very little,
you may want to decrease the size of your program by reducing the stack
size. In general, if you modify the stack size, do not use the /Gs option to
suppress stack checking.
4.3.9 /Fe (Rename Executable File)
Option
/Feexefile
By default, QCL names the executable file with the base name of the first
file (source or object) on the command line plus the extension .EXE. The /Fe
option lets you give the executable file a different name or create it in a
different directory.
Because QCL creates only one executable file, you can give the /Fe option
anywhere on the command line. If more than one /Fe option appears, QCL gives
the executable file the name specified in the last /Fe option on the command
line.
The /Fe option applies only in the linking stage. If you specify the /c
option to suppress linking, /Fe has no effect.
Path names and extensions
The exefile argument must appear immediately after the option with no
intervening spaces. The exefile argument can be a file specification, a
drive name, or a path specification. If exefile is a drive name or path
specification, the QCL command creates the executable file in the given
location, using the default name (base name of the first file plus .EXE). A
path specification must end with a backslash ( \ ) so that QCL can
distinguish it from an ordinary file name.
You are free to supply any name and any extension you like for exefile. If
you give a file name without an extension, QCL automatically appends the
EXE extension.
Examples
QCL /FeC:\BIN\PROCESS *.C
The example above compiles and links all source files with the extension .C
in the current directory. The resulting executable file is named PROCESS.EXE
and is created in the directory C:\BIN.
QCL /FeC:\BIN\ *.C
The preceding example is similar to the first example except that the
executable file, instead of being named PROCESS.EXE, is given the same base
name as the first file compiled. The executable file is created in the
directory C:\BIN.
4.3.10 /Fm (Create Map File)
Option
/Fm «mapfile»
The /Fm option produces a map file. The map file contains a list of segments
in order of their appearance within the load module.
Path names and extensions
The mapfile argument must follow the /Fm option immediately with no
intervening spaces. The mapfile can be a file specification, a drive name,
or a path specification. It can also be omitted.
If you give just a path specification as the mapfile argument, the path
specification must end with a backslash ( \ ) so that QCL can distinguish it
from an ordinary file name. For example, to create a map file in the path
C:\LIST, the appropriate /Fm option is /FmC:\LIST\ .
If you do not specify a name for the map file or if you supply only a drive
name or path, QCL uses the base name of the first source or object file on
the command line plus the extension .MAP.
A fragment of a sample map file is shown below:
Start Stop Length Name Class
00000H 01E9FH 01EA0H _TEXT CODE
01EA0H 01EA0H 00000H C_ETEXT ENDCODE
.
.
.
Segment information
The information in the Start and Stop columns shows the 20-bit address
(in hexadecimal) of each segment, relative to the beginning of the load
module. The load module begins at location zero. The Length column gives
the length of the segment in bytes. The Name column gives the name of the
segment, and the Class column gives information about the segment type.
Group information
The starting address and name of each group appear after the list of
segments. A sample group listing is shown below:
Origin Group
01EA:0 DGROUP
In this example, DGROUP is the name of the data group. DGROUP is used for
all near data (that is, all data not explicitly or implicitly placed in
their own data segment) in Microsoft QuickC programs.
Global symbols
The map file shown below contains two lists of global symbols: the first
list is sorted in ASCII-character order by symbol name and the second is
sorted by symbol address. The notation Abs appears next to the names of
absolute symbols (symbols containing 16-bit constant values that are not
associated with program addresses).
Global symbols in a map file usually have one or more leading underscores
because the QuickC compiler adds an underscore to the beginning of variable
names. Many of the global symbols that appear in the map file are symbols
used internally by the QuickC compiler and the standard libraries.
The addresses of the external symbols show the location of the symbol
relative to zero (the beginning of the load module).
Program entry point
Following the lists of symbols, the map file gives the program entry point,
as shown in the following example:
Program entry point at 0000:0129
────────────────────────────────────────────────────────────────────────────
NOTE
If you use the /Fm option with the /Gi option (for incremental compilation),
QCL produces a segmented-executable map file rather than a DOS executable
map file. The segment addresses in the file are different from those in DOS
map files, and the file itself has a different format.
────────────────────────────────────────────────────────────────────────────
4.3.11 /Fo (Rename Object File)
Option
/Foobjfile
By default, QCL gives each object file it creates the base name of the
corresponding source file plus the extension .OBJ. The /Fo option lets you
give different names to object files or create them in a different
directory. If you are compiling more than one source file, you can use the
/Fo option with each source file to rename the corresponding object file.
Keep the following rules in mind when using this option:
■ The objfile argument must appear immediately after the option, with no
intervening spaces.
■ Each /Fo option applies only to the next source file on the command
line.
Path names and extensions
You are free to supply any name and any extension you like for objfile.
However, it is recommended that you use the conventional .OBJ extension
since the linker and the LIB library manager use .OBJ as the default
extension when processing object files.
If you do not give a complete object-file name with the /Fo option (that is,
if you do not give an object-file name with a base and an extension), QCL
names the object file according to the following rules:
■ If you give an object-file name without an extension (such as TEST),
QCL automatically appends the .OBJ extension.
■ If you give an object-file name with a blank extension (such as
TEST.), QCL leaves the extension blank.
■ If you give only a drive or directory specification following the /Fo
option, QCL creates the object file on that drive or directory and
uses the default file name (the base name of the source file plus
.OBJ).
You can use this option to create the object file in another directory or on
another disk. When you give only a directory specification, the directory
specification must end with a backslash ( \ ) so that QCL can distinguish
between a directory specification and a file name.
Examples
QCL /FoB:\OBJECT\ THIS.C
In the example above, QCL compiles the source file THIS.C and gives the
resulting object file the name THIS.OBJ (by default). The directory
specification B: \OBJECT\ tells QCL to create THIS.OBJ in the directory
named \OBJECT on drive B.
In the example above, the first /Fo option tells the compiler to create the
object file THIS.OBJ (the result of compiling THIS.C) in the \OBJECT
directory. The second /Fo option tells the compiler to create the object
file NEWTHOSE.OBJ (the result of compiling THOSE.C) in the \SRC directory.
The compiler also creates the object file THAT.OBJ (the result of compiling
THAT.C) in the current directory.
The /FPi and /FPi87 options specify how your program handles
floating-point-math operations.
4.3.12.1 /FPi (Emulator)
Use the /FPi option if you do not know whether an 8087 or 80287 math
coprocessor will be available at run time. Programs compiled with /FPi work
as follows:
■ If a coprocessor is present at run time, the program uses the
coprocessor.
■ If no coprocessor is present or if the NO87 environment variable has
been set, the program uses the emulator.
The /FPi option generates in-line instructions for an 8087 or 80287
coprocessor and places the name of the emulator library (mLIBCE.LIB) in the
object file. At link time, you can specify an 8087/80287 library
(mLIBC7.LIB) instead. If you do not choose a floating-point option, QCL uses
the /FPi option by default.
Interrupt fixups
This option works whether or not a coprocessor is present because the QuickC
compiler does not generate "true" in-line 8087/80287 instructions. Instead,
it generates software interrupts to library code. The library code, in turn,
fixes up the interrupts to use either the emulator or the coprocessor,
depending on whether a coprocessor is present. The fixups can be removed by
linking the file RMFIXUP.OBJ with the C program. Linking this file with
QuickC programs can save execution time (the time required to fix up all the
interrupts the first time). However, a C program linked with RMFIXUP.OBJ
will run only if a coprocessor is present.
4.3.12.2 /FPi87 (Coprocessor)
The /FPi87 option includes the name of an 8087/80287 library (mLIBC7.LIB) in
the object file. At link time, you can override this option and specify an
emulator library (mLIBCE.LIB) instead so that the program will run on
computers without coprocessors.
If you use the /FPi87 option and link with mLIBC7.LIB, an 8087 or 80287
coprocessor must be present at run time; otherwise, the program fails and
the following error message is displayed:
run-time error R6002
- floating point not loaded
If you compile with /FPi87 and link with mLIBCE.LIB, you can set the NO87
environment variable to suppress the use of the coprocessor (see Section
4.3.12.5).
Compiling with the /FPi87 option results in the smallest, fastest programs
possible for handling floating-point arithmetic.
4.3.12.3 Library Considerations for Floating-Point Options
You may want to use libraries in addition to the default library for the
floating-point option you have chosen on the QCL command line. For example,
you may want to create your own libraries or object files, then link them at
a later time with object files that you have compiled using different QCL
options.
You must be sure that you use only one standard combined C library when you
link. You can control which library QLINK uses in one of two ways:
1. Make sure the first object file passed to the linker has the name of
the desired library. For example, if you want to use an 8087/80287
library, give the /FPi87 option before the first source-file name on
the QCL command line; or, give the name of an object file compiled
with /FPi87 as the first file name on the command line. All
floating-point calls in this object file refer to the 8087/80287
library.
2. Give the /NOD (no default-library search) option after the /link
option on the QCL command line. Then specify the name of the library
you want to use on the QCL command line. The /NOD option overrides the
library names embedded in the object files. Because the linker
searches libraries given on the command line before it searches
libraries named in object files, all floating-point calls will refer
to the libraries you specify.
Removing library names
Another complication might arise if you create your own libraries: normally,
each module in the library you create contains a standard-library name, and
the linker tries to search the standard libraries named in the modules when
it links with your library.
The safest course, especially when you are distributing libraries to others,
is to use the /Zl option when you compile the object files that make up your
libraries. The /Zl option tells the compiler not to put library names in the
object files. Later, when you link other object files with your library, the
standard library used for linking will depend only on the floating-point and
memory-model options used to compile those object files.
Examples
QCL CALC.C ANOTHER SUM
In the example above, no floating-point option is given, so QCL compiles the
source file CALC.C with the default floating-point option, /FPi. The /FPi
option generates in-line instructions and selects the small-model-emulator
combined library (SLIBCE.LIB), which is the default.
In the example above, QCL compiles CALC.C with the /FPi87 option, which
selects the SLIBC7.LIB library. The /link option, however, overrides the
default library specification: the /NOD option suppresses the search for the
default library, and the alternate math library (SLIBCE.LIB) is specified.
QLINK uses SLIBCE.LIB when it creates the resulting executable file,
CALC.EXE.
4.3.12.4 Compatibility between Floating-Point Options
Each time you compile a source file, you can specify a floating-point
option. When you link two or more source files to produce an executable
program file, you are responsible for ensuring that floating-point
operations are handled in a consistent way.
Example
QCL /AM CALC.C ANOTHER SUM /link MLIBC7.LIB /NOD
The preceding example compiles the program CALC.C with the medium-model
option (/AM). Because no floating-point option is specified, the default
(/FPi) is used. The /FPi option generates in-line 8087/80287 instructions
and specifies the emulator library MLIBCE.LIB in the object file. The /link
field specifies the /NOD option and the name of the medium-model 8087/80287
library, MLIBC7.LIB. Specifying the 8087/80287 library forces the program to
use an 8087 coprocessor; the program fails if a coprocessor is not present.
4.3.12.5 The NO87 Environment Variable
Programs compiled with the /FPi option automatically use an 8087 or 80287
coprocessor at run time if one is installed. You can override this and force
the use of the emulator instead by setting an environment variable named
NO87.
Coprocessor-suppression message
If NO87 is set to any value when the program is executed, the program will
use the emulator even if a coprocessor is present. When this occurs, the
NO87 setting is displayed on the standard output as a message. The message
is displayed only if a coprocessor is present and its use is suppressed; if
no coprocessor is present, no message appears. If you want to force use of
the emulator, but don't want a message to appear, set NO87 equal to one or
more spaces. The variable is still considered to be defined.
Note that the presence or absence of the NO87 definition determines whether
use of the coprocessor is suppressed. The actual value of the NO87 setting
is used only for the message.
The NO87 variable takes effect with any program linked with an emulator
library (mLIBCE.LIB). It has no effect on programs linked with 8087/80287
libraries (mLIBC7.LIB).
Examples
SET NO87=Use of coprocessor suppressed
The example above causes the message Use of coprocessor suppressed to
appear when a program that would use an 8087 or 80287 coprocessor is
executed on a computer that has such a coprocessor.
SET NO87=space
The example above sets the NO87 variable to the space character. Use of the
coprocessor is still suppressed, but no message is displayed.
4.3.12.6 Standard Combined Libraries
Table 4.3 shows each combination of memory-model and floating-point options
and the corresponding library name that QCL embeds in the object file.
Table 4.3 QCL Options and Default Libraries
╓┌──────────────────────┌────────────────────┌───────────────────────────────╖
Floating-Point Option Memory-Model Option Default Library
────────────────────────────────────────────────────────────────────────────
/FPi87 /AT or /AS SLIBC7.LIB
/AM MLIBC7.LIB
/AC CLIBC7.LIB
/AL or /AH LLIBC7.LIB
Floating-Point Option Memory-Model Option Default Library
────────────────────────────────────────────────────────────────────────────
/AL or /AH LLIBC7.LIB
/FPi /AT or /AS SLIBCE.LIB
/AM MLIBCE.LIB
/AC CLIBCE.LIB
/AL or /AH LLIBCE.LIB
────────────────────────────────────────────────────────────────────────────
4.3.13 /G0, /G1, /G2 (Generate Instructions for 8086, 80186, or 80286
Processor)
If you are writing programs for a machine with an 80186 or 80286 processor,
you can use the /G1 or the /G2 option, respectively, to enable the
instruction set for those processors. When you use either of these options,
the compiler automatically defines the identifier M_I286.
Although it is sometimes advantageous to enable the appropriate instruction
set, you may not always wish to do so. If you have an 80286 processor, for
example, but you want your program to be able to run on an 8086, do not
compile with the /G2 option.
The /G0 option enables the instruction set for the 8086/8088 processor. You
do not have to specify this option explicitly because QCL uses the 8086/8088
instruction set by default. Programs compiled with this option will also run
on machines with 80186 and 80286 processors but will not take advantage of
any processor-specific instructions. When you specify the /G0 option, the
compiler automatically defines the identifier M_I8086.
If your program includes in-line assembler code that uses a mnemonic
instruction supported only by the 80186/87 or 80286/87 processors, you must
compile with the /G1 or the /G2 option, respectively; compiling with /G0
results in an error. Note that you cannot use 80186 or 80286 mnemonics as
labels, even if you are compiling for an 8086/8088.
These options apply to all file names that follow on the command line until
another /G0, /G1 or /G2 option appears.
4.3.14 /Gc, /Gd (Use FORTRAN/Pascal or C Calling Convention)
The _fortran, _pascal, and _cdecl keywords along with the /Gc and /Gd
options, allow you to control the function-calling and naming conventions so
that your QuickC programs can call and be called by functions that are
written in FORTRAN or Pascal.
Parameter-passing conventions
Because functions in QuickC programs can take a variable number of
arguments, QuickC must handle function calls differently from languages such
as Pascal and FORTRAN. Pascal and FORTRAN normally push actual parameters to
a function in left-to-right order so that the last argument in the list is
the last one pushed on the stack. In contrast, because QuickC functions do
not always know the number of actual parameters, they must push their
arguments from right to left, so that the first argument in the list is the
last one pushed.
Stack-cleanup conventions
Another difference between QuickC programs and FORTRAN or Pascal programs is
that in QuickC programs, the calling function must remove the arguments from
the stack. In Pascal and FORTRAN programs, the called function must remove
the arguments. If the code for removing arguments is in the called function
(as in Pascal and FORTRAN), it appears only once; if it is in the calling
function (as in QuickC), it appears every time there is a function call.
Because a typical program has more function calls than functions, the
Pascal/FORTRAN method results in slightly smaller, more efficient programs.
The _pascal and _fortran keywords
The QuickC compiler can generate the Pascal/FORTRAN calling convention in
one of several ways. The first is through the use of the _pascal and
_fortran keywords. When these keywords are applied to functions, or to
pointers to functions, they indicate a corresponding Pascal or FORTRAN
function (or a function that uses the Pascal/FORTRAN calling convention).
Therefore, the correct calling convention must be used. In the following
example, sort is declared as a function using the alternative calling
convention:
short pascal sort(char *, char *);
The _pascal and _fortran keywords can be used interchangeably. Use them when
you want to use the left-to-right calling sequence for selected functions
only.
The /Gc option
The second method for generating the Pascal/FORTRAN calling convention is to
use the /Gc option. If you use the /Gc option, the entire module is compiled
using the alternative calling convention. You might use this method to make
it possible to call all the functions in a QuickC module from another
language or to gain the performance and size improvement provided by this
calling convention.
When you use /Gc to compile a module, the compiler assumes that all
functions called from that module use the Pascal/FORTRAN calling convention,
even if the functions are defined outside that module. Therefore, using /Gc
would normally mean that you cannot call or define functions that take
variable numbers of parameters and that you cannot call functions such as
the QuickC library functions that use the QuickC calling sequence. In
addition, if you compile with the /Gc option, either you must declare the
main function in the source program with the _cdecl keyword, or you must
change the start-up routine so that it uses the correct naming and calling
conventions when calling main.
The _cdecl keyword
The _cdecl keyword in QuickC is the "inverse" of the _fortran and _pascal
keywords. When applied to a function or function pointer, it indicates that
the associated function is to be called using the normal QuickC calling
convention. This allows you to write QuickC programs that take advantage of
the more efficient Pascal/FORTRAN calling convention while still having
access to the entire QuickC library, other QuickC objects, and even
user-defined functions that accept variable-length argument lists. The
_cdecl keyword takes precedence over the /Gc option.
For convenience, the _cdecl keyword has already been applied to
run-timelibrary function declarations in the include files distributed with
the QuickC compiler. Therefore, your QuickC programs can call the library
functions freely, no matter which calling conventions you compile with. Just
make sure to use the appropriate include file for each library function the
program calls.
The /Gd option
The /Gd option has the same effect as the _cdecl keyword. It specifies that
the entire module should use the C calling convention. This option is on by
default.
Naming conventions
Use of the _pascal and _fortran keywords, or the /Gc option, also affects
the naming convention for the associated item (or, in the case of /Gc, all
items): the name is converted to uppercase letters, and the leading
underscore that QuickC normally prefixes is not added. The _pascal and
_fortran keywords can be applied to data items and pointers, as well as to
functions; when applied to data items or pointers, these keywords force the
naming convention described above for that item or pointer.
The _pascal, _fortran, and _cdecl keywords, like the _near, _far, and _huge
keywords, are disabled by use of the /Za option. If this option is given,
these names are treated as ordinary identifiers, rather than keywords.
Examples
int _cdecl var_print(char*,...);
In the example above, var_print is declared with a variable number of
arguments using the normal right-to-left QuickC function-calling convention
and naming conventions. The _cdecl keyword overrides the left-to-right
calling sequence set by the /Gc option if the option is used to compile the
source file in which this declaration appears. If this file is compiled
without the /Gc option, _cdecl has no effect since it is the same as the
default QuickC convention.
float *pascal nroot(number, root);
The example above declares nroot to be a function returning a pointer to a
value of type float. The function nroot uses the default calling sequence
(left-to-right) and naming conventions for Microsoft FORTRAN and Pascal
programs.
4.3.15 /Ge, /Gs (Turn Stack Checking On or Off)
Stack probes
A "stack probe" is a short routine called on entry to a function to verify
that the program stack has enough room to allocate local variables required
by the function. The stack-probe routine is called at every function-entry
point. Ordinarily, the stack-probe routine generates a stack-overflow
message if the required stack space is not available. When stack checking is
turned off, the stack-probe routine is not called, and stack overflow can
occur without being diagnosed (that is, no stack-overflow message is
printed).
The QuickC compiler uses stack probes to guard against possible execution
errors. These stack probes are used whenever the /Ge option (the default) is
in effect. You can remove the stack probes by using either the /Gs option or
the check_stack pragma, which will reduce the size of a program and speed up
execution slightly. Note that the /Gs option and the check_stack pragma have
no effect on standard C library routines, only on the functions you compile.
When to use the /Gs option
Use the /Gs option when you want to turn off stack checking for an entire
module, if you know that the program does not exceed the available stack
space. For example, stack probes may not be needed for programs that make
very few function calls or that have only modest local-variable
requirements. In the absence of the /Gs option, stack checking is on. The
/Gs option should be used with great care. Although it can make programs
smaller and faster, it may mean that the program will not be able to detect
certain execution errors.
When to use the check_stack pragma
Use the check_stack pragma when you want to turn stack checking on or off
only for selected routines, leaving the default (as determined by the
presence or absence of the /Gs option) for the rest. When you want to turn
off stack checking, put the following line before the definition of the
function you don't want to check:
#pragma check_stack (off)
Note that the preceding line disables stack checking for all routines that
follow it in the source file, not just the routines on the same line. To
reinstate stack checking, insert the following line:
#pragma check_stack (on)
If you don't give an argument for the check_stack pragma, stack checking
reverts to the behavior specified on the command line: disabled if the /Gs
option is given, or enabled if it is not. The interaction of the check_stack
pragma with the /Gs option is summarized in Table 4.4.
Table 4.4 Using the check_stack Pragma
╓┌────────────────────────┌────────────────────────┌─────────────────────────╖
Compiled with /Gs
Syntax Option? Action
────────────────────────────────────────────────────────────────────────────
#pragma check_stack() Yes Turns off stack checking
for routines that follow
#pragma check_stack() No Turns on stack checking
Compiled with /Gs
Syntax Option? Action
────────────────────────────────────────────────────────────────────────────
#pragma check_stack() No Turns on stack checking
for routines that follow
#pragma check_stack(on) Yes or no Turns on stack checking
for routines that follow
#pragma Yes or no Turns off stack checking
check_stack(off) for routines that follow
────────────────────────────────────────────────────────────────────────────
NOTE
For versions of Microsoft QuickC prior to 2.0, the check_stack pragma had a
different format: check_stack(+) to enable stack checking and check_stack(-)
to disable stack checking. Although the Microsoft QuickC compiler still
accepts this format, its use is discouraged because it may not be supported
in future versions.
────────────────────────────────────────────────────────────────────────────
Example
QCL /Gs FILE.C
This example optimizes the file FILE.C by removing stack probes with the /Gs
option. If you want stack checking for only a few functions in FILE.C, you
can use the check_stack pragma before and after the definitions of functions
you want to check.
4.3.16 /Gi (Use Incremental Compilation)
Option
/Gi«mdtname»
When you specify the /Gi option, QCL compiles only those functions in each C
source file that have changed since the last time the source file was
compiled. The process of compiling only the changed functions in a source
file is known as "incremental compilation." Because the compiler does not
need to handle the entire source file, incremental compilation is
considerably faster than regular compilation. However, the object files
created and the code generated when you compile incrementally may be larger.
If you specify any of the optimization (/Ostring) options on the same line
with /Gi, the compiler ignores the /Gi option.
If you own the Microsoft C Optimizing Compiler version 5.1 or earlier, and
you wish to use the CodeView debugger, do not use the /Gi option or the
related /Li option (for incremental linking). You can use the QuickC
integrated debugger, or the CodeView debugger included with the Microsoft C
Professional Development System version 6.0, on programs compiled with /Gi
and /Li.
Module-description table (MDT)
The compiler tracks changes for incremental compilation in a file known as a
"module-description table," or MDT. A single MDT can contain change
information for multiple source files. If you specify mdtname, the compiler
saves change information for all source files in a single MDT named mdtname.
If you do not specify mdtname, the compiler creates one MDT for each source
file named on the command line. Each MDT has the base name of the source
file and the .MDT extension.
The types of changes made to a source file determine whether the compiler
can incrementally compile a source file and whether the compiler creates or
updates the corresponding MDT.
Incrementally compile, update MDT
Except as noted below, if changes are confined to function bodies, the QCL
command compiles only those changed functions and the "global regions" of
the source file. Global regions are the parts of the source file between the
closing curly brace (}) of one function and the opening curly brace ({) of
the next function (see Figure 4.2). The compiler also updates the MDT to
reflect changes to the source file.
(This figure may be found in the printed book.)
If a global region of the source file has changed, QCL recompiles from the
point at which the change occurred. A change in a global region is any
change in the storage-class specifier, type specifier, function declarator,
or formal-parameter declarations of a function. Similarly, if a file
specified in an #include directive has a more recent modification date than
the including object module, QCL recompiles the source file from the point
at which the #include directive appears. In addition, if a function is
defined within an include file, the source file is recompiled from the start
of the function.
Compile whole program, don't update MDT
The compiler must recompile an entire source file, but does not update its
MDT, in both of these cases:
■ A function definition appears within an include file.
■ The compiler does not have enough memory to create the MDT.
Using function prototypes
For fastest compilation with /Gi, use a prototype for each function in your
program. A function prototype lists the name and type of the function and
the name and type of each of its parameters. (See Chapter 2, "Functions," in
C for Yourself for more information.) The C include files that Microsoft
supplies contain prototypes for all the functions in the C run-time library.
The information in the prototypes lets the compiler check the number and
type of arguments to the function.
If you use the /Gi option and your program contains functions without
corresponding prototypes, the compiler issues the following level 3 warning
message:
no function prototype given
Compilation errors
When the /Gi option is given and errors occur during compilation, the
compiler still creates a partial object file; that is, it generates object
code up to the point at which the error occurs. It places a record in each
object file indicating that the object file is invalid. If you try to link
one of these object files, the linker issues the following error message:
invalid object due to aborted incremental compile
Incremental linking
When the compiler can perform incremental compilation, it invokes a special
form of the linker that performs "incremental linking." Like incremental
compiling, incremental linking links only the object files that have changed
since the previous link. No library searches are performed; the assumption
is that the libraries are exactly the same as in the previous link.
Incremental linking is considerably faster than regular linking. If any of
the changes to the program prevent QuickC from performing an incremental
link, it automatically performs a full link. If you specify the /c option
along with the /Gi option, QCL performs incremental compilation, but does
not invoke any linker.
If you use the /Gi option with the /Fm option (which produces a map file),
the map file is a segmented-executable map file rather than a DOS-executable
map file. The segment addresses in the file are different from those in DOS
map files, and the file itself has a different format.
────────────────────────────────────────────────────────────────────────────
Examples
For the following examples, assume there are three C source files named
MOD1.C, MOD2.C, and MOD3.C .
QCL /Gi MOD1.C MOD2.C MOD3.C
The example above incrementally compiles and links the three C source files.
Three MDTs are created or updated: MOD1.MDT, MOD2.MDT, and MOD3.MDT.
QCL /GiMYMDT.MDT MOD1.C MOD2.C MOD3.C
The example above has the same effect as the example preceding it, except
that the compiler creates or updates only one MDT named MYMDT.MDT. This MDT
includes all change-control information for the three C source files.
4.3.17 /Gr (Register Calling Convention)
Normally, your program passes parameters to functions on the stack. The /Gr
option causes your program to pass parameters in registers instead. This
calling convention decreases execution time if you are using the Microsoft C
Professional Development System version 6.0, but it gives no advantage if
you are using QuickC. Therefore, you should use the /Gr option only if you
plan on using the C Professional Development System for your final
compilation.
This method of parameter passing is not appropriate for all functions. The
/Gr option enables it for all eligible functions, and the _fastcall keyword
enables it on a function-by-function basis. The _fastcall keyword cannot be
used with the _cdecl or _pascal keywords.
Because the 80x86 processor has a limited number of registers, only the
first three parameters are passed in registers; the remaining parameters are
passed using the FORTRAN/Pascal calling convention (see the /Gc option).
Note that the compiler allocates different registers for variables declared
as register and for passing arguments using the register calling convention.
Passing arguments in registers does not conflict with any register variables
that you may have declared.
────────────────────────────────────────────────────────────────────────────
IMPORTANT
Exercise caution when using the register calling convention for any function
written in in-line assembly language. Your use of registers in assembly
language could conflict with the compiler's use of registers for storing
parameters.
────────────────────────────────────────────────────────────────────────────
4.3.17.1 The _fastcall Calling Convention
The following section describes the details of the _fastcall calling
convention. This information is for assembly-language programmers who are
interested in using either the in-line assembler or the Microsoft Macro
Assembler to write functions declared as _fastcall.
The register usage documented here applies only to Microsoft QuickC version
2.5 and Microsoft C Professional Development System version 6.0. It may
change in future releases of either compiler.
────────────────────────────────────────────────────────────────────────────
4.3.17.2 Argument-Passing Convention
The _fastcall register calling convention is "strongly typed": the compiler
allocates arguments to registers according to the argument's data types.
Strong typing allows the compiler to generate better code. Because the
compiler chooses registers depending on the type of the argument and not in
a strict linear order, the calling program and called function must agree on
the types of the arguments in order to communicate data correctly.
For each type of argument, there is a list of register candidates. Each
argument is put in the first register candidate that does not already
contain an argument. If no suitable register remains unused, the arguments
are pushed onto the stack in left-to-right order. The following list shows
the basic types and the register candidate for each:
Type Register Candidates
────────────────────────────────────────────────────────────────────────────
character AL, DL, BL
unsigned character AL, DL, BL
integer AX, DX, BX
unsigned integer AX, DX, BX
long integer DX:AX
unsigned long integer DX:AX
near pointer BX, AX, DX
Structures and unions are always pushed onto the stack, as are all
floating-point types.
4.3.17.3 Return Value Convention
The _fastcall return value convention is based on the size of the return
value, except with floating-point types. All floating point types are
returned on the top of the numeric coprocessor stack (whether real or
emulated). The following list shows how values 4 bytes or smaller, including
unions and structures, are returned from a _fastcall function.
Size Return Convention
────────────────────────────────────────────────────────────────────────────
1 Byte AL Register
2 Bytes AX Register
4 Bytes DX, AX Registers (for pointers, the
segment is returned in DX, the offset in
AX; for long integers, the
most-significant byte is returned in DX,
leastsignificant byte in AX)
The method for returning values 4 bytes or smaller is the same as for
functions declared as _cdecl. To return structures and unions larger than 4
bytes, the calling function passes a hidden parameter after the rest of the
parameters have been pushed. This parameter is a near pointer, based in the
segment specified by the stack register (SS), to a buffer in which the value
is to be returned. A far pointer to SS:hidden-param is returned in DX:AX.
This is the same convention for returning structures as _pascal.
4.3.17.4 Stack Adjustment Convention
When a function declared as _cdecl terminates, the calling program clears
the stack of the parameters it passed. However, functions declared as
_fastcall must pop the parameters off the stack themselves. The calling
function does not adjust the stack after function return.
4.3.17.5 Register Preservation Requirement
All functions must preserve the DS, BP, SI, and DI registers. Your _fastcall
function can modify the values in AX, DX, and BX.
The compiler can make significant optimizations by keeping certain values in
registers. One such value is the base for variables declared as _based. This
value is normally stored in the ES register. By declaring functions as
_fastcall, you guarantee that the ES register is preserved and that ES does
not have to be reloaded.
────────────────────────────────────────────────────────────────────────────
4.3.18 /Gt (Set Data Threshold)
Option
/Gt«number»
The /Gt option causes all data items whose size is greater than or equal to
number bytes to be allocated in a new data segment.
If you specify number, it must follow the /Gt option immediately with no
intervening spaces. If you use /Gt without a number, the default threshold
value is 256. If you don't use the /Gt option, the default threshold value
is 32,767.
Use this option with programs that have more than 64K of initialized static
and global data in small data items.
By default, the compiler allocates all static and global data items within
the default data segment in the tiny, small and medium memory models. In
compact-, large-, and huge-model programs, only initialized static and
global data items are assigned to the default data segment.
You can use the /Gt option only if you are creating a compact-, large-, or
huge-model program because tiny-, small-, and medium-model programs have
only one data segment.
────────────────────────────────────────────────────────────────────────────
4.3.19 /Gw, /GW (Generate Code for Windows(tm) Function Calls)
The /Gw option instructs the compiler to generate entry/exit code sequences
for call-back functions in Windows applications. The /GW option is similar,
but it generates a more efficient entry sequence and is intended for use
with non-call-back functions. See the Microsoft Windows(tm) Software
Development Kit for more information.
4.3.20 /HELP (List the Compiler Options)
Option
/HELP
/help
This option displays a list of the most commonly used compiler options. QCL
processes all information on the line containing the /help option and
displays the command list.
Unlike all the other QCL options, /HELP is not case sensitive. Any
combination of uppercase and lowercase letters is acceptable. For example,
/hELp is a valid form of this option. The option has no abbreviation.
4.3.21 /I (Search Directory for Include Files)
Option
/Idirectory
You can add to the list of directories searched for include files by using
the /I (for "include") option. This option causes the compiler to search the
directory you specify before searching the directories given by the INCLUDE
environment variable. That way, you can give a particular file special
handling without changing the compiler environment you normally use.
The space between /I and directory is optional. To search more than one
directory, you can give additional /I options on the QCL command line. The
directories are searched in order of their appearance on the command line.
The directories are searched only until the specified include file is found.
If the file is not found in the given directories or the standard places,
the compiler prints an error message and stops processing. When this occurs,
you must restart compilation with a corrected directory specification.
Examples
QCL /I \INCLUDE /I\MY\INCLUDE MAIN.C
In the example above, QCL looks for the include files requested by MAIN.C in
the following order: first in the directory \INCLUDE, then in the directory
\MY\INCLUDE, and finally in the directory or directories assigned to the
INCLUDE environment variable.
QCL /X /I \ALT\INCLUDE MAIN.C
In the example above, the compiler looks for include files only in the
directory \ALT\INCLUDE. First the /X option tells QCL to consider the list
of standard places empty; then the /I option specifies one directory to be
searched.
4.3.22 /J (Change Default char Type)
In Microsoft QuickC, the char type is signed by default, so if a char value
is widened to int type, the result is sign-extended.
You can change this default to unsigned with the /J option, causing the char
type to be zero-extended when widened to int type. If a char value is
explicitly declared signed, however, the /J option does not affect it, and
the value is sign-extended when widened to int type. This option is useful
when working with character data that eventually will be translated into a
language other than English.
When you specify /J, the compiler automatically defines the identifier
_CHAR_UNSIGNED, which is used with #ifndef in the LIMITS.H include file to
define the range of the default char type.
4.3.23 /Lc, Lr (Compile for Real Mode)
The /Lc and /Lr options are synonymous. Both options compile the program for
OS/2 real mode or for the DOS environment. If you compile with /Lc or /Lr,
you must make sure the linker uses the appropriate real-mode library; either
use /NOD to tell the linker not to search for the default library, or rename
the appropriate real-mode library so that it has the default name.
4.3.24 /Li (Link Incrementally)
The /Li option specifies incremental linking, causing QCL to invoke ILINK
instead of QLINK for linking the object files. When you link incrementally,
the linker pads all _near functions to a 40-byte boundary by default. Note
that QCL automatically invokes the incremental linker when you use the /Gi
option for incremental compilation, unless you also specify the /c option to
prevent linking.
4.3.25 /Ln (Link without C Run-Time Startup Code)
If you are using the tiny memory model (see the /AT option for QCL), you
will be creating a .COM file (see the /T option for QLINK). Normally, QCL
tells QLINK to link tiny- model programs with CRTCOM.LIB; this file contains
startup code needed by any .COM program written in C. Programs that are
written in assembly language do not need this code. Use the /Ln option to
keep QLINK from linking with this startup code.
4.3.26 /ND, /NT (Name the Data or Code Segments)
Options
/NDdatasegment
/NTcodesegment
The /ND option renames a data segment in a QuickC program, and the /NT
option renames a code segment. The name can be any combination of letters
and digits. The space between the option and the argument is optional.
Each object file produced by the QuickC compiler has its code and its data
stored separately, in blocks called "segments." A segment that contains
program instructions is called a "code segment," while a segment that
contains program data is
called a "data segment." An object file may have one or more of each kind of
segment. When object files are linked into a program, these segments are
combined and reorganized. The program's memory model determines how many
code segments and how many data segments the resulting program has (see
Appendix B).
Every segment in every object file has a name. The linker uses this name to
determine which segments are combined during linking, and how the segments
are arranged in the .EXE file. (Note that the segments in the group named
DGROUP are an exception.) By using the /ND and /NT options, you can control
how segments are combined and arranged.
The QuickC compiler normally gives the code and data segments default names.
These default names are determined by the memory model chosen for the
program, as follows:
■ Tiny- and small-model programs. The code segment is named _TEXT and
the data segment is named _DATA. These names are the same for all
object files. During linking with the tiny model, all the code and
data are placed in one segment. During linking with the small model,
all code segments from all object files are placed in one segment, and
all data segments are placed in another segment.
■ Medium-model programs. The code segment for each object file is given
a distinct name, consisting of the module base name plus the suffix
_TEXT. The data segment is named _DATA.
■ Compact-model programs. All data items that are smaller than the
threshold size (specified by the /Gt option) are placed in the default
data segment, _DATA. If they are larger than the threshold, they are
placed in a segment having a distinct name consisting of the
object-file name plus a suffix (_DATA, _CONST, or _BSS). The code
segment is named _TEXT.
■ Large- and huge-model programs. The code and data from each object
file are placed in separate segments with distinct names. Each code
segment is given the name of the object file plus the suffix _TEXT.
All data items smaller than the threshold size are placed in the
default data segment, _DATA, and those that are larger are placed in a
segment with a unique name.
The /ND option creates three new segments with the names datasegment,
datasegment_BSS, and datasegment_CONST, and combines them into a group named
datasegment_GROUP. The program then treats the named segment as the default;
that is, it assumes that the data register (DS) contains the address of the
segment, so that it can access the segment's contents using near pointers
instead of far. In doing so, your program no longer assumes that the address
in the stack segment register (SS) is the same as the address in the data
register (DS). You must therefore use the _loadds modifier for function
declarations or the /Au segment setup option to ensure that DS is loaded on
entry to a function.
The /NT option gives the code segment the specified name. In general, you
should not use the /NT option with the tiny, small and compact memory
models. Doing so may cause fixup-overflow errors at link time (see Section
5.5.6 for more information).
4.3.27 /nologo (Suppress Display of Sign-On Banner)
The /nologo option suppresses the display of the sign-on banner when QCL is
invoked.
4.3.28 /O Options (Optimize Program)
Option
/O string
The /O options give you control over the optimizing procedures that the
compiler performs. The string consists of one or more of the letters "d,"
"l," "t," and "x." The list below shows how each of these affects
optimization:
Letter Optimizing Procedure
────────────────────────────────────────────────────────────────────────────
/Od Turns off all optimization
/Ol Enables loop optimization
/O, /Ot Favors execution speed during
optimization
(the default)
/Ox Maximizes optimization
The letters can appear in any order. More than one /O option can be given;
the compiler uses the last one on the command line if any conflict arises.
Each option applies to all source files that follow on the command line.
4.3.28.1 /Od (Turn Off Optimization)
The /Od (for "debug") option tells the compiler to turn off all
optimizations in the program. This option speeds compilation because the
compiler does not take time to perform optimizations.
Use the /Od option when you compile with the /Zi option (described in
Section 4.3.36) to include debugging information. The /Od option does not
reorganize code, thus making it easier to debug.
4.3.28.2 /Ol (Optimize Loops)
The /Ol option tells the compiler to perform loop optimizations, which store
frequently used loop variables in registers. The /Ox option implicitly turns
on the /Ol option.
4.3.28.3 /O and /Ot (Minimize Execution Time)
When you do not use any of the /O options, the QCL command automatically
favors program execution speed in the optimization. The /O and /Ot options
have the same effect as this default.
Wherever the compiler has a choice between producing smaller (but perhaps
slower) and larger (but perhaps faster) code, the compiler generates faster
code. For example, when you specify the /Ot option, the compiler generates
intrinsic functions to perform shift operations on long operands.
4.3.28.4 /Ox (Use Maximum Optimization)
The /Ox option is a shorthand way to combine optimizing options to produce
the fastest possible program. Its effect is the same as using the following
options on the same command line:
/Olt /Gs
That is, the /Ox option performs loop optimizations, favors execution time
over code size, and removes stack probes.
Example
QCL /Ol FILE.C
This command tells the compiler to perform loop optimizations when it
compiles FILE.C. The compiler favors program speed over program size because
the /Ot option is also specified by default.
4.3.29 /P (Create Preprocessor-Output File)
The /P writes preprocessor output to a file with the same base name as the
source file but with the .I extension. The preprocessed listing file is
identical to the original source file except that all preprocessor
directives are carried out and macro expansions are performed. You normally
use the /P option with the /C option (discussed in Section 4.3.4), which
preserves comments in the preprocessed output.
The /P option suppresses compilation; QCL does not produce an object file or
listing, even if you specify the /Fo or /Fm option on the QCL command line.
Example
QCL /P MAIN.C
The example above creates the preprocessed file MAIN.I from the source file
MAIN.C.
4.3.30 /Ta, /Tc (Specify Assembly Language or C Source File)
Options
/Tc filename
/Ta filename
The /Tc option specifies that filename is a C source file, even if it
doesn't have the extension .C. The /Ta option specifies that filename is an
assembly language file, even if it doesn't have the extension .ASM. You must
have installed the Microsoft Macro Assembler in order to use the /Ta option.
This option causes QCL to invoke the Macro Assembler to assemble the file.
The space between the option and the filename is optional.
If this option does not appear, QCL assumes that files with the .C extension
are C source files, files with the .ASM extension are assembly language
files, files with the .LIB extension are libraries, and files with any other
extension or with no extension are object files.
If you need to specify more than one source file with an extension other
than .C, you must specify each source file in a separate /Tc option. The
same is true with regard to assembly language files and the /Ta option.
Example
In the example below, the QCL command compiles the three source files
MAIN.C, TEST.PRG, and COLLATE.PRG.
QCL MAIN.C /Tc TEST.PRG /Tc COLLATE.PRG PRINT.PRG
Because the file PRINT.PRG is given without a /Tc option, QCL treats it as
an object file. Therefore, after compiling the three source files, QCL links
the object files MAIN.OBJ, TEST.OBJ, COLLATE.OBJ, and PRINT.PRG.
4.3.31 /U, /u (Remove Predefined Names)
Options
/U name
/u
The /U (for "undefine") option turns off the definition of one of the names
that the QuickC compiler predefines. The /u option turns off the definitions
of all predefined names except for the name of the memory model. These
options do not apply to user-defined names.
These names are useful in writing portable programs. For instance, they can
be used with compiler directives to conditionally compile parts of a
program, depending on the processor and operating system being used. The
predefined identifiers and their meanings are listed in Table 4.5.
One or more spaces can separate /U and name. You can specify more than one
/U option on the same command line.
The /u option turns off the definitions of all predefined names except
M_I86mM, which identifies the memory model. You can use the /U option to
remove the definition of M_I86mM. If you do, however, you must explicitly
define the NULL constant in your program since the definition of NULL in the
STDIO.H and STDDEF.H files depends on the memory model in use.
Limits on command-line definitions
The /U and /u options are useful if you need to give more than the maximum
number of definitions (23 if you use either the /Za or the /J option, 22 if
you use both options, or 24 otherwise) on the command line, or if you have
other uses for the predefined names. For each predefined name you remove,
you can substitute a definition of your own on the command line. When the
definitions of all six predefined names are removed, you can specify up to
30 command-line definitions. However, because MS-DOS limits the number of
characters you can type on a command line the number of definitions you can
specify in practice is probably fewer than 30.
Example
QCL /UMSDOS /UM_I86 WORK.C
This example removes the definitions of two predefined names. Note that the
/U option must be given twice to do this.
4.3.32 /V (Set Version String)
Option
/V string
The /V option embeds a text string in the object file. This string can label
an object file with a version number or a copyright notice. If the specified
string contains white-space characters, it must be enclosed in double
quotation marks (" "). A backslash must precede any embedded double
quotation marks.
Table 4.5 Predefined Names
╓┌────────────────┌────────────────────────────┌─────────────────────────────╖
Syntax Purpose When Defined
────────────────────────────────────────────────────────────────────────────
_CHAR_UNSIGNED Indicates that the char When the /J option is given
type is unsigned by default.
M_I86 Identifies target machine Always
as a member of the Intel(R)
family.
M_I86mM Identifies memory model, Always
where m is either T (tiny
model), S (small model), C
(compact model), M (medium
Syntax Purpose When Defined
────────────────────────────────────────────────────────────────────────────
(compact model), M (medium
model), L (large model), or
H (huge model). If huge
model is used, both M_I86LM
and M_I86HM are defined.
M_I8086 Identifies target machine When the /G0 option is given
as an 8086. and by default
M_I286 Identifies target machine When the /G1 or /G2 option
as an 80286. is given
_MSC_VER Identifies version of Always
Microsoft C currently
supported. Equal to 600.
MSDOS Identifies target operating Always
system as MS-DOS.
Syntax Purpose When Defined
────────────────────────────────────────────────────────────────────────────
NO_EXT_KEYS Indicates that When the /Za option is given
Microsoft-specific language
extensions and extended
keywords are disabled.
_QC Identifies compiler as Always
Microsoft QuickC.
You can control the number of warning messages produced by the compiler by
using the /w, /W0, /W1, /W2, /W3, /W4, or /WX option. Compiler warning
messages are any messages beginning with C4; see Appendix D, "Error
Messages," for a complete list of these messages.
Warnings indicate potential problems (rather than actual errors) with
statements that may not be compiled as you intend.
The /W options affect only source files given on the command line; they do
not apply to object files.
The following list describes the warning-level options:
Option Action
────────────────────────────────────────────────────────────────────────────
/w Turns off all warning messages. Use this
option when you compile programs that
deliberately include questionable
statements. The /W0 option applies to
the remainder of the command line or
until the next occurrence of a /W option
on the command line.
/w0 Same as /w.
/W1 The default. Displays severe warning
messages.
/W2 Displays an intermediate level of
warning messages. Level-2 warnings may
or may not indicate serious problems.
They include warnings such as the
following:
■ Use of functions with no declared
return type
■ Failure to put return statements in
functions with non-void return types
■ Data conversions that would cause loss
of data or precision
/W3 Displays a higher level of warning
messages, including warnings about
function calls that precede their
function prototypes in the source code.
/W4 Displays the highest level of warning
messages, including warnings about the
use of non-ANSI features and extended
keywords.
/WX Treats all warnings as fatal errors. If
there are any warning messages, the
compilation aborts and QCL does not
produce an object file.
────────────────────────────────────────────────────────────────────────────
NOTE
The descriptions of the warning messages in Appendix D indicate the warning
level that must be set (that is, the number for the appropriate /W option)
for the message to appear.
────────────────────────────────────────────────────────────────────────────
Example
QCL /W4 CRUNCH.C PRINT.C
This example enables all possible warning messages when the source files
CRUNCH.C and PRINT.C are compiled.
4.3.34 /X (Ignore Standard Include Directory)
You can prevent the QuickC compiler from searching the standard places for
include files by using the /X (for "exclude") option. When QCL sees the /X
option, it does not search the current directory or any directories
specified in the INCLUDE environment variable.
You can use this option with the /I option to define the location of include
files that have the same names as include files found in other directories
but that contain different definitions. See Section 4.3.21 for an example of
/X used with /I.
4.3.35 /Ze, /Za (Enable or Disable Language Extensions)
Microsoft QuickC supports the ANSI C standard. In addition, it offers a
number of features beyond those specified in the ANSI C standard. These
features are enabled when the /Ze (default) option is in effect and disabled
when the /Za option is in effect. They include the following:
■ The _cdecl, _far, _fortran, _huge, _near, and _pascal keywords
■ Use of casts to produce lvalues:
int *p;
((long *)p)++;
The preceding example could be rewritten to conform with the ANSI C
standard:
p = (int *)((long *)p + 1);
■ Redefinitions of extern items as static:
extern int foo();
static int foo()
{}
■ Use of trailing commas (,) rather than an ellipsis (...) in function
declarations to indicate variable-length argument lists:
int printf(char *,);
■ Benign typedef redefinitions within the same scope:
typedef int INT;
typedef int INT;
■ Use of mixed character and string constants in an initializer:
char arr[5] = {'a', 'b', "cde"};
■ Use of bit fields with base types other than unsigned int or signed
int
■ Use of single-line comments, which are introduced with two slash
characters:
// This is a single-line comment.
■ Casting of a function pointer to a data pointer:
int (* pfunc) ();
int *pdata;
pdata = (int *) pfunc;
To perform the same cast while maintaining ANSI compatibility, you
must cast the function pointer to an int before casting it to a data
pointer:
pdata = (int *) (int) pfunc;
Use the /Za option if you plan to port your program to other environments.
The /Za option tells the compiler to treat extended keywords as simple
identifiers and disable the other extensions listed above.
When you specify /Za, the compiler automatically defines the identifier
NO_EXT_KEYS. In the include files provided with the QuickC run-time library,
this identifier is used with #ifndef to control use of the _cdecl keyword on
library function prototypes. For an example of this conditional compilation,
see the file STDIO.H.
4.3.36 /Zi, /Zd (Compile for Debugging)
The /Zi option produces an object file containing full symbolic-debugging
information for use with the QuickC debugger and the CodeView
window-oriented debugger. This object file includes full symbol-table
information and line numbers.
The /Zd option produces an object file containing line-number records
corresponding to the line numbers of the source file. Use /Zd if you plan to
debug with the SYMDEB debugger. Also use this option when you want to reduce
the size of an executable file that you will be debugging with the CodeView
debugger and when you do not need to use the expression evaluator during
debugging.
Example
QCL /c /Zi TEST.C
This command produces an object file named TEST.OBJ that contains line
numbers corresponding to the lines in TEST.C.
4.3.37 /Zl (Remove Default-Library Name from Object File)
Ordinarily, QCL puts the name of the default library (SLIBCE.LIB) in the
object file so that the linker can automatically find the correct library to
link with the object file.
The /Zl option tells the compiler not to place the default-library name in
the object file. As a result, the object file is slightly smaller.
Use the /Zl option when you are using the LIB utility (described in Chapters
2 and 6) to build a library. You can use /Zl to compile the object files you
plan to put in your library, thereby omitting the default-library names from
your object modules. Although the /Zl option saves only a small amount of
space for a single object file, the total amount of space saved is
significant in a library containing many object modules.
Example
QCL ONE.C /Zl TWO.C
The example above creates the following two object files:
1. An object file named ONE.OBJ that contains the name of the C library
SLIBCE.LIB
2. An object file named TWO.OBJ that contains no default-library
information
When ONE.OBJ and TWO.OBJ are linked, the default-library information in
ONE.OBJ causes the default library to be searched for any unresolved
references in either ONE.OBJ or TWO.OBJ.
4.3.38 /Zp (Pack Structure Members)
Option
/Zp«{1|2|4}»
When storage is allocated for structures, structure members are ordinarily
stored as follows:
■ Items of type char or unsigned char, or arrays containing items of
these types, are byte aligned.
■ Structures are word aligned; structures of odd size are padded to an
even number of bytes.
■ All other types of structure members are word aligned.
To conserve space or to conform to existing data structures, you may want to
store structures more or less compactly. The /Zp option and the pack pragma
control how structure data are packed into memory.
Use the /Zp option to specify the same packing for all structures in a
module. When you give the /Zpn option, where n is 1, 2, or 4, each structure
member after the first is stored on n-byte boundaries depending on the
option you choose. If you use the /Zp option without an argument, structure
members are packed on two-byte boundaries.
On some processors, the /Zp option may result in slower program execution
because of the time required to unpack structure members when they are
accessed. For example, on an 8086 processor, this option can reduce
efficiency if members with int or long type are packed in such a way that
they begin on odd-byte boundaries.
Use the pack pragma in your source code to pack particular structures on
boundaries different from the packing specified on the command line. Give
the pack(n) pragma, where n is 1, 2, or 4, before structures that you want
to pack differently. To reinstate the packing given on the command line,
give the pack() pragma with no arguments.
Table 4.6 shows the interaction of the /Zp option with the pack pragma.
Table 4.6 Using the pack Pragma
╓┌─────────────────────┌─────────────────────────┌───────────────────────────╖
Compiled with /Zp
Syntax Option? Action
────────────────────────────────────────────────────────────────────────────
#pragma pack() Yes Reverts to packing
specified on the command
line for structures that
follow
#pragma pack() No Reverts to default packing
for structures that follow
#pragma pack(n) Yes or no Packs the following
structures to the given
byte boundary until
changed or disabled
────────────────────────────────────────────────────────────────────────────
Compiled with /Zp
Syntax Option? Action
────────────────────────────────────────────────────────────────────────────
────────────────────────────────────────────────────────────────────────────
Example
QCL /Zp PROG.C
This command causes all structures in the program PROG.C to be stored
without extra space for alignment of members on int boundaries.
4.3.39 /Zr (Check Pointers)
The /Zr option checks for null or out-of-range pointers in your program. A
run-time error occurs if you try to run a program with such pointers.
#pragma check_pointer
If you compile with the /Zr option, you can use the check_pointer pragma
within your source file to turn checking on or off only for selected
pointers leaving the default (see below) for the remaining pointers in the
program. When you want to turn on pointer checking, put the following line
before the usage of the pointer you want to check:
#pragma check_pointer (on)
This line turns on pointer checking for all pointers that follow it in the
source file, not just the pointers on the following line. To turn off
pointer checking, insert the following line:
#pragma check_pointer (off)
If you don't give an argument for the check_pointer pragma, pointer checking
reverts to the behavior specified on the command line: turned on if the /Zr
option is given or turned off otherwise.
Example
QCL /Zr prog.c
This command causes QCL to check for null or out-of-range pointers in the
file prog.c. All pointers in the file are checked except those to which a
check_pointer(off) pragma applies.
4.3.40 /Zs (Check Syntax Only)
The /Zs option tells the compiler to check only the syntax of the source
files that follow the option on the command line. This option provides a
quick way to find and correct syntax errors before you try to compile and
link a source file.
When you give the /Zs option, the compiler does not generate code or produce
object files, object listings, or executable files. The compiler, however,
does display error messages if the source file has syntax errors.
Example
QCL /Zs TEST*.C
This command causes the compiler to perform a syntax check on all source
files in the current working directory that begin with TEST and end with the
C extension. The compiler displays messages for any errors found.
4.3.41 Giving Options with the CL Environment Variable
Use the CL environment variable to specify files and options without giving
them on the command line. This variable has the following format:
SET CL=« «option» ... «file» ...» «/link « link-libinfo» »
Use this variable if you usually give a large number of files and options
when you compile. Ordinarily, DOS limits the command line to 128 characters.
The files and options that you define with the CL environment variable,
however, do not count toward this limit. Therefore, you can define the files
and options you use most often with the CL variable and then give only the
files and options you need for specific purposes on the command line.
The information defined in the CL variable is treated as though it appeared
before the information given on the QCL command line, as illustrated in
Figure 4.3.
(This figure may be found in the printed book.)
Note that if you have given an option in the CL environment variable, you
generally cannot turn off or change the option from the command line. You
must reset the CL environment variable and omit the file or option that you
do not want to use.
Also note that you cannot use CL to set options that use an equal sign (for
example, the /Didentifier= string option), and you cannot use wild-card
characters in file names to specify multiple files with CL.
Examples
In the following example, the CL environment variable tells the QCL command
to use the /Zp, /Ox, and /I options during compilation and then to link with
the object file \LIB\BINMODE.OBJ.
SET CL=/Zp /Ox /I\INCLUDE\MYINCLS \LIB\BINMODE.OBJ
QCL INPUT.C
With CL defined as shown, the QCL command above has the same effect as the
command line
That is, both specify structure packing on two-byte boundaries; perform
maximum optimizations; search for include files in the \INCLUDE\MYINCLS
directory; and suppress translation of carriage-return-line-feed character
combinations for the source file INPUT.C.
In the following example, the CL environment variable tells the QCL command
to compile and link the source files FILE1.C and FILE2.C.
SET CL=FILE1.C FILE2.C
QCL FILE3.OBJ
The QCL command line above has the same effect as the command line
QCL FILE1.C FILE2.C FILE3.OBJ
The following example illustrates how to turn off the effects of a QCL
option defined in the environment.
SET CL=/Za
QCL FILE1.C /Ze FILE2.C
In this example, the CL environment variable is set to the /Za option, which
tells the compiler not to recognize Microsoft extensions to the C language.
This option causes Microsoft-specific keywords to be treated as ordinary
identifiers rather than reserved words. The QCL command specifies the
inverse option, /Ze, which tells the compiler to treat language extensions
as reserved words. Since the effect is the same as compiling with the
command line
QCL /Za FILE1.C /Ze FILE2.C
FILE1.C is compiled with language extensions turned off and FILE2.C is
compiled with language extensions enabled.
4.4 Controlling Stack and Heap Allocation
The "stack" and the "heap" are two important memory areas that are allocated
for QuickC programs. The stack is used for all local data (that is, data
that are defined within a function); the heap is used for all dynamically
allocated data (that is, data allocated by one of the alloc family of
functions).
Programs compiled and linked with QuickC run with a fixed stack size (the
default size is 2,048 bytes). The stack resides above static data, and the
heap uses whatever space is left above the stack. For some programs,
however, a fixed-stack model may not be ideal; a model where the stack and
heap compete for space is more appropriate.
Linking with the mVARSTCK.OBJ object files (where m is the first letter of
the library you choose) gives you such a model: when the heap runs out of
memory, it tries to use available stack space until it runs into the top of
the stack. When the allocated space in the heap is freed, it is once again
made available to the stack. Note that the stack cannot grow beyond the
last-allocated heap item in the stack, or, if there are no heap items in the
stack, beyond the size it was given at link time. Furthermore, while the
heap can employ unused stack space, the reverse is not true: the stack
cannot employ unused heap space.
You can change the model used to allocate heap space by linking your program
with one of the mVARSTCK.OBJ object files. These files are the small-,
medium-, compact-, and large-model versions of a routine that allows the
memory-allocation functions (malloc, calloc, _expand, _fmalloc, _nmalloc,
and realloc) to allocate items in unused stack space if they run out of
other memory. (If you use the huge memory model, link with the large-model
object file LVARSTCK.OBJ.)
When you link your program with one of the mVARSTCK.OBJ files, do not
suppress stack checking with the #check_stack pragma, or with the /Gs or /Ox
option. Stack overflow can occur more easily in programs that link with the
variable-stack object files, possibly causing errors that would be difficult
to detect.
Example
QCL TEST.C SVARSTCK
This command line compiles TEST.C and then links the resulting object module
with SVARSTCK.OBJ, the variable-stack object file for small-model programs.
This chapter describes in detail the operation of the Microsoft QuickC
Compiler linker (QLINK) and includes an alphabetical reference to the QLINK
options.
5.1 Overview
The QuickC linker (QLINK) combines object files into a single executable
file. It can be used with object files compiled or assembled for 8086/8088,
80286, 80386, or 80486 machines. The format of input to the linker is the
Microsoft Relocatable Object-Module Format (OMF), which is based on the
Intel 8086 OMF.
The output file from QLINK (that is, the executable file) is not bound to
specific memory addresses. Thus, the operating system can load and execute
this file at any convenient address. QLINK can produce executable files
containing up to one megabyte of code and data.