This is the DJGPP Frequently-Asked Questions List.

Copyright (C) 1994, 1995, 1996, 1997, 1998 Eli Zaretskii.

This is the second edition of the FAQ list,
and is consistent with version 2.01 of DJGPP.

This FAQ list may be freely distributed with the DJGPP package or any part
thereof, provided that this copyright notice is left intact on all copies.

DJGPP FAQ List
**************

  In DJGPP (see DJGPP overview in Chapter 2), a 32-bit compiler and programming
environment, originally written for Unix machines, meet a 16-bit MS-DOS
operating system.  Programmers who work in this environment have to master a
large body of knowledge from both Unix and MS-DOS, especially if they want to
use some advanced features, like interrupt handling, directly accessing
peripheral devices, etc.

  But because the DJGPP project is run by a group of volunteers on their free
time, there isn't always enough time (or patience, or money ;-) to produce
documentation which will describe all the subtle features and pitfalls a user
should know about.  The documentation of DJGPP-specific utilities and
features is minimal at times, leaving wide space for confusion, in newcomers
and veterans alike, and making the DJGPP learning curve steeper than it could
be.

  This FAQ list is an attempt to take the sting out of that learning curve, by
supplying solutions for problems which are known to puzzle DJGPP users.
(Another solution would be to pay to DJ Delorie and other people who develop
DJGPP to produce more documentation ;-).

  Some additional places to look for tutorials and other introductory material
about DJGPP are listed below.

  One good place to look for DJGPP features that are often overlooked is the
DJGPP Knowledge Base (http://www.delorie.com/djgpp/doc/kb/).  The Knowledge
Base is also available in Info format; type `info knowledge' from the DOS
prompt.  A `User's Guide' is also being written by several contributors; it
is currently available from the DJGPP server
(http://www.delorie.com/djgpp/doc/ug/).

  Brennan Underwood <brennan@rt66.com> maintains a home page
(http://brennan.home.ml.org/djgpp/), which is another valuable source for
information about DJGPP.

  You can browse the HTML version of this FAQ list on line at DJ Delorie's Web
server (http://www.delorie.com/djgpp/v2faq/faq.html).

  Also available from the DJ's server: FAQ in several additional formats
(http://www.delorie.com/djgpp/v2faq/faq211b.zip).

  A previous version of this FAQ was translated into French
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/frfaq21b.zip), also
available through the WWW
(http://www.delorie.com/djgpp/v2faq/frfaq21.zip).

  This is Edition 2.11 of the FAQ, last updated 13 September 1998, for DJGPP
Version 2.01.

   Table of Contents
   *****************
1. If You Are In a Hurry
2. What is DJGPP?
3.  Hardware and Software Requirements
  3.1 The minimum system requirements for using DJGPP
  3.2 Does it really work under OS/2?
  3.3 Will it work under Windows/NT?
  3.4 Can it run under Linux?
  3.5 Can I run it on a 286?
  3.6 MS-Windows applications and DJGPP
  3.7 Machine you *would like* to buy...
  3.8 Machine most of us will *actually* buy ...
  3.9 How to configure your system for DJGPP?
  3.10 How to get the most RAM for DJGPP programs?
4. Where and What to Download?
  4.1 Where can DJGPP be found?
  4.2 CCT sites
  4.3 How do I download DJGPP?
  4.4 What if I don't know what `FTP' is?
  4.5 What Files to Download?
  4.6 How much disk space will I need?
  4.7 Can I get away with less megabytes?
  4.8 How to uninstall a DJGPP package.
5. The DJGPP Documentation
  5.1 Where are the documentation files?
  5.2 How to read the docs without `Info?'
  5.3 How to print the docs?
  5.4 Some docs are nowhere to be found...
  5.5 What are these `foo.1' files?
  5.6 What if the docs don't say enough?
6. When the Compiler (or `Make', or `Info', or ...) Crashes...
  6.1 GCC or some other DJGPP programs hang
  6.2 GCC says ``No DPMI''
  6.3 Buggy DPMI host or junk in DJGPP.ENV can crash v2.x programs
  6.4 GCC can crash during optimization
  6.5 Why does GCC say ``cannot exec `as'''?
  6.6 What does ``Internal compiler error'' mean?
  6.7 What does ``Unknown filetype'' mean?
  6.8 Compiler hangs, but only when invoked from Make
  6.9 Info doesn't like some files
  6.10 Info Crashes During Startup
  6.11 Why does Bash crash?
  6.12 Why does the Linker Access my CD Drive?
  6.13 Other kinds of trouble
  6.14 I cannot keep up with the error messages
  6.15 How to search DJGPP archives for similar problems
  6.16 How to ask DJGPP gurus for help
7. Compiler and Linker Performance
  7.1 Slow Compilation
  7.2 Slow Linking
8. Compile-time and Link-time Problems
  8.1 GCC can't find headers or libraries
  8.2 GCC can't find C++ headers
  8.3 GCC barfs on C++-style comments in C programs
  8.4 How does GCC recognize the source language?
  8.5 Problems with Objective C
  8.6 Writing codes fragments which are specific to DJGPP
  8.7 Unresolved externals when linking programs
  8.8 How not to lose your head with all these libraries
  8.9 DJGPP uses a one-pass linker
  8.10 Some functions still not found in C++ programs
  8.11 Unresolved djgpp_first_ctor
  8.12 C++ programs yield large `.exe' file
  8.13 Why are DJGPP `.exe' files so large?
  8.14 Linker complains about `djgpp.lnk'
  8.15 Linker fails to produce the EXE program under Novell
  8.16 Linker fails for large object files or large libraries
  8.17 Building Allegro library fails
  8.18 C++ compiler says ``NULL redefined''
  8.19 C++ exceptions support
  8.20 How to get GCC to generate assembly code
  8.21 What's wrong with `sys/movedata.h'?
  8.22 How do I create a library of object files?
9. Running Compiled Programs
  9.1 My program crashes only in v2.0!
  9.2 What is that gibberish printed when my program crashes?
  9.3 Reading and writing binary files
  9.4 Buffered screen I/O surprises
  9.5 What do DJGPP programs need to run?
  9.6 How many file handles can DJGPP use?
10. Writing and Running Graphics Programs
  10.1 What GRX driver to use with your SVGA
  10.2 Accessing the video memory
  10.3 Graphics screen restoring under Windows
11. Floating Point Issues and FP Emulation
  11.1 Floating-point code without 80387
  11.2 Other FP emulators cannot be used with DJGPP
  11.3 Floating-point emulation under OS/2
  11.4 DJGPP doesn't support `-msoft-float'
  11.5 Numeric exceptions---sometimes
  11.6 Floating point inaccuracies when using emulator
  11.7 Floating point exception in Objective-C programs
  11.8 Floating point exception in libm functions
12. Debugging DJGPP Programs
  12.1 How to run a DJGPP program under debugger
  12.2 How to begin debugging using the crash dump info
  12.3 You need QEMM 7.53 or later
  12.4 GDB would not debug unless it sees COFF output
  12.5 How to debug a graphics program
  12.6 GDB finds only `.cc' source
  12.7 Can GDB print class members?
  12.8 GDB cannot list source that was #include'd
  12.9 GDB cannot display or set static uninitialized variables
  12.10 Debuggers choke on some programs ...
13. Profiling DJGPP Programs
  13.1 How to profile a DJGPP program
  13.2 Programs compiled with -pg crash when run
  13.3 Gprof won't work unless it can find COFF executable
  13.4 Where is Gprof docs?
  13.5 Why is `__dpmi_int' so heavily used?
  13.6 `gprof' doesn't produce output
14. Run-time Performance of DJGPP Programs
  14.1 How efficient is DJGPP-generated code?
  14.2 Comparing newer versions with old ones
  14.3 DJGPP programs on a Pentium
  14.4 My program's I/O is so slow!
  14.5 My ported program runs much slower!
15. Run-Time Memory Issues
  15.1 How much virtual memory do you have?
  15.2 It seems `malloc'/`free' don't affect virtual memory...
  15.3 Failure to get more memory than is physically installed
  15.4 Memory allocation fails before all memory is used
  15.5 Memory allocation fails under Windows
  15.6 Memory allocation peculiarities under Windows 9X
  15.7 Memory allocation fails under EMM386 or HIMEM
  15.8 How much memory do parent DJGPP programs leave for their child?
  15.9 How much stack can I have in DJGPP programs?
16. Command-line Arguments Handling in DJGPP
  16.1 Filename wildcards expansion under DJGPP
  16.2 How to disable filename wildcards expansion
  16.3 How to pass command-line arguments with quotes or `@'
  16.4 How to pass command lines longer than 126 characters
  16.5 What is the maximum length of command line under DJGPP
  16.6 Why Make passes only 126 characters to programs?
17. Converting DOS Programs/Libraries to DJGPP
  17.1 GCC/Gas won't accept valid assembly code ...
  17.2 Converting between Intel ASM syntax and AT&T syntax
  17.3 Converted code GP Faults!
  17.4 Which registers need to be saved in assembly code?
  17.5 I want to use a `.obj' or `.lib' code with DJGPP
  17.6 I *must* use my 16-bit code with DJGPP!!
  17.7 What should I do with those ``near'' and ``far'' declarations?
  17.8 How to convert _AX pseudo-registers?
18. Low-level DOS/BIOS and Hardware-oriented Programming
  18.1 Got ``Unsupported INT 0xNN'' calling `int86'
  18.2 How to use buffers with DOS/BIOS services
  18.3 How to call software interrupt functions
  18.4 How to move data between your program and conventional memory
  18.5 How to move structs returned by real-mode services?
  18.6 Fast access to absolute addresses
  18.7 Accessing absolute address above 1MB
  18.8 How to make DOS/BIOS call your function
  18.9 How to hook hardware interrupts
  18.10 Should I use _go32_XXX or __dpmi_YYY functions?
  18.11 Hardware interrupt hooking has its subtleties
  18.12 How to read and write ports
  18.13 Inline Assembly code with GCC
  18.14 Using DMA with DJGPP
19. Legal Aspects
  19.1 Legal (un)restrictions on DJGPP applications
  19.2 Legal restrictions of DJGPP utilities and libraries
20. Getting Help
  20.1 Don't post DJGPP-specific problems to GNU News groups
  20.2 How to post to the mailing list
  20.3 How to become a subscriber to the mailing list
  20.4 How to unsubscribe from the mailing list
21. Version 2 vs v1.x
  21.1 New features in DJGPP v2
  21.2 DJGPP environment in v2.x
  21.3 Why are new DJGPP versions released so slowly?
  21.4 Where to find the best C library for DJGPP
22. Miscellany
  22.1 Unzipping gppNNb.zip complains about g++.exe
  22.2 How to change a DJGPP package?
  22.3 Where to find sample DJGPP code or a package ported to DJGPP?
  22.4 How to create symbolic links to programs
  22.5 Where to find the DPMI specification?
  22.6 The DJGPP Web site.
  22.7 Where to upload your contributions to DJGPP
  22.8 DJGPP as cross-compiler
  22.9 GCC says ``garbage at end of number''
  22.10 What should sizeof (struct xyzzy) return?
  22.11 C++ doesn't pack structs!
  22.12 How to avoid ``Abort, Retry, Fail'' messages
  22.13 What is that `go32-v2.exe' program?
  22.14 What is DXE?
  22.15 Long Filenames Don't Work!
  22.16 Make says ``missing separator''
  22.17 Make says ```foo' has modification time in the future''
  22.18 How to Set Up a Dual DOS/Windows Installation
  22.19 What is in that `zoneinfo' directory?
  22.20 The Secrets of the /dev/ Directory...
  22.21 How about switching to ELF as DJGPP's object file format?
  22.22 How to produce random numbers?
  22.23 What are all these buzzwords I see?
  22.24 What should the `main' function return in a C program?
  22.25 Generating the FAQ in your favorite format
23. About this FAQ
24. Topic Index
25. Program Index

1. If You Are In a Hurry
************************

**Q*: Do you really mean I have to read this looongish FAQ list to get my
answers?*

**Q*: I have this problem which I absolutely MUST solve NOW!  What do I do?*

*A*: No, you don't need to read *all* of the FAQ unless you want to (although
this is by all means recommended).  The questions in this document are
listed, as much as possible, in the order they appear when one goes through
getting DJGPP, installing it and using it.  To quickly find an answer to your
question, first look at the Table of Contents, at the beginning of this
document.  If that doesn't help, try the indices at the end of this manual.
You can look up your question either by program name in Chapter 25, or by
topic name in Chapter 24.  To search the indices in Info, press `i' (you
don't need to go to the Index node for that), then type the string you want
to look up, and press <Enter>.  If the first place found by Info is not what
you are after, press `,' (comma) repeatedly, to visit the rest of the places
which appear in the indices.

If you don't find anything appropriate, search this FAQ for words which are
pertinent to your problem(1).  For those in a *real* hurry, here are some
pointers to the most important topics in this FAQ list:

   * How to install DJGPP after downloading it?

     Here's a brief description of the necessary steps:

        - Create a directory for DJGPP and chdir there.

        - Unzip all the `*.zip' files preserving the directory structure.  On
          Windows 9X, use an unzip program which supports long file names.

        - Add these two lines to your `AUTOEXEC.BAT' file:

                set PATH=C:\DJGPP\BIN;%PATH%
                set DJGPP=C:\DJGPP\DJGPP.ENV

          If your top DJGPP directory is other than `C:\DJGPP', *change these
          two lines accordingly!*

        - Reboot your machine.

     Your installation is now complete.

   * How do I compile and link programs?

     Here are several simple commands:

        - Compile a single C source `cprog.c' into `cprog.exe':

                gcc -o cprog.exe cprog.c

        - Compile a C++ source `cxxprog.cc' into `cxxprog.exe':

                gxx -o cxxprog.exe cxxprog.cc

        - Compile several C/C++ source files into object files:

                gcc -c cfile1.c cxxfile2.cc

        - Link several `*.o' object files into `myprog.exe':

                gxx -o myprog.exe cfile1.o cxxfile2.o

     To compile with optimizations, add the `-O2' switch to the command line.
     In addition, use of the `-Wall' switch is highly recommended: it turns
     on many useful diagnostic messages.

   * How to ask experienced DJGPP users for help?

     Use the DJGPP News group or mailing list.  For most questions, you will
     have your answer in a day or two.  See the details on how to ask the
     gurus in Section 6.16.

   * What is the best way to configure my system for DJGPP?

     This depends on your hardware and software.  Detailed instructions are
     in system configuration guidelines in Section 3.9.

   * Some files I need seem to be missing.  Where do I find them?

     Check out list of required and optional packages in Section 4.5.

   * How do I subscribe to or unsubscribe from the DJGPP mailing list?

     See subscription instructions in Section 20.3.  However, it is better to
     read comp.os.msdos.djgpp news group if you have access to Usenet News.

   * How can I search News group/mailing list traffic for some info?

     This FAQ includes description of DJGPP archive search server in Section
     6.15.  That search facility is set up by DJ Delorie <dj@delorie.com>,
     and you should use it whenever you have any questions or look for an
     information on a DJGPP-related subject.

---------- Footnotes ----------

(1) Please report any issues that couldn't be found via the indices to the
maintainer of this FAQ, whose name and e-mail address can be found near the
end of the FAQ.

2. What is DJGPP?
*****************

**Q*: What is DJGPP?*

*A*: DJGPP is a compiler and a set of tools that let you produce 32-bit
protected-mode programs which run on MS-DOS/MS-Windows machines.

The originator and principal maintainer of DJGPP is DJ Delorie
<dj@delorie.com>; that's where the "DJ" in "DJGPP" comes from.  However,
anybody is welcome and encouraged to contribute.

Programs compiled with DJGPP, and all development tools provided as part of
DJGPP, look on the outside like normal DOS programs, and they rely on MS-DOS
and BIOS for file I/O and other basic functions such as keyboard input,
screen cursor position, etc.  DJGPP programs use "DPMI" (the DOS Protected
Mode Interface) to allow DOS/BIOS calls from protected mode.  Therefore, any
environment that can run DOS programs and provides DPMI services, will run
DJGPP programs as well.  Environments that are known to be compatible with
DJGPP include MS-DOS, DR-DOS, NWDOS, FreeDOS, OpenDOS, Windows 3.X, 9X and
NT, OS/2, and Linux DOSEmu.  When DJGPP programs run on Windows 9X, they
support long filenames.

It is important to understand that all these environments will treat DJGPP
programs as DOS programs which call DPMI services.  DJGPP cannot by itself
create Win16 or Win32 applications; however, you can use the RSXNT package
together with DJGPP to achieve this.  See writing Windows applications with
DJGPP in Section 3.6.

Programs compiled with DJGPP can access all the physical memory on your
machine and support virtual memory.  All this memory presents a flat address
space with no segmentation (you can say goodbye to far and huge pointers and
to memory models), and is only limited by the amount of virtual memory
supported by the DPMI server in use.  A typical DPMI server can provide at
least 64MB of virtual memory (if you have enough free disk space).

DJGPP is free: you don't have to pay anything to download and use it, even if
you write commercial programs.  DJGPP doesn't impose any restrictions on
programs that you write and compile with it: you can make them commercial,
shareware, freeware, or any other kind.  (There are a few minor exceptions to
that rule, see (un)restrictions on distribution of DJGPP apps in Application
distribution.)

The core of DJGPP is the MS-DOS port of the GNU C/C++ compiler, GCC, and
auxiliary utilities, such as assembler, linker, librarian, Make, and a
hypertext docs browser.  The DJGPP C library was written specifically for
DJGPP, mainly by DJ Delorie himself, with help from a small group of
volunteers.

DJGPP presents a set of tools which are remarkably ANSI- and
Posix-compliant(1).  GCC complies to ANSI/ISO C Standard; the DJGPP C library
is ANSI- and Posix-compliant (however, a small number of Posix features, like
the `fork' system call, are unimplemented); the C++ libraries also comply to
the latest standards; and the GNU development tools used by DJGPP are all
Posix-compliant.  As a result, DJGPP tools provide a complete and coherent
Posix layer on top of Microsoft operating systems, to the degree that even
the infamous limitations of DOS and incompatibilities between DOS/Windows and
Unix are almost completely concealed from users and developers.

Here are some of the tasks that DJGPP is said to be good for:

   - learning C and C++ programming and teaching others to program in C/C++;

   - using Unix development tools on MS-DOS and MS-Windows;

   - writing games(2) and graphics programs;

   - setting up a common development environment for Unix and
     MS-DOS/MS-Windows;

   - writing portable DOS/Unix programs;

   - porting Unix programs to Microsoft operating systems.

DJGPP is also used as back-end for programming languages other than C/C++.
ADA, Pascal and Fortran compilers have been ported to MS-DOS based on DJGPP
(GNU Pascal (`gpc') and GNU Fortran (`g77') are available from the DJGPP
archives).

Starting from v2.0, DJGPP programs do not need a separate extender program,
only a DPMI server to run; DJGPP includes a free 32-bit DPMI server which
allows for a 32-bit, 4 GByte flat address space and up to 512 MBytes of
virtual memory.

---------- Footnotes ----------

(1) Posix is an international standard for a portable operating system.  It
specifies facilities of a compiler, its libraries, and the basic set of
development tools.  Posix was originally modeled on Unix systems, but is
currently supported by most modern operating systems.

(2) For example, the DOS version of the well-known game `Quake' by id
Software was compiled with DJGPP.

3.  Hardware and Software Requirements
**************************************

  This chapter describes what are the hardware and software which will allow
you to use DJGPP.  Minimum, "reasonable" and optimal system configurations
are listed.

3.1 The minimum system requirements for using DJGPP
===================================================

**Q*: What are the minimum system requirements for using DJGPP?*

**Q*: Will DJGPP run on my brand-new Acme i986DX7/500 PC with a SCSI-III
10-Terabyte disk drive under MulticOS/42 v7.99 operating system?*

*A*: DJGPP requires at least 386SX CPU and between 15 and 35 MB of free disk
space (see more details on this below in Section 4.6), including space for
the software installation and some swap space.  A minimum of 64K of free
system memory is enough for DJGPP to run with CWSDPMI as your DPMI host (most
other DPMI hosts will require much more), but at least 4MB of free extended
RAM is recommended for reasonably fast compilation of large source files (8MB
for compiling large C++ programs); you might see painfully slow compiles for
large sources if you don't have at least that much.  If your machine doesn't
have a numeric co-processor, you will need to install an emulator to run
floating-point code (DJGPP provides such an emulator) or link your
applications with a special emulator library (also provided with DJGPP).

DJGPP will run under native DOS; any other operating system is OK if it
includes a DPMI server and supports some kind of "DOS box".  Environments
known to run DJGPP besides native DOS: Windows 3.1 & 3.11 DOS box, OS/2
(including Warp) DOS box, Windows 9X/DOS 7, Windows NT (on Intel CPUs),
Novell NWDOS 7 and Caldera's OpenDOS (but several people have found the DPMI
services of NWDOS and OpendDOS incompatible with DJGPP, so they should
probably be turned off and CWSDPMI used instead), and Linux DOSEmu
environment.

3.2 Does it really work under OS/2?
===================================

**Q*: You tell me it will work under OS/2, but I'm experiencing strange
crashes after several compilations ...*

**Q*: DJGPP Make crashes when I run it on OS/2!*

*A*:  There was a bug in the DPMI server of the old OS/2 versions, which was
triggered by spawning child processes (like GCC does when it invokes the
various compiler passes).  Current versions of OS/2 don't have that bug, so
DJGPP programs should run fine under OS/2.  If you can't make this happen,
chances are that your setup is incorrect.  One system parameter that can
cause problems with DJGPP (reportedly, Make crashes if it isn't set
correctly) is `DPMI_DOS_API'.  Setting it to `ENABLED' instead of the default
`AUTO' should solve the problem.  I'm also told that experimenting with the
value of `DPMI_MEMORY_LIMIT' sometimes solves problems on OS/2.  Reportedly,
version 4.0 of OS/2 solves problems with DPMI support, so the above is only
required for OS/2 v3.0 or earlier.

One particular problem with OS/2 v3.0 is that RHIDE 1.4 and later exits after
the compilation ends.  This doesn't happen under OS/2 v4.0, so you should
upgrade if you have such problems.

If the above doesn't help, please post the details of the crashes you see to
the DJGPP mailing list (see how to post to the mailing list in Section 20.2),
or to comp.os.msdos.djgpp news group, and somebody will help you.

3.3 Will it work under Windows/NT?
==================================

**Q*: What about Windows NT?*

*A*:  Current Windows NT versions support DPMI programs in the DOS box, so
DJGPP programs should in general run fine under NT (but see the list of
possible problems below).

The DPMI server built into NT (and Windows 9X) loses selectors with each
child program that is invoked by a DJGPP program, so after about two thousand
calls to functions from the `spawnXX' family you can see an error message
like this:

       Load error: no DPMI selectors

This problem is likely to afflict only DJGPP ports of Unix shells (such as
`bash'), since no other DJGPP program, not even `Make', is likely to call so
many child programs before it exits.  The only known work-around is to exit
the shell every now and then, because when all the available selectors are
exhausted, the DOS box will crash.  I'm told that `Make' sometimes fails on
long `Makefiles' on Windows 9X, where the selectors are lost at even higher
rate than on NT.  If you ever run a very long `Makefile' and see `Make' crash,
just run `Make' again, and it will pick up where the crashed session has left
off.

Note that the long filename API (the special functions of Int 21h which
support file names longer than the DOS 8+3 limitation) for DOS box is not
supported by current versions of Windows/NT, so you cannot have long
filenames there from DJGPP programs.  An alpha version of an LFN driver for
NT which enables long file name support for DJGPP programs, written by Andrew
Crabtree, can be downloaded from Andrew's site
(http://www.goof.com/pcg/data/djgpp/lfn0106.zip).

The popular DJGPP IDE RHIDE needs a `-M' switch to work on NT (to disable the
mouse support which will otherwise crash RHIDE).

You might have problems with using the SVGA modes of your video card under
Windows/NT.  That is because NT doesn't allow direct access to the SVGA
registers, without which it is impossible to recognize the type of the SVGA
and employ its capabilities.  For example, a user reported that GRX functions
and the `MODETEST.EXE' program thought that only a standard VGA was
installed, whereas he had an S3 card.  There is nothing you can do about this
feature of Windows/NT; that is the price you pay for the stability and
protection you get under this OS (a runaway program that accesses hardware
registers can wipe out your disk or wedge the entire system cold).  However,
I'm told that Windows/NT 4.0 supports "DirectX" which is a method of
accessing screen, audio and other peripherals directly, so it might be
possible to use full GRX graphics capabilities there.

Programs that use the "nearptr" facility of DJGPP to access absolute memory
addresses (e.g., for memory-mapped devices) won't work on NT, because its
DPMI server silently ignores functions that set huge limits on selectors.
Since the default algorithm which allocates memory from the DPMI server needs
to set such huge limit in some rare cases, there's a small probability that a
program will fail or crash even if it doesn't set selector limits in user
code.  It is best to use the Unix-style `sbrk' algorithm in programs that run
on Windows/NT.  See the library docs for the variable `_crt0_startup_flags'
where the `_CRT0_FLAG_UNIX_SBRK' bit is explained, for more info on this
issue.  If you cannot switch to the Unixy `sbrk' (e.g., if you don't have
access to the program's sources), I'm told that sometimes such problems can
be worked around if you run DJGPP programs in a full-screen session; your
mileage may vary.

Some people report that NT servers cause much more problems than NT
workstations of the same version and build.  It seems that these problems
usually mean that NT installation was done incorrectly (maybe it is much
harder to get it right with a server than with a workstation?).  If you have
such problems, try to install a workstation, or re-install the server, and
see if that helps.  And if you gain some insight as to why servers like DJGPP
less than workstations, please tell what you've learned.

The Cygnus Win32 project is another (unrelated to DJGPP) port of GCC and
development tools to Windows/NT and Windows 9X platforms, which specifically
targets development of Windows programs.  See  in Windows apps, for more
details about the Cygnus ports.

3.4 Can it run under Linux?
===========================

**Q*: You say it works on Linux, but I seem to be unable to run the compiler
from within Make...*

**Q*: I can run DJGPP on Linux, but Make crashes with SIGFPE on even the
simplest Makefiles!*

**Q*: When I run bash on Linux/DOSEmu, echoing of what I type is very slow.*

*A*:  Versions of Linux which were released before 13 March 1996 need a patch
to be able to reliably run nested DJGPP programs.  That patch was posted to
the DJGPP mailing list and can be found by using the search capabilities of
the DJGPP mail archives
(http://www.delorie.com/djgpp/mail-archives/djgpp/1996/02/26/13:28:52).

If you prefer to download that patch via ftp, you can find it on the DJGPP
ftp server (ftp://ftp.delorie.com/pub/djgpp/contrib/dpmi-dosemu-djgpp.mail).

In general, upgrading to DOSEmu version 0.97.10 or later is recommended, at
least with versions of Linux kernel earlier than 2.1; in particular, some
users report that DJGPP programs sometimes crash on version 0.66.7 under
Linux 2.0.35.

You might also need to edit the RAM section of the `/etc/dosemu.conf' file to
make it comfortable for DJGPP.  I suggest setting `dpmi' and `xms' to 16MB
and `ems' to 4MB.  For example, I'm told that building the Allegro library
with the `-O3' optimization switch fails in DOSEmu unless you allocate at
least 16MB of DPMI memory to DOSEmu sessions.

If DJGPP programs crash with an error message like this(1):

     DPMI: Unhandled Execption 0d - Terminating Client
     It is likely that dosemu is unstable now and should be rebooted

then you should add a line saying `secure off' to your `/etc/dosemu.conf'
file.

Some users reported that `Make', and possibly other programs which use
floating point computations, crash in DOSEmu environment on systems without
an FPU, even if you set the 387 and EMU387 environment variables correctly
(as explained in Setting up the FP emulator in Section 11.1, below).  The
only known work-around is to not use floating point or to upgrade your
machine hardware.  It is possible that newer versions of Linux might solve
this problem too, so try upgrading your Linux software.

If your only problem is to run GNU Make, get the latest DJGPP port of Make,
since ports of Make 3.75 or later can be configured to not issue FP
instructions at all.

If DJGPP programs respond too slow to keyboard input, you might need to tune
the `HogThreshold' parameter in the `dosemu.conf' file.  Set it to zero and
see if this helps; if so, further tune it until you get reasonable response
time, but still leave Linux with enough cycles for the other programs that
run.

Several users reported that DJGPP programs cannot get input from the keyboard
if Caldera's OpendDOS is booted under DOSEmu.  I'm told that adding
`rawkeyboard' to `dosemu.conf' might solve this.

Some people complain that RHIDE crashes on DOSEmu whenever the mouse is
moved.  I'm told that using the `-M' switch when invoking RHIDE solves this
problem.  Alternatively, you could try giving DOSEmu access to the serial
port to which the mouse is connected, and then using your DOS mouse driver.
To this end, add the following to your `dosemu.conf'(2):

      serial { mouse com 2 device /dev/mouse }
      mouse {mousesystems device /dev/mouse emulate3buttons }

and then load a DOS mouse driver in the DOSEmu `AUTOEXEC.BAT'.

If you have problems with mounting FAT32 partitions, upgrade the Linux kernel
to version 2.0.34 or later.

---------- Footnotes ----------

(1) The typo in the word `Exception' is in the actual message popped by Linux.

(2) This was reported for DOSEmu version 0.66.7; the format of `dosemu.conf'
might be different in version 0.9x.

3.5 Can I run it on a 286?
==========================

**Q*: Why can't I run DJGPP on my 286?  It has protected mode also...*

*A*:  True, but the protected mode isn't an issue here.  Gcc doesn't care
much about memory protection, but it does care to run on a 32-bit processor,
which the 286 isn't.  A 386 or better CPU really *is* required.

3.6 MS-Windows applications and DJGPP
=====================================

**Q*: Can I write MS-Windows applications with DJGPP?*

*A*: Currently, you can only run DJGPP programs under Windows as DOS apps
(i.e. inside the DOS Box).  If you need to write true Windows apps, you will
have to use auxiliary tools or another compiler.  This section lists some of
the possibilities.

RSXNTDJ is an add-on to DJGPP which allows to develop Win32 programs.  This
is targeted for Win32 (Windows 9X and NT) and Win32s (Windows 3.X + Win32s)
platforms (but the development environment will only run on Windows 9X/NT);
it supports DJGPP v2.x and includes debugging tools and an IDE, but it needs
to be registered (for a small fee) if you want to develop commercial or
shareware applications with it.

RSXNTDJ supports Win32 console, GUI, DLLs and bound programs (the latter can
be run on DOS under the RSX extender, as well as on Windows).  You can
download RSXNTDJ from SimTel
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/rsxdj131.zip).

RSXNTDJ was produced with GCC v2.7.2.1 and DJGPP v2.01.  If you use it with
later versions of GCC and DJGPP, you might need to tweak the installation a
bit.  People who succeeded in this feat report that they needed to make the
following changes:

   * Add the directory where the pre-processor (`cpp.exe') is kept to the
     `PATH' environment variable.  (Without this, the resource compiler won't
     work.)

   * Edit `DJGPP.ENV' to add the directories where the RSXNTDJ libraries are
     kept to the value of the `LIBRARY_PATH' variable.

   * The URL mentioned in the RSXNTDJ help file for the MS Platform SDK
     header files is no longer valid.  You can find the SDK headers on the
     Microsoft World Wide Web site
     (http://www.microsoft.com/msdownload/platformsdk.html).  Note that the
     patches to Windows header files included in the package are outdated by
     later versions of those headers released by Microsoft.  You might need to
     apply the patches manually if the `patch' utility fails.

   * I'm also told that the `stdio.h' header supplied with RSXNTDJ defines
     several inline functions with the `extern' qualifier, which causes GCC
     to not compile them into the object file, and triggers undefined
     references.  The solution is to define the `extern' symbol to an empty
     string in one of the source files which includes the `stdio.h' header.

Some people report that they needed to bump up the stack size using the
`pestack' utility, allegedly due to insufficient size of the default stack.

Note that the version of linker `ld.exe' which comes with RSXNTDJ doesn't
print any message if you forget to link in libraries such as `libcomct.a' and
`libcomdl.a'.  Instead, the produced executables will die with SIGSEGV when
run.  Sometimes, forgetting to `#include' `windows.h' also produces a program
that crashes at run time.  You can use the stock DJGPP version of `ld.exe' to
see the list of the missing functions, and then find out which libraries to
add to the link command line (use the `nm' utility to find out which
libraries contain the required external symbols).

If RSXNTDJ doesn't suit your needs, you can use a few other compilers which
target Win32 platforms:

`Cygnus GNU-Win32 tools'
     This tool-chain includes native Win32 ports of GCC and of many GNU
     development tools.  It requires you to comply to the GNU License, the
     GPL, when distributing programs built with these tools.  The tools and
     the programs you build are native Win32 executables (won't run on DOS,
     Windows 3.X or Win32s platforms) and Posix-compliant, but you need to
     distribute a 4MB DLL file with all your programs.  Also, GNU-Win32 is
     still in beta phase, and some bugs are still worked on.  You can find
     GNU-Win32 on the Cygnus site (http://www.cygnus.com/misc/gnu-win32/), or
     via FTP (ftp://ftp.cygnus.com/pub/gnu-win32/latest/).

`Mingw32 (Minimal GNU-Win32)'
     This features native Win32 ports of GCC and EGCS, the experimental
     version of GCC, but it relies on the Windows C runtime (`CRTDLL.DLL',
     which is standard on Windows 9X and Windows/NT) and doesn't require any
     additional DLLs like Cygnus ports do; however, you lose the Posix layer.
     Since it doesn't use any GPL'ed stuff except GCC and its subprograms,
     the programs produced by Mingw32 are *free*.  For more details, visit
     the Mingw32 home page
     (http://www.xraylith.wisc.edu/~khan/software/gnu-win32/).

`Lcc-Win32 compiler and tools'
     This is a Win32 port of a freeware compiler Lcc, not related to GCC.  It
     doesn't currently support C++ programs.  The tool-chain includes some
     additional utilities such as a resource compiler and a resource browser,
     an IDE, and a Make utility.  For more information, visit the Lcc home
     page (http://www.cs.princeton.edu/software/lcc/) and the lcc-win32 home
     page (http://www.cs.virginia.edu/~lcc-win32/).

A better (but harder) way would be to volunteer to add Windows support to
DJGPP.

3.7 Machine you *would like* to buy...
======================================

**Q*: What is the optimal system configuration for running DJGPP?*

*A*:  Here is the description of your dream machine (at least for the next 6
months :-):

   * Hardware:

        - the fastest CPU you can find on the market (a 400 MHz Pentium II,
          as of this writing) with a 100 MHz memory bus;

        - at least 512KB second-level (off-chip) cache memory;

        - 256 MByte RAM;

        - PCI-based motherboard;

        - SCSI-II hard disk with bus-mastering controller;

   * Software:

        - DOS, device drivers and TSRs all loaded HIGH, leaving only 5K DOS
          footprint in lower (under 640K) memory;

        - 16 MByte RAM disk installed, `TMPDIR' environment variable points to
          it (e.g., `set TMPDIR=e:', if E: is the RAM drive letter);

        - 32 MByte of disk cache, set to delayed-write operation;

3.8 Machine most of us will *actually* buy ...
==============================================

**Q*: OK, I don't have this much money.  What is the *reasonable*
configuration?*

*A*:  If you have the following machine, you should be able to stop worrying
about memory and compilation performance:

   - CPU: P133 with 256 KB off-chip cache;

   - RAM: 32 MByte;

   - Disk: 12 ms IDE with VLB controller, or SCSI;

   - 4 MByte RAM disk;

   - 8 MByte disk cache;

This will leave you with about 19 MBytes of free extended RAM.  Note that the
RAM disk must be 4 MBytes to hold the output of the preprocessor for some
exceedingly large source files (notably, some GCC source files).  If you
don't have that much RAM to spare and still want to compile *very* large
source files, either reduce the disk cache so you can give more to RAM disk,
or point `TMPDIR' to your hard disk and make the disk cache larger, if you
can.

3.9 How to configure your system for DJGPP?
===========================================

**Q*: How do I configure my system to get optimal performance under DJGPP?*

*A*:  That depends on the amount of RAM you have installed in your machine.
Below are some guidelines to help you.

  a. If you have 2 MBytes or less RAM installed:

        * Don't use *any* memory manager.

        * Use of CWSDPMI as your DPMI host is highly recommended.

        * Remove any TSR and device drivers you don't absolutely need (like
          `SETVER.EXE', `HIMEM.SYS' etc.) from your `CONFIG.SYS' and
          `AUTOEXEC.BAT.'

        * Do *not* install disk cache or RAM disk; point your `TMPDIR'
          environment variable to a directory on your hard disk.  Put a
          sufficiently large `BUFFERS=' statement into your `CONFIG.SYS' (I
          recommend setting `BUFFERS=40,8') to make DOS file operations
          faster.

        * If you use CWSDPMI as your DPMI host, get the `CWSPARAM' program
          (from the `csdpmi4b.zip' archive) and set the "Minimum application
          memory desired before 640K paging" parameter to 512K or larger.
          Depending on how much memory you actually have, you might need to
          further fine-tune this parameter.  This parameter defines the
          lowest amount of extended memory CWSDPMI will use; if your system
          doesn't have that much free extended RAM, CWSDPMI will use
          conventional memory instead, where usually there should be around
          600K of free RAM.

        * If you run under Windows, be sure to set the maximum amount of
          extended memory on your PIF file for the DOS box to a reasonable
          value.

     With this configuration, GCC will run out of free physical RAM and start
     paging when compiling almost any C program and all C++ programs.  If you
     are serious about DJGPP development, you need to buy more RAM *urgently*.

  b. If you have 2-4 MBytes of RAM installed:

        * Don't use *any* memory manager.

        * Remove any TSR and device driver you don't absolutely need (like
          `SETVER.EXE', `HIMEM.SYS') from your `CONFIG.SYS' and
          `AUTOEXEC.BAT.'

        * Get a disk cache which works from conventional memory and configure
          it to 256K size at most, or don't use a cache at all.

        * Do *not* install a RAM disk; point your `TMPDIR' environment
          variable to a directory on your hard disk.

        * If you run under Windows, be sure to set the maximum amount of
          extended memory on your PIF file for the DOS box to a reasonable
          value.

     With this configuration, GCC will still run out of free physical RAM and
     start paging when compiling large C programs and most C++ programs.
     Plan to buy more RAM as soon as you can.

  c. If you have 5-8 MBytes of RAM installed:

        * Use a memory manager such as `EMM386' or `QEMM386'.  Try using the
          `FRAME=NONE' parameter of the memory manager.  This will disable
          Expanded Memory (EMS) services as far as most programs are
          concerned; if you must use DJGPP together with any program which
          needs EMS, try to configure that program to use Extended Memory
          (XMS) instead.

        * Load DOS, device drivers and TSRs *HIGH*.

        * Give your disk cache 1 MByte of RAM.  Enable its delayed-write
          (a.k.a.  write-back) feature.

        * Do *not* install a RAM disk; point your `TMPDIR' environment
          variable to a directory on your hard disk.

        * If, after configuring your system as above, you still have more
          than 2.5 MBytes of free RAM left (4 MBytes, if you plan to program
          in C++ a lot), enlarge the disk cache size.

        * If you run under Windows, be sure to set the maximum amount of
          extended memory on your PIF file for the DOS box to a reasonable
          value.

  d. If you have more than 8 MBytes of RAM:

        * Use a memory manager to load DOS, TSRs and device drivers *HIGH*.

        * Install at least a 2-MByte-large disk cache, configured to use the
          delayed- write feature.  If you have plenty of RAM, you can give
          your cache as much as 8 MBytes of memory.

        * If you have more than 10 MBytes left, install a RAM disk with a
          size of at least 1.5 MBytes and point your `TMPDIR' environment
          variable to it.  If your RAM disk is less than 4 MBytes, GCC might
          run out of space there for *very* large source files (e.g., cccp.c
          file from the GCC source distribution), but this shouldn't happen
          unless the size of the source file you are compiling approaches 1
          MByte.  Note that software is available that lets you install a RAM
          disk even on Windows 9X.

        * As a general rule of thumb, you should leave at least 8 MBytes of
          free RAM after installing the disk cache and the RAM disk.  16MB
          free is even better, especially if you need to run large programs
          like RHIDE or Emacs, or to compile large source files.

Some people disable the delayed-write feature for safety reasons, to avoid
losing files due to system crashes.  If you are worried about this, you can
usually gain performance without sacrificing safety by enabling delayed-write
together with an option that causes the cache to flush the write-behind data
before the system returns to the DOS prompt.  For a `SmartDrv' disk cache,
this is achieved by specifying `/N/F' switches instead of `/X'.

A tutorial is available from the Web on how to set up and get started with
DJGPP (http://www.castle.net/~avly/djgpp.html).

Using a memory manager, such as `EMM386' or `QEMM', is not required (DJGPP
will run without it), but highly recommended, since it has several advantages:

   - Memory managers provide an API for allocating extended memory called
     VCPI (the "Virtual Control Program Interface").  Using that API allows
     CWSDPMI to allocate only as much extended memory as is needed, leaving
     the rest for non-DJGPP programs, in case you invoke them from DJGPP
     programs.  In contrast, without a memory manager, CWSDPMI will allocate
     all of the available extended memory o itself, leaving zero to non-DJGPP
     programs.  This consideration is especially important if you use some
     DJGPP program, like Bash or Emacs, as your primary system interface.

   - Without a memory manager, you cannot access UMBs (the "Upper Memory
     Blocks") which give you more DOS memory to work with.  In particular,
     CWSDPMI will load itself into UMBs if they are available.

   - Memory managers provide the VDS ("Virtual DMA Services") API which
     allows to write programs that use DMA in protected mode.

   - Memory managers support the expanded (EMS) memory, which some older DOS
     programs still use.

If your memory manager is `EMM386', I recommend to put the `NOEMS NOVCPI'
parameters on its command line.  This will allow you to use UMBs and up to
128MB of physical memory (if you have that much installed).  Without these
parameters, most versions of `EMM386' limit your physical memory to 32MB.

It is generally not recommended to install DJGPP on a networked drive, since
this makes it slower, particularly when linking programs.  If you do install
DJGPP on a networked drive, you should consult your network administrator to
configure the network for maximum performance.  For Novell networks, a good
place to look for advice is the Novell FAQ (search for a file called
`nov-faq.htm').

3.10 How to get the most RAM for DJGPP programs?
================================================

**Q*: How do I set my system so that DJGPP programs could use all of my 256MB
of installed physical RAM?*

**Q*: I have 128MB of memory installed, but `go32-v2' only reports 32MB, how
can I get more?*

*A*: You can have as much as 256MB of physical memory in DJGPP programs,
provided that you have at least that much installed, and that you observe the
following guidelines:

   * Use CWSDPMI as your DPMI server.  With a possible exception of Qualitas'
     386Max, all the other DPMI servers usually cannot support more than
     64MB.  (The DPMI server built into Windows usually won't even let you
     have more than 64MB physical *and* virtual memory combined, unless you
     have more than 64MB installed physically, see below.)

   * Do *not* install any memory managers: most of them will limit the amount
     of accessible memory to 64MB (`EMM386' usually limits it to 32MB unless
     you turn off the VCPI support using the `NOVCPI NOEMS' parameters on the
     `EMM386' command line).  Using `HIMEM' from MS-DOS 7 does allow access
     to more than 64MB.

   * If you are using `QEMM' (version 8.0 or later), you must include the
     `USERAM=128M' parameter (here for 128MB of installed memory) on its
     command line in your `CONFIG.SYS' and specify the exact amount of memory
     installed on your machine, otherwise `QEMM' won't support more than 64MB.

   * Make sure you use the latest release r4 of CWSDPMI.  Previous versions
     only supported up to 128MB of main memory, and had bugs with more than
     64MB.

Another possibility is to run your program from the Windows 9X DOS box, after
changing the `EMM386' line in your `CONFIG.SYS' like this:

      DEVICE=C:\WINDOWS\EMM386.EXE NOEMS L=131072

I'm told that this line (here for 128MB of installed memory) together with an
"Auto" setting of the DPMI memory for the DOS box allows DJGPP programs to
use up to 117MB of memory when running from the DOS box under Windows 9X.

If you need to use more than 256MB of physical memory, try to convince
Charles Sandmann <sandmann@clio.rice.edu> to upgrade CWSDPMI.  However, note
that breaking the current limit of 256MB will make CWSDPMI considerably
slower (it requires to abandon 16-bit arithmetics and move to 32-bit longs,
which causes Turbo C, the compiler used to build CWSDPMI, to generate much
slower code).  Charles says that people who got such customized versions of
CWSDPMI were never really happy with its performance, so he advises to
consider the 256MB limit a serious reason to switch to another operating
system.  For example, a dual-boot DOS/Linux system will probably do.  Another
possibility is to run under OS/2 which features a built-in DPMI 1.0 support
which can be configured to support as much as 512MB of DPMI memory (the user
who reported this didn't know how much of this can be physical RAM).

4. Where and What to Download?
******************************

  This chapter explains where and how can you get DJGPP, and recommends which
parts of the archive you should download.

4.1 Where can DJGPP be found?
=============================

**Q*: Where can I get DJGPP?*

*A*: Look on any SimTel.NET mirror in the pub/simtelnet/gnu/djgpp/
subdirectory, or on one of the CCT mirrors, world-wide.

This section lists the SimTel.NET mirrors; see below in Section 4.2, for the
list of CCT sites.

The primary SimTel.NET site is:
     ftp.simtel.net, directory /pub/simtelnet/gnu/djgpp(1)

Here is a list of hosts by countries that offer mirror sites:

Argentina
     ftp.satlink.com, directory /pub/mirrors/simtelnet/gnu/djgpp

Australia:
     ftp.tas.gov.au, directory /pub/simtelnet/gnu/djgpp

Australia:
     sunsite.anu.edu.au, directory /pub/pc/simtelnet/gnu/djgpp

Vienna, Austria:
     ftp.univie.ac.at, directory /mirror/simtelnet/gnu/djgpp

Brussels, Belgium:
     ftp.linkline.be, directory /mirror/simtelnet/gnu/djgpp

Sao Paulo, Brazil:
     ftp.unicamp.br, directory /pub/simtelnet/gnu/djgpp

Brazil:
     ftp.iis.com.br, directory /pub/simtelnet/gnu/djgpp

Ottawa, Canada:
     ftp.crc.doc.ca, directory /systems/ibmpc/simtelnet/gnu/djgpp

Vancouver, Canada:
     ftp.direct.ca, directory /pub/simtelnet/gnu/djgpp

Chile:
     sunsite.dcc.uchile.cl, directory /pub/Mirror/simtelnet/gnu/djgpp

Beijing, China:
     ftp.pku.edu.cn, directory /pub/simtelnet/gnu/djgpp

Czech Republic:
     ftp.eunet.cz, directory /pub/simtelnet/gnu/djgpp

Prague, Czech Republic:
     pub.vse.cz, directory /pub/simtelnet/gnu/djgpp

Czech Republic:
     ftp.zcu.cz, directory /pub/simtelnet/gnu/djgpp

Denmark:
     ftp.net.uni-c.dk, directory /pub/simtelnet/gnu/djgpp

Espoo, Finland:
     ftp.funet.fi, directory /mirrors/ftp.simtel.net/pub/simtelnet/gnu/djgpp

Neuilly, France:
     ftp.grolier.fr, directory /pub/simtelnet/gnu/djgpp

France:
     ftp.lip6.fr, directory /pub/simtelnet/gnu/djgpp

Germany:
     ftp.mpi-sb.mpg.de, directory /pub/simtelnet/gnu/djgpp

Bochum, Germany:
     ftp.rz.ruhr-uni-bochum.de, directory /pub/simtelnet/gnu/djgpp

Chemnitz, Germany:
     ftp.tu-chemnitz.de, directory /pub/simtelnet/gnu/djgpp

Heidelberg, Germany:
     ftp.uni-heidelberg.de, directory /pub/simtelnet/gnu/djgpp

Magdeburg, Germany:
     ftp.uni-magdeburg.de, directory /pub/mirrors/simtelnet/gnu/djgpp

Paderborn, Germany:
     ftp.uni-paderborn.de, directory /pub/simtelnet/gnu/djgpp

Trier, Germany:
     ftp.uni-trier.de, directory /pub/pc/mirrors/Simtel.net/gnu/djgpp

Wuerzburg, Germany:
     ftp.rz.uni-wuerzburg.de, directory /pub/pc/simtelnet/gnu/djgpp

Athens, Greece:
     ftp.ntua.gr, directory /pub/pc/simtelnet/gnu/djgpp

Hong Kong:
     ftp.cs.cuhk.hk, directory /pub/simtelnet/gnu/djgpp

Hong Kong:
     ftp.hkstar.com, directory /pub/simtelnet/gnu/djgpp

Hong Kong:
     sunsite.ust.hk, directory /pub/simtelnet/gnu/djgpp

Hungary:
     ftp.iif.hu, directory /pub/simtelnet/gnu/djgpp

Dublin, Ireland:
     ftp.heanet.ie, directory /pub/simtelnet/gnu/djgpp

Dublin, Ireland:
     ftp.iol.ie, directory /pub/simtelnet/gnu/djgpp

Rome, Italy:
     cis.uniroma2.it, directory /simtelnet/gnu/djgpp

Italy:
     ftp.flashnet.it, directory /pub/simtelnet/gnu/djgpp

Naples, Italy:
     ftp.unina.it, directory /pub/simtelnet/gnu/djgpp

Italy:
     mcftp.mclink.it, directory /pub/simtelnet/gnu/djgpp

Saitama, Japan:
     ftp.saitama-u.ac.jp, directory /pub/simtelnet/gnu/djgpp

Saitama, Japan:
     ftp.riken.go.jp, directory /pub/simtelnet/gnu/djgpp

Japan:
     ftp.iij.ad.jp, directory /pub/simtelnet/gnu/djgpp

Japan:
     ftp.u-aizu.ac.jp, directory /pub/PC/simtelnet/gnu/djgpp

Japan:
     ftp.web.ad.jp, directory /pub/simtelnet/gnu/djgpp

Latvia:
     ftp.lanet.lv, directory /pub/mirror/simtelnet/gnu/djgpp

Malaysia:
     ftp.jaring.my, directory /pub/simtelnet/gnu/djgpp

Mexico:
     ftp.gdl.iteso.mx, directory /pub/simtelnet/gnu/djgpp

Netherlands:
     ftp.euro.net, directory /d5/simtelnet/gnu/djgpp

Utrecht, Netherlands:
     ftp.nic.surfnet.nl, directory /mirror/simtelnet/gnu/djgpp

Bergen, Norway:
     ftp.bitcon.no, directory /pub/simtelnet/gnu/djgpp

Krakow, Poland:
     ftp.cyf-kr.edu.pl, directory /pub/mirror/Simtel.Net/gnu/djgpp

Warsaw, Poland:
     ftp.icm.edu.pl, directory /pub/simtelnet/gnu/djgpp

Poznan, Poland:
     ftp.man.poznan.pl, directory /pub/simtelnet/gnu/djgpp

Aveiro, Portugal:
     ftp.ua.pt, directory /pub/simtelnet/gnu/djgpp

Portugal:
     ftp.ip.pt, directory /pub/simtelnet/gnu/djgpp

Bucharest, Romania:
     ftp.digiro.net, directory /pub/simtelnet/gnu/djgpp

Timisoara, Romania:
     ftp.dnttm.ro, directory /pub/simtelnet/gnu/djgpp

Singapore:
     ftp.nus.sg, directory /pub/simtelnet/gnu/djgpp

Slovakia:
     ftp.uakom.sk, directory /pub/simtelnet/gnu/djgpp

Slovenia:
     ftp.arnes.si, directory /software/simtelnet/gnu/djgpp

Johannesburg, South Africa:
     ftp.is.co.za, directory /pub/simtelnet/gnu/djgpp

Stellenbosch, South Africa:
     ftp.sun.ac.za, directory /pub/simtelnet/gnu/djgpp

South Africa:
     ftp.netactive.co.za, directory /pub/simtelnet/gnu/djgpp

South Africa:
     ftp.saix.net, directory /pub/simtelnet/gnu/djgpp

South Korea:
     ftp.sogang.ac.kr, directory /pub/simtelnet/gnu/djgpp

South Korea:
     sunsite.snu.ac.kr, directory /pub/simtelnet/gnu/djgpp

Spain:
     ftp.rediris.es, directory /mirror/simtelnet/gnu/djgpp

Stockholm, Sweden:
     ftp.sunet.se, directory /pub/simtelnet/gnu/djgpp

Zurich, Switzerland:
     sunsite.cnlab-switch.ch, directory /mirror/simtelnet/gnu/djgpp

Chung-Li, Taiwan:
     ftp.ncu.edu.tw, directory /Packages/simtelnet/gnu/djgpp

Taipei, Taiwan:
     nctuccca.edu.tw, directory /mirror/simtelnet/gnu/djgpp

Nonthaburi, Thailand:
     ftp.nectec.or.th, directory /pub/mirrors/simtelnet/gnu/djgpp

London, UK:
     ftp.demon.co.uk, directory /pub/simtelnet/gnu/djgpp

London, UK:
     ftp.globalnet.co.uk, directory /pub/simtelnet/gnu/djgpp

Lancaster, UK:
     mic5.hensa.ac.uk, directory /mirrors/simtelnet/gnu/djgpp

London, UK:
     sunsite.doc.ic.ac.uk, directory /packages/simtelnet/gnu/djgpp

Concord, California, USA:
     ftp.cdrom.com, directory /pub/simtelnet/gnu/djgpp

California, USA:
     ftp.digital.com, directory /pub/micro/pc/simtelnet/gnu/djgpp

California, USA:
     ftp.lib.sonoma.edu, directory /pub/simtelnet/gnu/djgpp

Georgia, USA:
     ftp.peachnet.edu, directory /pub/mirrors/simtelnet/gnu/djgpp

Urbana, Illinois, USA:
     uarchive.cso.uiuc.edu, directory /pub/systems/pc/simtelnet/gnu/djgpp

Massachusets, USA
     ftp.bu.edu, directory /pub/mirrors/simtelnet/gnu/djgpp

Rochester, Michigan, USA:
     OAK.Oakland.Edu, directory /pub/simtelnet/gnu/djgpp

Missouri, USA:
     galileo.galilei.com, directory /pub/simtelnet/gnu/djgpp

New York, NY, USA:
     ftp.rge.com, directory /pub/systems/simtelnet/gnu/djgpp

Oklahoma, USA:
     ftp.ou.edu, directory /pub/simtelnet/gnu/djgpp

Corvallis, Oregon, USA:
     ftp.orst.edu, directory /pub/simtelnet/gnu/djgpp

Pennsylvania, USA:
     ftp.epix.net, directory /pub/simtelnet/gnu/djgpp

Virginia, USA:
     mirrors.aol.com, directory /pub/simtelnet/gnu/djgpp

---------- Footnotes ----------

(1) ftp.simtel.net is actually several ftp sites arranged in a rotating
pattern of IP addresses to help balance the load and to avoid access problems
due to network outages and simultaneous user limits.

4.2 CCT sites
=============

**Q*: Where can I find the nearest CCT site?*

*A*:  Look up the site nearest to you in the list below:

Note that the copyright to the name "SimTel" is owned by Walnut Creek which
sponsors the SimTel.NET repository, so the CCT mirrors are in the process of
renaming their directories to `Coast'.  Therefore, if you don't find the
directories listed below, replace "SimTel" by "Coast" and try again.

The primary CCT site is in Detroit, Michigan, USA:
     ftp.coast.net, directory /Coast/vendors/djgpp/.

Here is a list of hosts by countries that offer mirror sites:

Canberra, Australia:
     archie.au, directory /micros/pc/SimTel/vendors/djgpp

Edmonton, AB, Canada:
     ftp.agt.net, directory /pub/SimTel/vendors/djgpp

Prague, Czech Republic:
     pub.vse.cz, directory /pub/simtel/vendors/djgpp

London, England:
     src.doc.ic.ac.uk, directory /pub/packages/simtel/vendors/djgpp

Liverpool, England:
     ftp.mersinet.co.uk, directory /pub/ibmpc/coast/vendors/djgpp

London, England:
     ftp.demon.co.uk, directory /pub/mirrors/simtel/vendors/djgpp

Chemnitz, Germany:
     ftp.tu-chemnitz.de, directory /pub/simtel/vendors/djgpp

Mainz, Germany:
     ftp.uni-mainz.de, directory /pub/pc/mirrors/simtel/vendors/djgpp

Tuebingen, Germany:
     ftp.uni-tuebingen.de, directory /pub/simtel/vendors/djgpp

Hong Kong:
     ftp.cs.cuhk.hk, directory /pub/simtel/vendors/djgpp

Hong Kong:
     sunsite.ust.hk, directory /pub/simtel/vendors/djgpp

Dublin, Ireland:
     ftp.hea.ie, directory /pub/simtel/vendors/djgpp

Haifa, Israel:
     ftp.technion.ac.il, directory /pub/unsupported/simtel/vendors/djgpp

Naples, Italy:
     ftp.unina.it, directory /pub/simtel/vendors/djgpp

Pisa, Italy:
     cnuce-arch.cnr.it, directory /pub/msdos/simtel/vendors/djgpp

Rome, Italy:
     ftp.flashnet.it, directory /mirror/simtel/vendors/djgpp

Rome, Italy:
     cis.utovrm.it, directory /SimTel/vendors/djgpp

Tokyo, Japan:
     ftp.crl.go.jp, directory /pub/pc/archives/simtel/vendors/djgpp

Tokyo, Japan:
     ftp.web.ad.jp, directory /pub/mirrors/Coast/vendors/djgpp

Tokyo, Japan:
     ring.aist.go.jp, directory /pub/coast/vendors/djgpp

Tokyo, Japan:
     ring.asahi-net.or.jp, directory /pub/coast/vendors/djgpp

Seoul, Korea:
     ftp.kornet.nm.kr, directory /pub/SimTel/vendors/djgpp

Seoul, Korea:
     ftp.nowcom.co.kr, directory /pub/SimTel/vendors/djgpp

Utrecht, Netherlands:
     ftp.nic.surfnet.nl, directory
     /mirror-archive/software/simtel-vendors/djgpp

Poznan, Poland:
     ftp.man.poznan.pl, directory /mirror/simtel/vendors/djgpp

Warsaw, Poland:
     ftp.icm.edu.pl, directory /pub/simtel/vendors/djgpp

Moscow, Russia:
     ftp.radio-msu.net, directory /mirror/Coast/vendors/djgpp

Singapore:
     ftp.singnet.com.sg, directory /pub/mirrors/SimTel/vendors/djgpp

Slovak Republic:
     ftp.uakom.sk, directory /pub/SimTel/vendors/djgpp

Taipei, Taiwan:
     nctuccca.edu.tw, directory /PC/simtel/vendors/djgpp

Bangkok, Thailand:
     ftp.bu.ac.th, directory /pub/SimTel/vendors/djgpp

Sunnyvale, CA, USA:
     ftp.drcdrom.com, directory /Coast/vendors/djgpp

Note that DJGPP was moved to the `Coast/vendors/' directory on CCT mirrors.
This is because CCT claims a compilation copyright on its collection, to
prevent people from copying the CD-ROMs which are distributed by CCT.  The
GNU GPL prohibits *any* restrictions, even on compilations.  So, FSF asked
for GNU and GNU-related files to be moved to a separate directory to keep
people from accidentally thinking that their rights were being reduced.

4.3 How do I download DJGPP?
============================

**Q*: How do I download files from these sites?*

*A*: FTP to the nearest site, log in as `anonymous', give your full e-mail
address as password, and chdir to the `djgpp' subdirectory (the exact path to
it might be different on different mirrors, check out the DJGPP archive path
in Section 4.1, for your nearest mirror).  Then issue the `binary' command
and download the files you need (see the list of required files in Section
4.5) with the `get' or `mget' commands.

4.4 What if I don't know what `FTP' is?
=======================================

**Q*: What is that `FTP' thing?  I only use `Netscape' and `IE4' for Internet
access.*

*A*:  OK, here are some Web sites for use with your Web browser:

   - The main SimTel.NET site (http://www.simtel.net/simtel.net/gnu/djgpp/).

   - The main CCT site (http://www.coast.net/Coast/vendors/djgpp/).

You can also convert any of the mirrors' addresses listed in the list of
SimTel.NET mirrors in Where to find, above to a valid URL by prepending
`ftp://' to it.  For example, the URL for FTP from CCT
(ftp://ftp.coast.net/Coast/vendors/djgpp/).  Typing such a URL into your Web
browser will cause it to display the directory contents, and you can then
click on individual files to download them.

Gopher users can get CCT files with a Gopher client
(gopher://gopher.oakland.edu).

For those of you who only have an e-mail connection to the Internet, CCT
files may be also obtained by e-mail from various ftp-mail servers or through
the BITNET/EARN file servers.  For details send a message to the CCT list
server <listserv@Coast.NET> with this command in the message body:

      get simtel-mailserver.info

Another ftp-mail server is `ftpmail@pub1.bryant.vix.com'.  Send a message
with a single word "help" in the body to the above address, to get
instructions.

Walnut Creek, the company which maintains the SimTel.NET collection where the
DJGPP archives are held, also sells a `DJGPP Development System CDROM'.  It
includes *everything* from the DJGPP sites on SimTel.NET (even the old
version 1.12 of DJGPP), some example source code packages to get you started,
and a ready-to-run feature, which allows you to use DJGPP directly from the
CDROM; you can also use a provided install program to copy some or all of the
packages to your hard disk.  To order the CDROM, go to the Walnut Creek Web
site (http://www.cdrom.com/titles/prog/x2ftp.htm).

Salvador Eduardo Tropea (SET) <salvador@inti.gov.ar>, himself a veteran DJGPP
user and developer, sells a low-cost CDROM with all the DJGPP v2 files, plus
a lot of related stuff downloaded from the net.  For information, send email
to <set-soft@usa.net>.

4.5 What Files to Download?
===========================

**Q*: What's the minimum set of `.zip' files I need to download?*

*A*:  This depends on what you are planning to use DJGPP for.

The following table lists required and recommended files by category.  An
alternative method of choosing the files suitable for your needs is to use
the DJGPP zip-picker feature (http://www.delorie.com/djgpp/) which will guide
you through the process.

   * To only run DJGPP-compiled programs, you MUST download all of these(1):

    `v2/readme.1st'
          This explains how to install DJGPP and get started with using it.

    `v2/faq211b.zip'
          The latest edition of this FAQ list.  Use it whenever you have
          problems installing and using DJGPP.

    `v2/frfaq21b.zip'
          The latest version of the FAQ translated into French by Francois
          Charton <deef@pobox.oleane.com>.

    `v2misc/csdpmi4b.zip'
          CWSDPMI, the DJGPP free DPMI server.  DJGPP programs cannot run
          without DPMI services, which provide a way to run 32-bit
          protected-mode programs under real-mode MS-DOS.  (If you can get
          DPMI services in your environment, like if you run under Windows,
          QDPMI, or OS/2, you don't need CWSDPMI, but I recommend downloading
          it nonetheless so you can try it in case you have trouble with
          other DPMI servers.)

    `v2misc/pmode11b.zip'
          This is an alternative DPMI server, PMODE/DJ.  Its memory footprint
          is smaller than CWSDPMI and it can be bundled with DJGPP programs
          to make a stand-alone executable that doesn't require a DPMI server
          to run.  PMODE/DJ doesn't support virtual memory and its
          implementation of the DPMI spec is a bit more restricted than that
          of CWSDPMI, but it is faster, and therefore more appropriate for
          high-performance interrupt handling.

   * For developing C programs (no C++), you MUST download all of the above,
     plus the following:

    `v2gnu/bnu281b.zip'
          The GNU Binutils, including `as', the GNU assembler; `ld', the GNU
          linker; and their docs.  GCC calls these utilities during
          compilation.

    `v2/djdev201.zip'
          C header files and libraries, library reference, minimal development
          environment, DJGPP-specific utilities and their documentation.
          Required to compile/link programs.

    `v2gnu/gcc281b.zip'
          The GNU C Compiler binaries and docs (including the docs for the C++
          compiler).

    `v2gnu/txi312b.zip'
          Info, a stand-alone program to read GNU hypertext documentation
          files, and an environment to produce such files.  Without `info',
          you cannot read the C library reference and the docs included with
          the ported GNU software packages.  This package also includes the
          `install-info' utility, which helps to install Info docs of
          optional utilities that you download.  It also includes several
          files required to format Texinfo docs for printing.

   * For developing C++ programs, you will need all of the above, plus the
     following:

    `v2gnu/gpp281b.zip'
          The GNU C++ compiler binary (the docs are part of the gccNNNb.zip
          package, see above), the C++ header files and standard C++ class
          libraries, including the STL, and their docs.

    `v2gnu/lgp2811b.zip'
          Additional GNU C++ class libraries.  This library is now deprecated
          and no longer maintained.  I suggest not to use it.

    `v2gnu/obc281b.zip'
          If you want to develop Objective-C programs, you will need this
          file, which includes the Objective-C compiler and header files.
          More information about Objective-C is available from Brad Cox's
          home page (http://www.virtualschool.edu/lang/objectivec/).

   * The following are some optional packages which you might want:

        - Debugging:

         `v2gnu/gdb416b.zip'
               GDB, the GNU Debugger and its docs.  (Note that the `djdev'
               distribution includes two simpler, assembly-level debuggers,
               `edebug' and `fsdb.'  The latter presents a user interface
               similar to that of Turbo Debugger.)

        - Additional development tools (consider getting at least the Make
          distribution):

         `v2gnu/mak377b.zip'
               GNU Make program with its docs.  (Make is a program that can
               automatically compile/link a program given the description of
               dependencies between the various source and object files, on a
               special file called `Makefile'.)  You should install Make 3.75
               or later if you use DJGPP v2.01 (previous ports of Make have
               subtle incompatibilities with v2.01 tools).  The DJGPP port of
               Make supports Unix-style shells (as well as DOS `COMMAND.COM'
               and its `4DOS/NDOS' replacements) and can be used to run Unix
               Makefiles if you install a Unix-style shell (e.g., `bash') and
               auxiliary utilities.  It also supports long filenames on
               Windows 9X and MS-DOS pathnames with drive letters.

         `v2apps/rhide14b.zip'
               The RHIDE integrated development environment for DJGPP
               (similar to Borland IDE), written by Robert Hoehne
               <robert.hoehne@gmx.net>.  The latest version features an
               integrated debugger, based on GDB code; a stand-alone version
               of GDB with a Turbo Vision interface (but not all GDB features
               can be used); and support for user interface in languages
               other than English (using a port of GNU `Gettext' library).
               Latest developments and beta versions of RHIDE are available
               from its home page
               (http://www.tu-chemnitz.de/~sho/rho/rhide.html).

         `v2/djlsr201.zip'
               The sources of the DJGPP C library and utilities written
               specifically for DJGPP.  If you can afford the disk space (it
               requires about 10MB), I recommend installing or at least
               downloading it, so you can easily fix possible library bugs.

         `v2gnu/bsh1147b.zip'
               Bash (`Bourne-Again SHell'), the GNU shell, and its docs.  If
               you mostly work in Unix environment, you will feel right at
               home using `bash' as your interactive shell.  It is also great
               as a batch shell for running Unix-born shell scripts and
               Makefiles when these are too complex to convert them to MSDOS.
               If you install `bash', you should also install auxiliary
               utilities (Fileutils, Textutils, Sh-utils, Grep, Diffutils,
               Findutils, Sed and Gawk) as these are usually invoked from
               many shell scripts and Makefiles.

         `v2gnu/bsn125b.zip'
               Bison, a Yacc-like parser generator, and its docs.  You will
               need it if you intend to build a compiler or a parser for some
               language.

         `v2gnu/dif271b.zip'
               GNU Diffutils (diff, cmp, diff3, sdiff), and their docs.  If
               you need to submit patches or changes to DJGPP or GNU sources,
               you will need the GNU `diff' program from this package.
               `diff' is also required by almost all configuration-management
               packages, such as RCS.

         `v2gnu/emacs.README'
         `v2gnu/em1934*.zip'
               GNU Emacs, the most powerful, customizable, extensible
               programmer's editor known today.  The DJGPP port supports
               mouse, menu bar, pop-up menus, color syntax highlighting,
               reading Info documentation and compilation from within the
               editor, long filenames on Windows 9X, and much more.  Emacs
               can and should be used as an integrated development
               environment (another alternative is RHIDE, see above).  Please
               read the file `emacs.README' before you begin downloading the
               rest.

         `v2gnu/fil316b.zip'
               GNU Fileutils, including `ls', `rm', `cp', `mv', and others.
               Highlights of the latest port: `ls' supports colorization of
               files (like on Linux), `ln -s' knows about DJGPP-style
               "symlinks" (see symlink feature of DJGPP in Section 22.4,
               elsewhere in this document), `install -s' will strip
               executables on the fly, and all the utilities support long
               filenames on Windows 9X and numbered backups (even on plain
               DOS).  This package is a must if you want to run Unix shell
               scripts, as they use some of these utilities *a lot*.

         `v2gnu/find41b.zip'
               GNU Findutils, including `find', `xargs', and `locate'.  These
               programs are used to process a group of files which share some
               common attributes, like the file name pattern, read/write
               permissions, file time-stamps, etc.  Since DOS has its own,
               incompatible program called `find.exe', you will need either
               to make sure DJGPP's `bin' subdirectory is before the `C:\DOS'
               directory (for DOS and Windows 3.X) and `C:\WINDOWS\COMMAND'
               directory (for Windows 9X) on your `PATH', or to rename the
               DOS `find' program to some other name.

         `v2gnu/flx254b.zip'
               Flex, a Lex-like lexical analyzer generator, and its docs.
               Required to build compilers or programs which break streams of
               characters into lexical tokens.

         `v2gnu/gwk302b.zip'
               GNU Awk, an interpreter for a powerful text-processing
               language with many built-in functions.  Gawk is also invoked
               by many shell scripts, so if you use Bash or need to run shell
               scripts, you should download Gawk.

         `v2gnu/grep22b.zip'
               GNU Grep package and its docs.  The programs of this package
               are used to search for strings or regular expressions within
               files.  You will also need this if you use Emacs (which has
               commands that invoke Grep) or if you want to run Unix shells
               and Makefiles.

         `v2gnu/idu32b.zip'
               GNU Id-utils and their docs.  These utilities are used to
               quickly search for tokens in all the files that comprise a
               directory tree (e.g., a large project).  They are similar to
               `Grep', but much faster, and their notion of a token is
               sensitive to the source language of the scanned file.

         `v2gnu/pat25b.zip'
               GNU Patch program and docs.  Required to apply patches to
               sources given a source-level patch-file generated by `diff'.

         `v2gnu/perl54b.zip'
               Perl, a powerful scripting and text-processing language
               implemented as an interpreter.  Many sophisticated scripts,
               like `texi2html'(2), use Perl.

         `v2gnu/sed302b.zip'
               GNU Sed (a batch editor) program and its docs.  Many ported
               packages require it during the build process on MSDOS.

         `v2gnu/shl112b.zip'
               GNU Sh-utils.  A must if you use the port of `bash' or want to
               run Unix Makefiles, but some utilities (such as `env' or
               `test') can also be very useful on their own right.

         `v2gnu/txt122b.zip'
               GNU Textutils.  Includes many useful programs, such as `sort',
               `wc', `cat', `join', `paste', `od', and `uniq'.  Unix shell
               scripts and Makefiles call some of these *a lot*, so you
               should install this package if you run them.

        - Developing text-mode and graphics GUI applications:

         `v2tk/grx23.zip'
               A graphics library for DJGPP.  Note that it is still in
               development, so some advanced features might not work.  GRX is
               quite portable to other operating systems: it is known to work
               with several DOS compilers, including Borland and Watcom; on
               Linux with svgalib and X11, and on several Unix platforms with
               X11R5 or later version of X-Windows.  Also, GRX is the only
               library that supports printing out graphics images (check out
               the `addons/print' directory in the GRX distribution).  A
               significant drawback of GRX is that its docs is *very* outdated
               and incomplete.

               Hartmut Schirmer <hsc@techfak.uni-kiel.de> is the current
               maintainer of GRX.  GRX is distributed under the GNU Library
               License (a.k.a. LGPL).

         `v2tk/bcc2grx.zip'
               The interface library to convert Borland graphics calls into
               calls to GRX library functions.

         `v2tk/alleg30.zip'
               A powerful game-writing and graphics library.  This is an
               alternative to GRX (see above), even if you don't need to
               develop a game.  It is somewhat less portable than GRX to
               other operating systems, but its documentation is
               significantly better and up-to-date.  Unlike GRX, Allegro is
               *not* under LGPL, it is free.  A port of Allegro to Win32 and
               to Linux is in the works (initial versions are available).

               By popular demand, Allegro now has its mailing list.  To post
               a message to the list, send email to <allegro@canvaslink.com>.
               To subscribe, send a message to <listserv@canvaslink.com>
               with the text "subscribe allegro {your full name}".  Another
               related resource is the Allegro home page
               (http://www.talula.demon.co.uk/allegro/).

         `v2tk/pdc22.zip'
               A public-domain Curses library, for programming text-mode
               user-interfaces which are portable to Unix or ported from Unix.

               Lately, a new version 2.3 of PDCurses was released.  It is
               available via FTP
               (ftp://ftp.lightlink.com/pub/hessling/PDCurses/).

     Note that all of the packages have source distributions (`...s.zip')
     which you can download in case you discover a bug, or want to know more
     about how the tools work.

     For description of additional files not mentioned here, get the file
     `00_index.txt'; it contains a full list of the distribution files and a
     short description of every file.

---------- Footnotes ----------

(1) The version numbers of the packages listed here might not be up to date.
For the latest versions, check out the DJGPP Mini-FAQ posted weekly to the
comp.os.msdos.djgpp news group.  The file LISTINGS.zip available on every
DJGPP site includes one file for every zip that lists all the files inside
that zip; download and unzip it on your machine, and you've got a set of
files you can search for substrings.  Another place where you can look for
the latest versions of all files is on the DJGPP server
(http://www.delorie.com/djgpp/dl/ofc/), which is also a convenient way of
downloading individual files if you have lost them somehow.

(2) Like its name suggests, `texi2html' converts a Texinfo source to HTML.

4.6 How much disk space will I need?
====================================

**Q*: Wow, that's a lot of files.  How much disk storage will I need?*

*A*:  The following lists the approximate disk space required for several
major configurations, and additional storage required for some optional
packages:

Execution-only environment                 300 KBytes  
Developing C programs                      15 MBytes   
Developing C++ programs                    20 MBytes   
Developing Objective-C programs            16 MBytes   
Additional storage for RHIDE               4 MBytes    
Additional storage for DJGPP sources       6 MBytes    
Additional storage for GDB                 1.1 MBytes  
Additional storage for Emacs               30 MBytes   
Additional storage for Flex                280 KBytes  
Additional storage for Bison               310 KBytes  
Additional storage for Diffutils           560 KBytes  
Additional storage for Make                650 KBytes  
Additional storage for Patch               180 KBytes  
Additional storage for Sed                 200 KBytes  
Additional storage for Graphics libraries  4 MBytes    

Note that the above lists only approximate numbers.  In particular, the disk
cluster size can significantly change the actual disk space required by some
of the distributions (those with a large number of files).  The numbers above
are for disks which have 8KB or smaller clusters.

In addition to the space for installing the software, you will need some free
disk space for the swap file.  You should leave enough free disk space to
make the total virtual memory at least 20 MBytes; that will be enough for
most applications.  Invoke the `go32-v2.exe' program without arguments to see
how much DPMI memory and swap space DJGPP applications can use.  Depending on
your DPMI host, you might need to review its virtual memory settings in
addition to leaving free disk space; CWSDPMI only requires that enough free
disk space be available, but other DPMI hosts have special settings to
specify how much virtual memory they let their clients use, as explained in
how to set up memory in Section 15.1, below.

4.7 Can I get away with less megabytes?
=======================================

**Q*: The above table means that I need more than 17 MBytes for C/C++
development environment; that's about 7 1.44MB diskettes to hold even the
compressed archive!!  Seems to me DJGPP is afflicted by the *fatware*
disease...*

**Q*: Pulling that many megabytes through the net from my overloaded
SimTel.NET mirror is almost impossible.  Can't you prepare a ZIP archive
which only includes stuff I can't do without?*

*A*: There are a number of shareware/freeware programs floating around which
allow formatting DOS diskettes to almost twice their usual capacity, so you
can use less floppies.  One such program is 2M
(ftp://ftp.simtel.net/pub/simtelnet/msdos/diskutil/2m30.zip).

To make downloading DJGPP easier, download and compile the `BatchFTP'
program.  It allows you to submit a script of FTP commands and will
repeatedly try to login into the FTP site you specify until the script is
successfully completed.  It is smart enough to understand the messages which
the FTP server sends to you (like `login refused' etc.) and also is nice to
the remote server by sleeping for some time between login attempts.
`BatchFTP' is free software and can be found on many FTP sites
(ftp://oak.oakland.edu/pub/unix-c/networks/batchftp.tar.Z).

`BatchFTP' is a Unix program; those who access the net from their PC (not by
dialing into some Unix host with a shell account), can use one of the
available programs for automated FTP access.

As for the minimal DJGPP installation, volunteers are welcome to prepare such
an archive and make it publicly available, in the same spirit as `EZ-GCC' did
for DJGPP v1.x.

4.8 How to uninstall a DJGPP package.
=====================================

**Q*: How can I uninstall a certain package?*

**Q*: How can I install a newer version of some package without leaving
traces of the older installation?*

*A*:  The `*.mft' files in the `manifest' subdirectory hold the lists of all
the files included in every package you install.  For example, when you unzip
`gcc281b.zip', it puts a file called `gcc281b.mft' into the `manifest'
subdirectory.  The easiest way to remove all those files is to use the
`*.mft' files as response files to a command which deletes files.  For
example:

       rm -f @manifest/gcc281b.mft

The `rm' program is part of the GNU Fileutils package, available as
`v2gnu/fil316b.zip' from the usual DJGPP FTP sites.

When you install a new version of a package, it is best to uninstall the
previous version first, like in the above example, and then install the new
one.

5. The DJGPP Documentation
**************************

  This chapter explains where to find and how to read DJGPP documentation, and
how to solve occasional problems with the docs system.

5.1 Where are the documentation files?
======================================

**Q*: I don't see any documentation files...*

*A*:  The documentation files are in the `info/' subdirectory of your main
DJGPP installation directory.  You will need a program to read these docs,
which are hypertext structured files.  You have several choices:

  a. Use the stand-alone `Info' reader.

     Texinfo
     (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/txi312b.zip)
     includes `INFO.EXE' and its docs.  Unzip it and type `info <Enter>'.  It
     will bring up a (hopefully) self-explanatory online help system.
     Confused?  Press `?' to see the list of all Info commands.  Still
     confused?  Press `h' to have `Info' take you on a guided tour through
     its commands and features.

  b. Use the `Info' command of your favorite editor.

     If you use Emacs, you already know about `Info.'  (What's that?  You
     don't?  Type `C-h <i>' and you will get the top-level menu of all the
     Info topics.)  RHIDE also has an integrated Info reader, which is the
     core of its help system.

  c. Get and install TkInfo, a graphical browser for Info documentation that
     runs on MS-Windows and uses a port of Tcl/Tk.  TkInfo is free and
     available from the Web (http://math-www.uni-paderborn.de/~axel/tkinfo/).


5.2 How to read the docs without `Info?'
========================================

**Q*: I'm too old/lazy/busy to learn yet another browser, and I despise
uGNUsable programs like Emacs.  How in the world can I read the DJGPP docs??*

*A*:  Info files are almost plain ASCII files, so you should be able to view
them with your favorite text file browser or editor.  You will lose the
hypertext structure and you might have a hard time finding the next chapter
(hint: look up the name of the Next node at the beginning of this node, then
use the search commands of the browser, or the Grep program, to find that
name), but other than that you will see all the text.

You can also produce pure ASCII files yourself, if you have their Texinfo
sources.  These are usually called `*.txi' or `*.texi' and should be included
with the source distribution of every package.  (You can use the DJGPP
server's downloading services (http://www.delorie.com/djgpp/dl/ofc/), to
download individual files.)  To produce an ASCII file `foo.txt' from the
Texinfo file `foo.txi', invoke the `Makeinfo' program like this:

      makeinfo --no-split --no-headers --output=foo.txt foo.txi

`Makeinfo' is one of the programs which come with the GNU Texinfo
distribution
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/txi312b.zip).

If you prefer reading the docs through the Web, point your Web browser to the
docs page of the DJGPP Web site (http://www.delorie.com/gnu/docs/).

5.3 How to print the docs?
==========================

**Q*: I like my docs the old way: printed on paper, right near my workplace.
How can I print the documentation files which come with DJGPP?*

*A*: Most of the DJGPP packages already have their docs converted to a
printable format, look for the files named `*d.zip' at the same place where
you got the binary `*b.zip' distribution.  For example, the ready-to-print
docs of GCC 2.8.1 should be in the `v2gnu/gcc281d.zip' archive.  These
distributions include a `.dvi' and a `.ps' file.  The latter can be printed
directly on a PostScript printer.  If you don't have access to such a printer,
you can use the `.dvi' file in conjunction with a "DVI driver" for your
printer to produce a printed copy of the docs.  A DVI driver is a program
that reads the `.dvi' file and translates it into commands for a particular
printer device which cause it to print the document.  DJGPP ports of DVI
drivers for LaserJet series of printers are available on SimTel.NET mirrors
in the v2apps/tex directory
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/tex/dvlj26.zip).
Drivers for DeskJet series are also available from there, in the
`dvdjNNb.zip' archive.  For other devices, download and install the
Ghostscript interpreter which supports a lot of popular printers.

If some package doesn't have a ready `*d.zip' archive, you will need to get
and install a program called TeX or its work-alike, like emTeX.  A DJGPP port
of TeX is available on SimTel.NET
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/tex/TeX.README).  Install
TeX, then run the `texi2dvi' shell script(1) on the docs' *source* files
(called `*.txi' or `*.texi') which you get with the source distribution of
every package you download.  TeX produces a `.dvi' file which you can then
print using one of the available DVI drivers, as explained above.  To convert
a `.dvi' file into PostScript, use the `DVIPS' program; you can find it as
dvps566.zip on the above-mentioned site, together with the TeX port.

If TeX won't run, check that you have the file `texinfo.tex' which defines
the TeX macros specific to Texinfo files.  If you don't, get the latest GNU
or DJGPP Texinfo distribution which includes that file.

If you'd like to produce printed docs of the library reference, TeX might
complain that it cannot find a file named `libc2.tex'.  This file is
generated from all the `*.txh' files in the DJGPP source distribution
(`djlsr201.zip').  In order to build this file, you need to install
`djlsr201.zip' and the C++ compiler, then go to the `src/libc' directory and
type this from the DOS command prompt:

       make -C ../mkdoc
       make doc

If the above command fails due to unresolved externals, you will need to edit
the file `makefile' in the `mkdoc' directory.  It has a line which calls `ld'
(the linker), where you should change `-lgcc -lc' into `-lgcc -lc -lgcc'.
Save `makefile' and try the above commands again.

Note that some documentation files (notably, the one for GCC and Emacs) will
produce voluminous print-outs.  *You have been warned!*

DJGPP comes with a program called `TEXI2PS' which can convert *.txi files to
a crude PostScript; try it if you don't care much about the appearance of the
printed docs.  Its advantage is that you don't need to install any additional
packages, just to fetch the Texinfo sources of the docs.

Finally, if you don't mind paying for the printed documentation, the Free
Software Foundation sells printed copies of manuals for GNU packages.  You
can contact the FSF <fsforder@gnu.org> for details.

For those who prefer reading docs with a Web browser, many GNU manuals in
`HTML' (hypertext) format, suitable for reading with your Web browser, can be
viewed at the DJGPP Web site (http://www.delorie.com/gnu/docs/).  The
`*d.zip' archives also include the docs converted to `HTML', which you can
browse locally on your machine.

---------- Footnotes ----------

(1)  You will need to install the port of Bash and some auxiliary utilities
to be able to run shell scripts; `texi2dvi' itself is part of the GNU Texinfo
distribution and comes with the `v2gnu/txiNNNb.zip' archive.

5.4 Some docs are nowhere to be found...
========================================

**Q*: I looked in my `info/' subdirectory, but I can't find docs for some of
the utilities, like SED or GPROF.*

**Q*: STL, the C++ Standard Template Library, seems to be undocumented...*

*A*: SED and GPROF are documented in the latest GNU releases,
`v2gnu/sed302b.zip' and `v2gnu/bnu281b.zip'.  Download the latest releases,
and you will get the missing docs.

The STL documentation is not included in the GNU GCC distribution (it appears
that nobody has bothered to write a free documentation for it).  But you can
find the STL docs on the net (http://www.sgi.com/Technology/STL/); this
includes the full documentation and a tutorial.  Many books that describe C++
programming also include documentation of large parts of the STL.

If you have some other package without any docs, try downloading the source
archive (`*s.zip') for that package and look inside it, usually in the
directory called `man/' or `doc/'.  Omitting documentation from the binary
(`*b.zip') distribution is generally considered a bug, so if you find the
docs in source distribution only, please report these cases on
comp.os.msdos.djgpp news group, so that next binary release could fix this.

5.5 What are these `foo.1' files?
=================================

**Q*: Some docs files are called `foo.1' or `bar.man' or `baz.nroff', and
they seem to be written in some weird format which is very difficult to read.
How can I convert them to readable text files?*

*A*: That weird format is the `troff' format which is used for writing Unix
"manual pages".  The Unix command `man' converts them to formatted text files
which are usually displayed with a program like `more' or `less' (and here
`less' is considered to be more than `more' :-)).  The formatted file
includes bold and underlined letters produced by over-typing using Backspace
characters.

DJGPP binary `*b.zip' distributions include such man pages already formatted
and ready to be browsed.  To browse formatted man pages, you will need to
install a clone for the Unix `man' command.  One such clone is available from
the DJGPP sites
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/man12b.zip).

`man' knows how to find a manual page file, and will format it if it isn't
formatted already, but to browse these files you will need a program that can
page through a text file and which understands how to show bold and
underlined letters instead of backspace-over-typed characters.  I suggest to
download the DJGPP port of GNU Less
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/lss332b.zip), which uses
colors to show bold and underlined letters.

Having installed `man' and Less, you should be able to view `*.1' files like
e.g. `patch.1' with several alternative tools:

   * Using the `man' command itself: simply typing `man patch' from the DOS
     prompt will cause `man' to look for the man page `patch.1' and pipe it
     to Less.

   * Using the stand-alone Info reader: type `info patch', and Info will
     invoke `man' as its back-end and display the manual page found by `man'.

     Using Info to display man pages has an advantage of displaying the Info
     version of documentation if it is available, and the man page version if
     it's not.  So, by using Info, you don't need to bother to remember which
     version of the docs is available for every topic.  Info also knows about
     special sections in man pages, such as "SEE ALSO", which refer to other
     man pages, and treats them as hypertext links (i.e., you can press <TAB>
     to move between the references and press <Enter> to display the man page
     under cursor).

   * Emacs, the GNU editor, can also display man pages.  Type `M-x man RET
     patch RET', and Emacs will display the `patch' man page highlighted with
     colors.  (You will need to install SED and Gawk, since Emacs invokes
     them when processing the man page.)  Emacs also supports the special
     sections like "SEE ALSO".

Note that all of these alternatives *require* `man' and Less to be installed.

The binary distribution of the DJGPP port of `bash' includes a simple SED
script called `man2txt.sh' which will convert formatted man pages into plain
text; you can then read them with any text browser or editor.  To convert,
invoke Sed like so:

       sed -f man2txt.sh < file.1 > file.txt

If you want to be able to browse *unformatted* man pages, get and install the
DJGPP port of Groff
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/gro110b.zip).  `man' will
automatically call Groff if it finds an unformatted page, so all the ways
mentioned above to browse man pages will work with unformatted pages as well,
once you install Groff.

Note that, for GNU packages, the man pages aren't always updated on a regular
basis.  If you need more up-to-date information, see the Info files.

5.6 What if the docs don't say enough?
======================================

**Q*: OK, I've got the docs and have read them, but I still can't figure out
some details.*

*A*:  Some ported packages include DJGPP-specific or MSDOS-specific `README'
files (named `README.dj', `README.dos' or some such), which explain
DOS-specific issues; you should read them before any serious use of the
package, or in case of any problems.  If this doesn't help, download the
sources and look there, or ask on the net--either the DJGPP News group or
appropriate GNU News groups.

6. When the Compiler (or `Make', or `Info', or ...) Crashes...
**************************************************************

  This chapter explains how to deal with certain problems which may prevent
DJGPP programs from running on your machine.  The first 12 sections describe
specific problems; if yours isn't solved with these techniques, read the
description of the general debugging procedure in Section 6.13.

6.1 GCC or some other DJGPP programs hang
=========================================

**Q*: When I try to compile anything, GCC just hangs!*

**Q*: Some programs, like Info and Less, hang on my Windows 9X machine after
some time, requiring to close the DOS box.  Help!!*

**Q*: Bash hangs on Windows 9X after the first DJGPP program I run from it!*

*A*: If you are using GCC 2.8.1, and if only GCC hangs, then chances are that
you have set the `DJGPP' environment variable incorrectly, or didn't set it
at all, or messed up your `DJGPP.ENV' file by editing it.  Refer to what to
do if GCC hangs in Section 8.1, later in this FAQ, for details about possible
problems with setting `DJGPP'.  When `DJGPP' is not set, or points to a
non-existent directory, the first release of GCC 2.8.1 would enter an endless
loop (the `NTDVM' process on Windows/NT will go nuts allocating memory, as a
result of this).

The latest uploads of the GCC 2.8.1 binary (`v2gnu/gcc281b.zip') were
modified to prevent them from hanging.  This version aborts with an error
message instead of hanging.  You should upgrade to the latest binaries of
GCC, and also set your `DJGPP' variable correctly.

Some people fail to read the release notes which come with GCC 2.8.1, and
install it incorrectly.  If you installed GCC 2.8.1 recently and it began to
hang, now is the time to read those instructions again (they are installed as
`gnu/gcc-2.81/problems.txt').  In particular, GCC 2.8.1 comes with a modified
version of `DJGPP.ENV' which you should install over the stock version.

If interactive programs like Bash, Less, Info, Emacs, and RHIDE are those
which hang, and if it only happens after running another DJGPP program from
within those programs, then your Windows 9X installation is afflicted by a
subtle bug whereby programs which call function 1680h of the Interrupt 2Fh
(to release the rest of their time slice when they are idle) hang after they
spawn another DJGPP program.  A modified version of the library function
`__dpmi_yield', which works around that bug in Windows, is available (it will
be part of DJGPP v2.02 release), and latest uploads of the binaries for the
affected programs should be free from this problem.  If you cannot find a
pre-compiled binary that works, get the sources and rebuild the program with
a fixed version of `__dpmi_yield'.

6.2 GCC says "No DPMI"
======================

**Q*: I'm trying to run `gcc', but all I get is a message saying "Load error:
no DPMI - Get csdpmi*.zip".  What am I doing wrong?*

*A*: You don't have a DPMI server installed, and DJGPP v2 requires it to run.
You can either use one of the commercial DPMI servers (e.g., run GCC in a
DOS box from Windows) or download and install CWSDPMI
(`v2misc/csdpmi4b.zip' from SimTel.NET mirrors) which is a free DPMI server
written for DJGPP.

If you already have CWSDPMI installed, and these messages still appear, it
might be because of a messed up `PATH' setting.  The DJGPP startup code looks
for `cwsdpmi.exe' along the `PATH', and, being optimized for size, it might
not be robust enough to cope with all possible cases of weirdness in the
value of `PATH'.  Try to copy `cwsdpmi.exe' into the same directory as the
program you are invoking, and if that helps, change your `PATH' as
appropriate.

If you see the message "Load error: no DPMI - Get csdpmi*.zip" on Windows/NT,
it most probably means that you have disabled the DPMI services built into
NT.  One way this might happen is if you edit the `autoexec.nt' file and
remove the line which loads `dosx.exe', or change some of the parameters on
that line.  You cannot use CWSDPMI on NT, so your only bet is to restore NT's
built-in DPMI services.

6.3 Buggy DPMI host or junk in DJGPP.ENV can crash v2.x programs
================================================================

**Q*: I cannot run v2 applications: they all hang or reboot my system, while
v1.x apps run OK.  Is this what v2 is all about--getting me out of the DJGPP
community?*

*A*: No, believe it or not, we don't want to oust you.  Your problems might
be caused by a buggy "DPMI" (see DOS Protected Mode Interface in Section
22.5) host installed on your machine.  One DPMI host which is particularly
known to be a source of trouble is the one which comes with Novell NWDOS (and
also Caldera's OpenDOS, which is a derivative of NWDOS).  Please see if DJGPP
programs run when you disable DPMI services of your usual configuration (DJGPP
programs will then use the CWSDPMI host supplied with DJGPP).  To turn off
the DPMI host built into Novell NWDOS and Caldera's OpenDOS, either remove
the `DPMI=TRUE' parameter from the EMM386 command line, or type `DPMI OFF'
from the DOS command prompt.

Another DPMI host which is known to cause problems in DJGPP is Quarterdeck's
QDPMI which comes with QEMM 7.5.  It was reported to cause `Info' and all
DJGPP debuggers to crash.  If you use QDPMI, upgrade to the version 7.53 or
later (patches for that version are available from the Quarterdeck's ftp
site), or disable QDPMI and use CWSDPMI.

6.4 GCC can crash during optimization
=====================================

**Q*: When I compile my program, the compiler crashes, but the problem seems
to go away if I compile without optimization.*

**Q*: The compiler prints "Virtual memory exhausted" and dies while compiling
some long functions with some optimization options, such as -funroll-loops or
-fforce-addr.*

*A*:  For some programs, this can be caused by an insufficient stack.  Some
source files make `cc1.exe' or `cc1plus.exe' need preposterously large
amounts of stack space, but only when you turn on optimizations.  (One user
reported that an innocent-looking C source file required 700KB of stack
before `cc1.exe' was able to compile it with optimizations!)  Try stubediting
the compiler to enlarge its stack, as described elsewhere in this FAQ, how to
enlarge the stack in Section 6.6, before you try any other remedies in this
section.

If GCC reports that it has exhausted virtual memory, you should first see if
your DPMI memory plus the swap space is large enough (run `go32-v2' with no
arguments to display the available memory) and make more memory available.
Some programs really need large amounts of memory to compile and/or link.
For example, linking `cc1.exe' is known to consume more than 12MB of memory.
On Windows 9X, be sure to set the amount of DPMI memory available to the DOS
box to the maximum value of 65535K (64MB) in the DOS box property sheets,
under `Memory', as explained in how to enlarge memory in the DOS box in
Section 15.6.

Some users have reported that GCC seems to run out of virtual memory if
TMPDIR environment variable points to a RAM disk which doesn't have enough
free space.  Changing TMPDIR to point to a hard disk would reportedly save
the day in those cases.

Compiling with PGCC or EGCS variants of the GNU compiler can also sometimes
run out of virtual memory.  These two compilers are memory hogs, especially
when compiling C++ programs, and at high optimization levels.  One particular
case is when your program makes use of many STL classes.  Try compiling
without optimizations.  I'm told that sometimes omitting the -Wall switch
prevents the compiler from using up too much memory (that sounds awfully like
a bug to me), so try that as well.

One user reported that optimization switches force GCC to use a math
co-processor, which can cause it to crash on a machine that lacks a numeric
processor.  Be sure you didn't delete the `emu387.dxe' file from your `bin'
subdirectory, when you compile on such machines, and that your
emulation-related setup is right.  See how to set up FP emulation in Section
11.1, for details.

GCC can sometimes crash when optimizing, especially when compiling C++
programs, in particular if your code has some syntactic or semantic bug.
(This is usually a genuine GCC bug, not something special to DJGPP.)  Upgrade
to the latest version of GCC.  If that doesn't help, then narrow the
offending code fragment using the `#if 0 ...  #endif' paradigm.  If this
fragment includes an error, correct it and try again; if it is syntactically
and semantically correct, then rewrite it as equivalent, but syntactically
different one.

A GCC switch can sometimes help you zero in on the code fragment that causes
GCC to crash.  If you add `-Q' to the GCC command line, it will print the
name of every function it compiles.  The function that makes it crash is
probably the one whose name is the last one printed, or the one after that.

As an extreme measure, don't optimize at all, if that's the only way to make
your program compile.

Another reason for crashes could be some problem with your system hardware or
the BIOS (like if you set an incorrect number of wait states when accessing
memory).  To check, try running the same compilation on another machine, or
review your BIOS settings.

Yet another cause for such crashes can be connected with excess memory usage
that GCC needs when compiling certain programs, which makes some DPMI hosts
fail.  For details about this, see CWSDPMI allocation problems in Section
6.6, below.

6.5 Why does GCC say "cannot exec `as'"?
========================================

**Q*: When I try compiling a program, GCC aborts saying "Installation
problem, cannot exec `as': No such file or directory (ENOENT)".  What does
that mean?*

**Q*: When I try compiling a program, GCC aborts saying "Installation
problem, cannot exec `cpp': No such file".  Huh?*

*A*: This usually means that GCC couldn't find some program it needs to run
to compile your source.  Check the `COMPILER_PATH' environment variable or
what the `COMPILER_PATH' line in the `DJGPP.ENV' file says, and make sure
they point to the directory where DJGPP programs reside.  Also check that the
named directory has all the required programs: `cpp.exe', `cc1.exe',
`cc1plus.exe', `cxxfilt.exe', `gasp.exe', `as.exe', `ld.exe', and (for
Objective-C) `cc1obj.exe.'  A typical case is when people fail to install the
Binutils package
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bnu281b.zip) and GCC
cannot find `as.exe' (the assembler) and `ld.exe' (the linker).  You can use
the `-v' switch to GCC to see what programs it invokes and which one of them
causes the fatal error.

Beginning with version 2.8.0 of GCC, the place where the pre-processor,
`cpp.exe', and the C and C++ compilers, `cc1.exe' and `cc1plus.exe', are
installed, has changed: they are no more in the same directory as `gcc.exe'
itself.  If you are using GCC version 2.8.0 or later, and the compiler cannot
find `cpp.exe', read the installation instructions carefully: the file
`problems.txt' explains how to change the settings on `DJGPP.ENV' so that GCC
will find the pre-processor.

6.6 What does "Internal compiler error" mean?
=============================================

**Q*: During compilation, GCC prints "Fatal: Error in DJGPP installation.
Environment variable DJGPP is not defined" and then aborts...*

**Q*: GCC aborts with "Internal compiler error" when compiling a large C++
program.*

**Q*: GCC behaves erratically when compiling programs, sometimes crashes with
register dump, sometimes compiles okay, sometimes reports "Internal compiler
error".  Why is this happening?*

**Q*: When I try to compile any program, GCC prints "Abort!" and doesn't
compile anything...*

**Q*: The compiler crashes or dies with "Virtual memory exhausted" when I
compile my simple program!*

*A*: The fatal error message about `DJGPP' not being defined means just
that--that your `DJGPP' environment variable is not defined.  The other two
messages you could see are:

      Environment variable DJGPP point to file `XXYYZZ'
      which doesn't exist

or

      Environment variable DJGPP points to wrong or corrupt file `ABCDEFG'

(In both cases, you will see an actual file name instead of `XXYYZZ' and
`ABCDEFG'.)  These messages mean that `DJGPP' points to a non-existing
directory, or to a file whose contents are too messed up.  Beginning  with
version 2.8.1, GCC refuses to work when the `DJGPP' variable doesn't point to
the actual path name of a valid `DJGPP.ENV' file, because GCC uses the value
of the `DJGPP' variable to find out where to look for its subprograms like
`cpp.exe', `cc1.exe', etc.  To solve this, set the `DJGPP' variable as the
installation instructions (in the file `readme.1st') describe.  Also, make
sure you didn't mess up the beginning of the `DJGPP.ENV' file, where the
value of the `DJDIR' variable is computed (when in doubt, compare it with the
stock `DJGPP.ENV' from the `djdevNNN.zip' distribution).

A possible cause for the "Abort!" message is that the `TMPDIR' environment
variable points to a non-writable directory.  If you don't set `TMPDIR' from
your `AUTOEXEC.BAT' or from the DOS prompt, the DJGPP startup code sets it to
the `tmp' subdirectory of the main DJGPP installation directory.  If DJGPP is
installed on a read-only drive, like CD-ROM or an unwritable networked drive,
this default will not work.  To solve this, set `TMPDIR' to point to a
writable temporary directory.  If `TMPDIR' is not set at all, GCC tries to
use `TEMP' and `TMP', in that order, so make sure these also point to a valid
directory.

Internal compiler errors (a.k.a. bugs) can also cause GCC to print "Abort!".
This FAQ describes a procedure that allows you to find the spot in the
sources where the compiler aborts, see use of the -Q switch in GCC
optimizations, above.  Once you find the offending code, you could rewrite it
and/or submit a bug report to the GCC maintainers.

When GCC aborts with a message such as "Internal compiler error" or "Exiting
due to signal SIGSEGV", it might mean a genuine bug in GCC (which should be
reported to FSF), but it can also happen when GCC requests additional chunk
of memory, and the DPMI server fails to allocate it because it exhausts
available memory for its internal tables.  Old releases of CWSDPMI could fail
like this if an application asks for a large number of small memory chunks.
Beginning with release 2, CWSDPMI defines a larger (6KB) default heap that is
configurable by CWSPARAM program to be anywhere between 3K and 40K bytes,
without recompiling CWSDPMI.  You should upgrade to the latest CWSDPMI if you
experience such problems, and if that doesn't help, bump up the size of
CWSDPMI heap using CWSPARAM.

Some innocent-looking programs are known to cause GCC to gobble preposterous
amounts of memory, which could cause it to crash or abort after printing
"Virtual memory exhausted".  One particular case of such programs is when you
initialize very large arrays.  For example, to compile a source which
initializes a char array of 300,000 elements requires more than 60MB(!) of
memory.  You should avoid such constructs in your programs.

Some programs require very large amounts of stack to compile.  DJGPP programs
have a fixed-size stack that is by default 256KB.  If the compiler, `cc1.exe'
or `cc1plus.exe', doesn't have enough stack to compile a program, it will
overflow its stack and crash, or hang, or die with "Internal compiler error".
You can enlarge the stack size of any DJGPP program by running the
`stubedit' program, like this:

       stubedit cc1.exe minstack=512k

I recommend to enlarge the maximum stack size of `cc1.exe' to at least 512K
bytes and that of `cc1plus.exe' to at least 1MB.  Some people report that
they needed to enlarge both the heap of CWSDPMI and the stack of the C++
compiler to make such problems go away.

Note that the problems with insufficient stack size have nothing to do with
the total available memory as reported by `go32-v2'.  A compiler can crash
because of insufficient stack size even though it has gobs of memory
available to it.  When in doubt, always enlarge the compiler stack size.

Sometimes, GCC can crash due to problems with your system hardware.  In
particular, bad memory chips can cause GCC to behave erratically, since the
compiler is a memory-intensive program.  One cause of problems with accessing
memory is incorrect setting of the wait states in your BIOS setup, or too
aggressive CPU cache mode that your motherboard cannot support reliably.  Try
to play with your BIOS setup and see if that helps.

For a program that you wrote, another work-around for the cases where a
program crashes due to failure of CWSDPMI to allocate more RAM is to use an
alternative algorithm for `sbrk', by putting the following somewhere in your
program:

       #include <crt0.h>
       int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;

Note that the Unix algorithm for `sbrk' might cause trouble in programs that
install hardware interrupts handlers.

6.7 What does "Unknown filetype" mean?
======================================

**Q*: I get error messages saying "Unknown filetype" from GCC.*

**Q*: Since a few days ago, whenever I try to run most of the DJGPP programs,
they print a message "C:\DJGPP\BIN\prog.exe: not COFF" and just terminate.
Help!!!*

*A*:  It might be that your DJGPP programs and/or `STUBIFY.EXE' are infected
by a virus.  (This is *not* a joke!  It did happen to a few of us and can
happen even to you.)  As the DOS stub prepended to the DJGPP programs is very
short, many viruses cannot attach themselves to it without overwriting the
beginning of the DJGPP COFF image which specifies vital information such as
location and length of various program sections, therefore triggering this
error from the code in the stub that loads the COFF image.

Another possible cause of the "Unknown filetype" message is that you mix a
v2.0 `gcc.exe' driver with `cc1plus.exe', `cc1.exe' or other programs from an
old v1.x distribution.

6.8 Compiler hangs, but only when invoked from Make
===================================================

**Q*: My compiles run OK from the command line, but hang or crash when I
invoke the compiler from Make.*

**Q*: When I try to compile something, I get a message "16-bit DPMI not
supported".*

*A*: Be sure you aren't inadvertently invoking some 16-bit programs, such as
Borland's Make or `cpp.exe' from Borland C.  GCC cannot run them, and cannot
run under Borland's Make (because Borland's programs are 16-bit DPMI clients,
and the DPMI 0.9 spec doesn't allow mixing them with 32-bit DPMI clients such
as DJGPP programs).  It might be that another program called `make.exe' or
`cpp.exe' is found earlier on your `PATH' than the Make and the preprocessor
which came with DJGPP.  Moving DJGPP's `bin' directory to the beginning of
your `PATH' will usually solve these problems.

Note that if you try to mix 16-bit and 32-bit DPMI clients in Windows DOS box
(like use Borland's Make to run GCC, or invoking Borland's `cpp.exe' under
GCC), the DOS box will usually crash.  So this problem is not specific to
CWSDPMI.

If you *must* use a non-DJGPP compiler or another utility together with DJGPP
programs, one solution would be to find a version of that utility that
doesn't use the 16-bit DPMI services.  For example, many DOS compilers have a
real-mode version that won't conflict with DJGPP.

If you use Make compiled under DJGPP v1.x, you will also experience all kinds
of trouble when invoking programs compiled under DJGPP v2.  That's because
v1.x programs cannot spawn v2 programs directly (the v1.x program sees that
the child is a DJGPP program and tries to call `go32' to run it, but v1's
`go32' cannot run v2 programs).  The result usually will be that the child
either crashes or silently exits.  If that's your problem, be sure to upgrade
your `Make' to the port distributed with v2. (Note that v2.x programs
generally know how to spawn both v1.x and v2.x programs.)  You can use
`go32-v2' to work around this limitation (see description of go32-v2 in
Section 22.13, below), but I suggest doing that only if you absolutely cannot
upgrade to v2's `Make'.

Some users report that v1.x programs might sometimes hang or reboot the
machine when invoked from v2.x Make.  The reason for this is a known bug in
the versions of `go32-v2.exe' program distributed with DJGPP v2.0 and 2.01:
it would not restore the keyboard handler after the COFF image it runs exits.
To work around that bug, don't touch the keyboard throughout the entire run
of Make.

6.9 Info doesn't like some files
================================

**Q*: When I run the Info browser, it tells me it cannot find the node "Top".*

**Q*: Sometimes, when I mistype the name of the Info topic, `info.exe' seems
to hang...*

*A*:  Check your installation of info files.  The file `DJGPP.ENV' in the
root of your DJGPP installation mentions the variable `INFOPATH' which should
point to the directory where Info looks for its files.  It must find there a
file named `DIR', the file you are trying to read, and other files with
`.iNN' or `.NN' extension, where `NN' is a number.  Also, make sure you
didn't edit the beginning of `DJGPP.ENV', where the value of `%DJDIR%' is
computed; if you did, try the original `DJGPP.ENV'.

Also, the `DJGPP' environment variable should be set to point to the full
pathname of the file `DJGPP.ENV'.  See problems with DJGPP variable setting
in Missing headers or libraries, for a description of some frequent problems
with setting the `DJGPP' variable.

Assuming the above checks OK, and all the necessary info files are indeed
installed in those directories (did you remember to give that `-d' switch to
`PKUNZIP' when unzipping all DJGPP packages?), it might be that you have an
old version of `info.exe'.  Upgrading to version 3.12 or later should solve
several problems which cause Info to complain about the "Top" node, or at
least make its error messages more self-explaining.

Another possibility is that the file `DIR' or the Info file that you want to
browse is corrupted.  For example, it might be a compressed file, but without
the telltale `.gz' or similar extension that tells `info.exe' to decompress
it.  You could examine the offending file(s) with a text editor, and
re-install them as needed.

If you invoke Info with a name of a topic that is non-existent or not
installed on your system, and you don't have a `man' command or its clone
installed, versions of Info before 3.12 would wait for 15 seconds before they
print an error message and exit.  If you think Info is wedged, wait for 15
seconds and see what happens then.  The DJGPP port of Texinfo 3.12 removes
this misfeature, so upgrade if you can.

6.10 Info Crashes During Startup
================================

**Q*: Whenever I invoke `info.exe', it immediately crashes!  How can I use
DJGPP without reading all those wonderful docs??*

*A*: One possible reason for this is a bug in `EMM386' shipped with some
versions of DOS 6.x.  This bug is only triggered if your system loads the
`DISPLAY.SYS' driver, usually to display non-US characters supported by
national code pages.  In addition, this bug causes Info to crash only if it
is run in 35- or 40-line display mode; any other display size avoids the
problem.  (The default display mode is 40 lines, as set in the `[info]'
section of `DJGPP.ENV'.)  So either switching to another display size, or
removing either `EMM386' or `DISPLAY.SYS' from `CONFIG.SYS', should prevent
Info from crashing.

If you use DJGPP v2.0, yet another cause of crashes in `Info' might be
trailing whitespace in the `DJGPP.ENV' file.  The telltale signs of this
failure are a stack dump that is bogus or doesn't start with your `main'
function, or a series of SIGSEGV that won't stop.  Actually, this is a bug in
the DJGPP v2.0 startup code, so any v2.0 program could crash in this way, but
since the last section of stock v2.0 `DJGPP.ENV' belongs to `Info', it is the
one which suffers most from this bug.  Make sure your `DJGPP.ENV' doesn't
have a `^Z' character at the end (some DOS editors put it if you edit the
file), and doesn't end with a blank line.  Alternatively, upgrade to DJGPP
v2.01 or later, where that bug is fixed.

6.11 Why does Bash crash?
=========================

**Q*: Bash crashes on me when I invoke shell scripts...*

**Q*: Why does Bash say "pipe error: Access denied" when I try to run two
programs via a pipe?*

**Q*: When I run certain complex shell scripts, Bash sometimes prints a
message saying "Cannot make a child for command substitution: (null)".  What
gives??*

*A*: If Bash crashes when you invoke shell scripts, check whether those
scripts have `#!/bin/sh' on their first line.  If they do, the most probable
reason for the crashes is that you don't have `sh.exe' anywhere on your
`PATH' (it does *not* have to be in `/bin'!).  Either copy `bash.exe' into
`sh.exe', or create a "symlink" to `bash.exe', like this:

      ln -s c:/djgpp/bin/bash.exe c:/djgpp/bin/sh.exe

(replace `c:/djgpp' with the actual pathname of your DJGPP installation).

Error messages about pipes and command substitution usually mean that your
`TMPDIR' environment variable points to an invalid drive.  Old ports of Bash
had problems with ``command`' substitution, so make sure you have the latest
binaries.

6.12 Why does the Linker Access my CD Drive?
============================================

**Q*: Why is it that every time I link a program, the CD-ROM drive is
accessed?*

*A*: This is a bug in Binutils 2.7 and in an early release of Binutils 2.8.1:
the linker would always try to look for its script `djgpp.djl' in a certain
directory on the `D:' or `E:' drive (the former in Binutils 2.7, the latter
in 2.8.1), no matter which disk uses that letter (these accesses usually go
unnoticed with hard disks, but are visible with CD-ROMs, Zip drives, or other
slower devices).  Download and install the latest `bnuNNNb.zip' archive you
can find on SimTel.NET mirrors, and the problem should go away.

You can see which directories on what drives does the linker try to access by
passing the `--verbose' option to the linker.  Here's an example:

      gcc -o hello.exe hello.o -Xlinker --verbose > linker.log

This redirects the linker log to a file which you can then examine.  Since
the list of directories accessed by the linker doesn't depend on the program
being linked, you can try this with any trivial program.

6.13 Other kinds of trouble
===========================

**Q*: I've installed DJGPP just like explained in the `README.*' files, but
when I run gcc, my machine crashes/hangs/needs cold boot.*

**Q*: I get errors I can't figure out when I try to compile something.*

*A*:  Add the `-v' switch to the GCC command line and run it again.  It will
print all the subprograms (compiler passes) it is running.  Then you can see
which subprogram caused the error, or where your machine crashes.  This might
give you a hint on what's wrong.

One cause of such problems might be that your system is set up inefficiently.
If GCC doesn't get enough free RAM, it will run very slowly, and you might
think it crashed when in fact it didn't.  (This kind of problem usually
happens on memory-starved machines.)  Invoking `go32-v2' with no arguments
will report the amount of memory available to DJGPP programs; large programs
might require up to 20MBytes to compile, sometimes more.  If you run from the
DOS box on Windows 9X, set its DPMI memory property to 65535KB (64MB) and try
again.  Check out the system configuration advice in Section 3.9, earlier in
this FAQ list, for other suggestions about your system configuration.

Sometimes, if the `TMPDIR' environment variable points to a full disk, GCC
may hang or crash as well.  Make sure you have enough free disk space where
`TMPDIR' points.

6.14 I cannot keep up with the error messages
=============================================

**Q*: I want to read all the error messages that GCC throws at me, but there
are so many that I can't keep up.  How can I redirect them to a file?*

**Q*: When I add `-v' to the GCC command line, how can I put all the
voluminous output into a file, so I don't miss anything when reporting a
problem?*

**Q*: I have this nifty graphics program which bombs from time to time, but
the registers and traceback info are hidden by the graphics display.  How can
I see it?*

*A*:  Error messages are usually written to `stderr', and stock `COMMAND.COM'
cannot redirect it.  There are several alternatives to do that:

  a. You can use a shell smarter then `COMMAND.COM', such as `4DOS' or
     `bash', which knows how to redirect standard error stream to a file.
     4DOS is shareware and can be found on SimTel.NET
     (ftp://ftp.simtel.net/pub/simtelnet/msdos/4dos/4dos601.zip), while `bash'
     is available from the `v2gnu' directory of DJGPP archives on SimTel.NET
     (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh1147b.zip).

  b. You can also run your program under any one of the programs which save
     all screen output of programs they spawn in a file.  I suggest using a
     program called `SCRIPT', which is similar to its Unix namesake.  It has
     an advantage of saving everything which goes to screen *and* showing it
     on the screen at the same time.  You can find SCRIPT on SimTel.NET
     (ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/script11.zip).

  c. Or you can use the `REDIR' program which comes with DJGPP.  It also
     redirects standard output and/or standard error to a file, but you don't
     get a chance to look at the output while the program runs.  Here's how
     to run GCC with `REDIR':

            redir -o gcc.log -eo gcc -v ...

     (put the rest of the GCC command line instead of the dots).  The
     messages printed by GCC will be written to the file `gcc.log'.


6.15 How to search DJGPP archives for similar problems
======================================================

**Q*: OK, I have all this voluminous output of `gcc -v', but I still have no
clue.*

*A*:  Your problem might be one which has already been posted and solved on
the DJGPP News group.  DJ Delorie <dj@delorie.com> has set up a searchable
News group archive on his Web server
(http://www.delorie.com/djgpp/mail-archives/).  You can search the *entire*
mailing list archives in just a few seconds.  DJ's archives are always up to
date, as they receive and store all posted messages automatically, but the
index is updated every 24 hours, so the last day might not be searchable yet.
To search the DJGPP archives, point your Web browser to the above URL and
specify a list of keywords pertinent to your problem.  You will get a list of
messages which include those keywords; clicking on any of the messages will
get the full text of that message.

6.16 How to ask DJGPP gurus for help
====================================

**Q*: I've read this monstrously-large FAQ, searched the news group archives,
but didn't find anything helpful.  I am totally lost.  *Help!!!**

**Q*: I don't have time to download all these messages, not to mention
looking through them.  Can't you DJGPP gurus help me?  *Please??**

*A*:  DJGPP News group is famous for its outstanding user support.  To get a
fast and effective solution to your problem, you will have to supply the
relevant info about your system, and describe exactly how things went wrong
for you.  To gather this info, do the following:

   * At the DOS command prompt, type `set > environ.lst', then press <Enter>.

   * Invoke the `go32-v2' program (it's in your `bin/' subdirectory) and save
     its output.

   * Post to comp.os.msdos.djgpp news group or send electronic mail to the
     DJGPP mailing list <djgpp@delorie.com> and put into your message the
     description of your calamity, the contents of the file `ENVIRON.LST',
     the output of `go32-v2', the contents of your `AUTOEXEC.BAT' and
     `CONFIG.SYS', and what GCC printed during compilation with the `-v'
     switch (if your problem is that GCC won't work).

   * If your problem involves a program that crashes and prints a stack dump,
     please post that stack dump in its entirety; do *not* omit any details
     from the crash dump.  It's best to run `symify' on the stack dump, and
     post the output of `symify':

            symify -o dumpfile yourprog

     (See detailed description of symify in Section 9.2, for more details.

   * Allow for 2-3 days (more on weekends) for all the reply messages to come
     in, then act according to what they recommend.

Be warned that you might get several dozen messages in reply to your request;
this is not meant to overflow your mailbox or sabotage your relationship with
your system manager, it's just the usual friendly response of fellow
DJGPP'ers to your lonely cry for help.  Some of the replies might suggest
what you already checked and reported in your original message, or even miss
the point altogether.  Be ready for this and don't flame us for trying to
help you as much as we can.

7. Compiler and Linker Performance
**********************************

  This chapter deals with speed of compilation and linking under DJGPP, and how
they could be improved.

  If you already know whether the compiler or the linker is the slow part, go
to the appropriate section; if not, add `-v' to your GCC command line and run
it again.  With the `-v' switch, GCC will print all the programs it invokes,
and you will be able to tell which one is taking most of the time.

7.1 Slow Compilation
====================

**Q*: Why GCC is compiling sooo slooowww?*

*A*:  That depends on what you mean by "slow".  The following table gives
"normal" gcc compilation speed, in source lines per second, on a 166-MHz
Pentium:

Source language  Without optimizations  With -O2  
C++              800                    400       
C                1800                   1000      

On machines faster or slower than P166, scale these numbers accordingly.  For
example, i486/DX2-66 is about 4 times slower than P166.  When comparing to
this table, don't forget to count header files your program `#include's' in
the total line count.  And *don't* check compilation speed on very short
programs (like the classic `"Hello, world!"'), because the overhead of
loading the multiple passes of the compiler will completely hide the compiler
performance.  It is also useful to run the compilation twice in succession,
especially if you have a disk cache installed, to prevent the overhead of the
first load from skewing the results.

If your results are close to these (deviations of a few percent are
considered "close" here), then that's as fast as you can get with GCC.  If
they are *significantly* lower, you may indeed have a problem; read on.

First, check to see if GCC pages to disk when it compiles.  This is
manifested by a heavy disk traffic which won't go away even if you have a
large write-back disk cache installed.  To be sure, disable the virtual
memory services for your DPMI host (for `CWSDPMI', load it before your
program with the `-s-' switch, or use the `CWSPARAM' program to point the
swap file to a non-existent drive), or use or `CWSDPR0' or `PMODE/DJ' as the
DPMI host, and then run the compilation again; if the compiler aborts with an
error message saying there isn't enough memory, then it *was* paging in your
original environment.

If paging does happen, you need to free more extended memory.  If you have a
RAM disk, make it smaller, or don't use it at all (it only makes compiles run
about 10% faster), or make your disk cache smaller (but don't discard the
disk cache altogether); if you have other programs which use extended RAM,
make them use less of it.  Failing all of the above, buy more RAM (see the
description of reasonable configuration in Section 3.8).  Also see
recommendations for optimal software configuration in Section 3.9.

If GCC doesn't page, check the settings of your disk cache.  If you don't use
a cache, install one--this can slash your compilation times by as much as
30%, more so when compiling a large number of small files.  If you already
have a cache, enable its delayed-write (a.k.a. write-back, a.k.a.
staggered-write) operation.  Some people disable the delayed-write feature
for safety reasons, to avoid losing files due to system crashes.  If you are
worried about this, you can usually gain performance without sacrificing
safety by enabling delayed-write together with an option that causes the
cache to flush the write-behind data before the system returns to the DOS
prompt.  (For `SmartDrv' disk cache, this is achieved by specifying `/N/F'
switches instead of `/X'.)  GCC usually gains a lot when you set up your
cache in such a way, because each compiler pass (pre-processor, compiler,
assembler) must write temporary files that are used by the following passes.

It is also worthwhile to check the settings of your system BIOS.  In
particular, the following items should be checked against your motherboard
vendor recommendations:

Internal and external CPU cache  set to Enable                      
CPU cache scheme                 set to Write-back, if possible     
DRAM and SRAM wait states        vendor-recommended optimal values  

Incorrect or suboptimal settings of the above items can explain as much as
30% performance degradation on 486 machines, and as much as 500% (!) if you
have a Pentium CPU.

7.2 Slow Linking
================

**Q*: The compiler finishes in a few seconds, but then the linker grinds away
for more than a minute, even on a very short program...*

*A*:  Try linking the trivial `"Hello, world!"' program; it should take no
more than 7-10 seconds on a 486, 3-5 seconds on a Pentium.  If you see much
slower linking on your system, then the following advice might help you.

A few users have reported that they got much faster linking after they've
stub-edited `ld.exe' to decrease the transfer buffer size to 4KB or even 2KB.
This speedup effect is usually seen when DJGPP is installed on a networked
drive or on a compressed disk, and sometimes when you run DJGPP from a DOS
emulator (such as OS/2 DOS box); when DJGPP is installed on a local disk
drive on plain DOS or Windows, linking speed is not affected by the size of
transfer buffer.  The reason for this seems to be the large number of calls
to `fseek' function issued by the linker, which defeats the benefits of
aggressive buffering imposed by the default 16KB size of the transfer buffer.
(DJGPP v2.02 will introduce a heuristic into the buffering of `stdio'
functions, whereby the size of the buffer for each `FILE *' stream adapts
itself to the behavior of that stream--grows when the stream is read
sequentially, and shrinks when it is seeked.  This should eliminate the need
for stubediting `ld.exe' and other similar programs.)

If you use a disk cache, make sure you enable its write-back (a.k.a.
delayed-write) operation.  Some people disable the delayed-write feature for
safety reasons, to avoid losing files due to system crashes.  If you are
worried about this, you can usually gain performance without sacrificing
safety by enabling delayed-write together with an option that causes the
cache to flush the write-behind data before the system returns to the DOS
prompt.  For `SmartDrv' disk cache, this is achieved by specifying `/N/F'
switches instead of `/X'.

For very large (several MBytes) executables which are built from a large
number of small source files, the link (as opposed to the compilation) stage
might be the one which needs more RAM than you have free, and thus be the
bottleneck of the time it takes to build your program.  Check that the size
of the executable isn't larger than the amount of your free RAM.  If it is,
then it might make sense to use a smaller (or even no) disk cache, and allow
the linker as much physical RAM as it needs.  Make sure that the linker
wasn't stub-edited to make its transfer buffer too small.

Another reason for slow linking might be that the `DJGPP.ENV' file by default
sets `TMPDIR' to a `tmp/' subdirectory of the main DJGPP installation
directory; if DJGPP is installed on a networked drive, this means all your
temporary files go back and forth through the network (and networked disks
are usually not cached on your PC).  In such cases, setting `TMPDIR' to a
directory on your local drive, or to a RAM disk, would probably make linking
faster.

Generally, it is not recommended to install DJGPP on a networked drive.  If
you have to, you should configure your network interface for best
performance.  Consult your network administrator.

8. Compile-time and Link-time Problems
**************************************

  Being of a Unix origin, GCC has a somewhat different flavor of command-line
syntax and its peculiar compilation and link algorithms.  It also has a
plethora of optional switches, some of them obscure or semi-documented.
These are known to confuse users, especially those who had previous
experience with DOS-based C compilers.

  This chapter explains how to solve some of those problems which tend to
appear when compiling and linking your programs.

8.1 GCC can't find headers or libraries
=======================================

**Q*: When I run the compiler it says it couldn't find header files and/or
libraries.  But the headers and libraries are all there, so why won't it find
them?*

**Q*: When I link my programs, ld.exe complains that it cannot open crt0.o,
although that file exists in the lib subdirectory...*

**Q*: I tried to compile a program, but GCC complained about missing header
files `netdb.h' and `socket.h'.  Can somebody please mail me those headers?*

**Q*: Why does GCC complain that it "cannot open -lgcc: File format not
recognized"?*

*A*: When a compiler complains about missing files, you need first to find
out whether they at all exist on your system.  For C header files, look in
the `include' directory and its subdirectories; for C++ header files, look in
the `lang/cxx' directory and its subdirectories; for libraries look in the
`lib' directory.  Some header files and object files which are specific to a
certain GCC version install into the `lib/gcc-lib/djgpp/X.YZ' directory (where
`X.YZ' is the GCC version number, e.g. 2.81), so look there as well.

If a header file indeed is not there, and you cannot find it in the
`djdevNNN.zip' and `gppNNNb.zip' distributions, it probably means that header
belongs to a package which isn't part of the basic DJGPP distribution.  You
need to find that package and install it.  It is important to understand that
if a package is missing, getting hold of the header files like `socket.h' is
not enough: you need the library of the functions whose declarations and
prototypes are in the header.

If the header or the library *does* in fact exist on your machine, then in
order for the compiler to find them, you should have the following variable
set in your environment(1):

      set DJGPP=c:/djgpp/djgpp.env

and it should point to the correct path of the file `DJGPP.ENV' on your
system; the file itself is in djdev201.zip
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/djdev201.zip) in the DJGPP
distribution.  In the above example it is assumed to be in the `C:/DJGPP'
directory, but you should set it as appropriate for your installation.

Most of the problems with "missing" files, including the highly-confusing
message about `-lgcc' ("File format not recognized"), are usually caused by
having the `DJGPP' variable set incorrectly.  The following describes some
problems with defining `DJGPP' which pop up frequently on the DJGPP forum.

Sometimes, people make errors in their `AUTOEXEC.BAT' that cause the DJGPP
variable to be defined incorrectly, or not defined at all (some of the more
common errors are listed below).  To check what is the actual setting, type
from the DOS prompt:

      set > env.lst

then examine the contents of the file `env.lst'.  You should see there a line
like this:

      DJGPP=c:/djgpp/djgpp.env

If a line such as this isn't there, you should investigate the cause for this
(see below for some of the possibilities).

Many problems with setting DJGPP happen when people put excess blanks around
the `=' character, which has the effect of defining "DJGPP " (with the blank)
which is not the same as "DJGPP" (without blanks).  You should make sure
there are no such excess blanks, or DJGPP won't find its files.

Another possible cause of DJGPP variable not being set is that you invoke
another batch file from your `AUTOEXEC.BAT' before the line that sets DJGPP.
Make sure such batch files are invoked with the `CALL' statement, because
otherwise the subsidiary batch file will never return to process the rest of
`AUTOEXEC.BAT' (that's a "feature" of DOS batch file processing).

The code that processes `DJGPP.ENV' assumes that this file resides in the
main DJGPP installation directory.  If that assumption is wrong, the compiler
(and some other DJGPP programs) might fail to find some of the files or
auxiliary programs they need.  *Do NOT move DJGPP.ENV to any other directory!*

Note that if you run DJGPP on Windows/NT, you *cannot* use long names of the
directories in the pathname of `DJGPP.ENV' when you set the above variable in
the environment; you should use their 8+3 aliases instead.  That's because
Windows/NT doesn't support the LFN API for DOS programs, so the DJGPP startup
code won't be able to find the `DJGPP.ENV' file using its long pathname.  For
example, the following setting *won't work* on Windows/NT because
`Development' is longer than 8 characters:

      set DJGPP=c:/Programs/Development/Djgpp/djgpp.env

If the DJGPP variable is set correctly, then check the following possible
causes of this misbehavior:

   * You have edited the file `DJGPP.ENV' in a way that invalidated some of
     the settings there; try restoring the original file from the
     distribution to see if that fixes your problems.  Be sure you are
     familiar with the syntax of `DJGPP.ENV' before you edit it.  The DJGPP
     server has a page with a description of the `DJGPP.ENV' syntax
     (http://www.delorie.com/djgpp/doc/kb/kb_7.html#SEC7)

     The syntax of `DJGPP.ENV' is also described in the `DJGPP Knowledge
     Base', see DJGPP.ENV section in the kb.inf file in (kb.inf)DJGPP.ENV,
     which comes with the `djdev' distribution.

   * Some older versions of Novell Netware cause the linker to fail if the
     libraries or the startup file `crt0.o' reside on a networked drive.
     This is due to a peculiarity of Novell that happens to fail the library
     function `stat' in some cases.  The exact reason of the failure has been
     identified, and the library which comes with DJGPP v2.01 includes a
     version of `stat' that works around that problem, so the linker from
     v2.01 is free of this bug, and upgrading will solve this.  Another
     solution would be to upgrade your Novell software; version 4.x is
     reportedly free of this problem, even if you use DJGPP v2.0.

   * You renamed the `gcc.exe' driver to some other name.  In this case, you
     should edit the file `DJGPP.ENV' to add a section named after the new
     name of GCC, which is an exact duplicate of the section called `[gcc]'.
     DJGPP start-up code uses this file to find environment variables which
     it should put into the environment before the `main' function is called,
     but it searches for the relevant variables using the actual name of the
     program, so when you rename the executable, it can't find its section
     and doesn't put the necessary variables into the environment.

   * Your `FILES=' setting in `CONFIG.SYS' is insufficient, so GCC runs out
     of available handles.

     You should have at least `FILE=15' in your `CONFIG.SYS', more on
     Windows.  See details about FILES= directive in Section 9.6.

   * Your DJGPP directory is on a networked drive, and the network redirector
     doesn't have enough available handles in its configuration.

     Presumably, there should be a parameter in some configuration file or a
     command-line argument to one of the network drivers which sets the number
     of files that can be open simultaneously on a networked drive; you should
     set it to be at least 15.

   * You passed the `-B' switch to GCC.  This overrides the default location
     of `crt0.o' and if you follow `-B' with a directory other than that
     where `crt0.o' resides, the linker won't find it.

     You should not need to use the `-B' or `-L' switches at all if your
     installation is correct and the `DJGPP' variable points to the main
     installation directory, because GCC should be able to figure out all the
     linker switches itself.  If linking fails without explicit `-L' or `-B',
     check out above for the possible causes.

---------- Footnotes ----------

(1) The example uses Unix-style forward slashes, but DOS-style backslashes
can also be used.

8.2 GCC can't find C++ headers
==============================

**Q*: I installed all the packages, but GCC complains it can't find
`iostream.h', `_string.h' and other C++ headers.  Where can I find those
header files?*

**Q*: GCC complains about being unable to find `Complex.h', `Regex.h' and
other header files which start with a capital letter, and I indeed don't see
them in my `lang/cxx/' directory.  Where are they?*

**Q*: My C++ program needs header files whose filenames exceed the 8+3 DOS
filename restrictions, like `stdiostream.h' and `streambuf.h', and GCC cannot
find those files.  How in the world can I write portable C++ programs??*

*A*:  All C++ include files are packaged as part of the GNU C++ compiler
distribution zip file
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/gpp281b.zip), so if you
didn't install it, GCC won't find them.  Files whose names usually start with
a capital letter, on MS-DOS have an underscore `_' prepended so they can be
distinguished from `complex.h', `regex.h' and the like under case-insensitive
DOS.  Change `Complex.h' to `_Complex.h', and `String.h' to `_String.h' in
your source, and GCC will find them.  The same goes for the header
`iostreamP.h'--you should use `_iostreamP.h' instead.  If you don't have the
underscore `_' on your keyboard, you might find using `strclass.h' instead of
`_String.h' easier.

Another possibility to handle header files like `Complex.h' in a portable way
is to pass the `-remap' switch (supported by GCC 2.8.0 and later) to the
pre-processor; see the `cpp' docs and the `README.DJGPP' file in the GCC
distribution, for more info about this feature.

The most probable cause of problems with header files whose names exceed the
DOS 8+3 limits is that you are compiling on Windows 9X, but the "Long File
Names" (a.k.a. LFN) support is disabled.  DJGPP v2.01 comes with LFN disabled
by default on the `DJGPP.ENV' file.  To enable it, set the environment
variable `LFN' to `y', like this:

       set LFN=y

If the problems with long names of header files aren't solved by this, it is
possible that you unpacked the DJGPP distribution with a program which
doesn't support long file names.  The solution is to install DJGPP again
using a different unzip program.

If you have problems with header files with long filenames, and you run under
Windows NT, it usually means that you used an unzip program which supports
long file names on NT; unzip again using a DOS unzip program.  Alternatively,
you could install an LFN driver for Windows NT, see LFN driver for NT in
Section 3.3, earlier in this FAQ.

Another possible cause for problems with C++ include files is that your
source file has a `.c' extension.  GCC then thinks that this is a C program
and doesn't instruct the preprocessor to search the include directories
specific to C++.  Rename your file to `.cc' or `.cpp' extension, or call GCC
with the `-x c++' switch, and the header files will be found.  A full list of
extension rules which GCC uses to determine the source language can be found
in the list of language-specific suffixes in Which language, elsewhere in
this FAQ.

8.3 GCC barfs on C++-style comments in C programs
=================================================

**Q*: My C program compiles OK with Borland's C, but GCC complains about
"parse error before `/' " at a line where I have a "//"-style comment.*

*A*: That's because // isn't a comment neither in ANSI C nor in K&R C.
Borland and Microsoft C compilers support it as an extension.  GCC also
supports this extension (beginning with version 2.7.0), but using the `-ansi'
or `-traditional' switches to GCC disables this extension.  In general, it's
a bad practice to use this extension in a portable program until such time as
the ANSI C standard includes it.  If it's a C++ program, then rename it to
have a suffix which will cause gcc to compile it as such (see list of
language-specific suffixes in Section 8.4), or use `-x c++' switch.  If it's
a C program, but you want to compile it as C++ anyway, try `-x c++'; it can
help, but can also get you in more trouble, because C++ has its own rules.
For example, the following program will print 10 if compiled as a C program,
but 5 if compiled as C++(1):

         #include <stdio.h>
     
         int
         main ()
         {
           printf ("%d \n" 10    //*
     		     / 2    //*/
     		       1
     		       );
           return 0;
         }

If you must have both `-ansi' and C++-style comments, use
`-lang-c-c++-comments' preprocessor switch.  Gcc doesn't accept the
`-lang-XXX' switches on its command line, so you will have to use the `-Wp'
option, like this:

      gcc -c -Wp,-lang-c-c++-comments myprog.c

Alternatively, you can add `-lang-c-c++-comments' to the `*cpp:' section of
your `lib/specs' file (but that will make it permanent).

Bottom line: until the future ANSI/ISO C standard includes this as part of
the C language, it's best to change those `//' comments to C-style ones, if
you really mean to write a C program.  The following SED command will convert
a C program with C++-style comments into a valid C source, provided you don't
have the string "//" in a character string:

      sed "s?//\(.*\)?/*\1 */?" file.c > newfile.c

SED can be found with the DJGPP archives on SimTel.NET, in the `v2gnu'
directory.

---------- Footnotes ----------

(1) While admittedly perverse, this little monstrosity was written with the
sole purpose of demonstrating that C and C++ have quite different semantics
under certain circumstances.

8.4 How does GCC recognize the source language?
===============================================

**Q*: I type `GCC PROG.CC' and GCC complains that it can't recognize
`PROG.CC''s file format.  How come a C++ compiler doesn't recognize a C++
source??*

**Q*: I type `GCC PROG.C' to compile a C program which I already remember to
pass compilation without a single warning, and suddenly it gives all kinds of
strange error messages and unresolved externals.*

*A*:  That's because you typed your source file extension in *UPPER* case.
GCC is *not* case-insensitive about filenames like DOS is, and it uses the
file's extension to determine how to compile a file.  Valid extensions are:

`.cc'
`.C'
`.cxx'
`.cpp'
     C++ source (passed through cpp).

`.c'
     C source that must be passed through cpp first.

`.i'
     Raw C source (no cpp pass).

`.ii'
     Raw C++ source (not to be preprocessed).

`.m'
     Objective-C source.

`.S'
     Assembler that must be passed through cpp first.

`.s'
     Raw assembler source (no cpp pass).

Any other file is passed to the linker, under the assumption that it's an
object file.

In the examples above, `PROG.C' is taken as a C++ program, not a C one, and
`PROG.CC' is passed to the linker as if it were an object file.  You can see
what GCC does by adding the `-v' switch to the GCC command line; if you see
that it's invoking `cc1plus.exe' (the C++ compiler) instead of `cc1.exe' (the
C compiler), or calling `ld.exe' (the linker) on a source file, then you'd
know this is your problem.  If you have problems keeping up with the verbose
GCC output caused by `-v', see how to capture GCC output in Section 6.14,
earlier in this FAQ.

You can override the default rules gcc uses to decide how each input file
should be treated, using the `-x LANGUAGE' switch.  For instance, the command

      gcc -x c++ prog.c

compiles `prog.c' as C++ source.  See -x LANGUAGE switch description in "The
GNU C Compiler Manual", or point your Web browser to
http://www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_8.html#SEC11, for more info on
`-x' options.

8.5 Problems with Objective C
=============================

**Q*: How do I tell gcc my .cc file is to be compiled as Objective-C source?*

**Q*: I compile an Objective-C program, but get unresolved symbols.*

**Q*: I can't compile the Objective-C test program which came with DJGPP.*

*A*:  Give your sources the `.m' extension, or use `-x objective-c' switch to
GCC, so it will *know* you mean to compile with Objective C.

Objective-C was broken in GCC 2.6.0.  The problem manifests itself by
unresolved modules.  If you use that version, you'll have to upgrade to
version 2.6.3 or higher.

8.6 Writing codes fragments which are specific to DJGPP
=======================================================

**Q*: I must put a DJGPP-specific code fragment into my program.  What symbol
should I use in the `#ifdef' directive to make it only visible under DJGPP?*

*A*:  Use `__DJGPP__', like this:

         #ifdef __DJGPP__
         ... DJGPP-specific code ...
         #else
         ... not seen under DJGPP ...
         #endif

`__DJGPP__' has the value of the DJGPP major revision number, so you can
write code fragments which have different behavior under different versions
of DJGPP:

         #ifdef __DJGPP__
         #if __DJGPP__ > 2
         .... will work only in DJGPP v3.x and later ...
         #else
         .... get here for DJGPP v2.x ...
         #endif
         #else
         .... get here in DJGPP v1.x or non-DJGPP environment
         #endif

If you need to distinguish between minor DJGPP revision numbers, use the
symbol `__DJGPP_MINOR__'.  For example:

         #if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 1
         .... will work only in DJGPP v2.01 ....
         #endif

Another DJGPP-specific pre-processor symbol which DJGPP defines is
`__GO32__'; but it is only provided for compatibility with previous versions
of DJGPP (v1.x) and its use should be discouraged.

8.7 Unresolved externals when linking programs
==============================================

**Q*: Why do I get so many unresolved symbols when linking my programs?*

**Q*: Why does GCC complain that it cannot open -lstdcx?*

**Q*: Why do I get "Undefined reference to yywrap" when linking programs
produced by Flex?*

*A*: By default, GCC instructs the linker to only look in two libraries:
`libgcc.a' and `libc.a.'  Some functions aren't included there, so the linker
can't find them.  If you need to link against some optional library, say
`libxy.a', put the library into the DJGPP `lib/' subdirectory and append a
`-lxy' to the link command line.  The Standard C++ Template classes are in
`libstdcxx.a' (it's called `libstdc++.a' on Unix); append `-lstdcxx'.  To use
the additional GNU C++ classes in the `libgpp.a' library (it's called
`libg++.a' on Unix systems), append `-lgpp'.  Flex-generated lexical
analyzers call functions in the `libfl.a' library; you need to append `-lfl'
when linking them.

When linking C++ programs, you can use either one of the `gxx', `gpp', or
`g++' commands (the latter on Windows 9X only) instead of `gcc'; they will
then instruct the linker to also scan the C++ libraries automatically, so you
don't have to remember doing that yourself.

Another reason for undefined references when linking C++ programs is that you
mix GCC and `libstdcxx.a' from different releases: they are usually
incompatible.

An error message about missing `-lstdcx' usually means that the linker cannot
find the standard C++ library, `libstdcxx.a'.  Look into your `lib/'
subdirectory to see if it's there; if not, unzip it from the `gppNNNb.zip'
file.  If `libstdcxx.a' exists but the linker still complains, you most
probably have a problem related to long file names on Windows 9X
(`libstdcxx.a' exceeds the DOS 8+3 limits).  For a quick fix, try to `set
LFN=y' in the environment and see if that helps.  If that doesn't help, make
sure you unpacked `gppNNNb.zip' with an unzip program which supports long
file names.  This issue is further complicated if you use RHIDE, and is
described in full in the file `gnu/gcc-2.81/problems.txt' which comes with
the GCC distribution (and which you should have read before installing it).
Bottom line is that you need to add a line either to `rhide.env' or to
`DJGPP.ENV' which says this:

      RHIDE_TYPED_LIBS_DJGPP.cc=stdcxx

When you add this line, make sure neither it nor the `[rhide]' line have
trailing whitespace, otherwise RHIDE will not recognize these lines.

If your program uses a lot of floating-point math, or needs math functions
beyond those specified in the ANSI/ISO standard, consider appending `-lm' to
your link command line.  The basic math functions required by ANSI/ISO
standard are included in the `libc.a' library, but `libm.a' includes higher
quality versions of these functions, and also some functions not included in
the default library, like Gamma function and Bessel functions, support for
Posix-compliant behavior in case of errors (e.g., it math functions from
`libm.a' always set `errno'), a `matherr' facility, etc.

8.8 How not to lose your head with all these libraries
======================================================

**Q*: I'm lost with all those different libraries.  How in the world can I
find out which functions are included in which library?*

*A*:  You can use the `nm' program to check what functions are included in a
library.  Run it with the `-C' option and with the library as its argument
and look in the output for the name of your function (the `-C', or
`--demangle' option makes the function names look closer to what they are
called in the source file).  Functions which have their code included in the
library have a capital `T' before their name.  For example, the following is
a fragment from the listing produced by `nm':

         c:\djgpp\lib> nm --demangle libc.a
         .
         .
         .
         stdio.o:
         000000e4 b .bss
         000000e4 d .data
         00000000 t .text
         00000098 t L12
         0000001e t L3
         00000042 t L6
         0000004d t L7
         0000006a t L9
         00000000 t __gnu_compiled_c
     	     U _filbuf
     	     U _flsbuf
         00000000 T clearerr
         000000ac T feof
         000000c2 T ferror
         000000d8 T fileno
         0000000c T getc
         00000052 T getchar
         0000002a T putc
         0000007c T putchar
         00000000 t gcc2_compiled.
         .
         .
         .

Here we see that the module `stdio.o' defines the functions `clearerr',
`feof', `ferror', `fileno', `getc', `getchar', `putc' and `putchar', and
calls functions `_filbuf' and `_flsbuf' which aren't defined on this module.

Alternatively, you can call `nm' with the `-s' or `--print-armap', which will
print an index of what symbols are included in what modules.  For instance,
for `libc.a', we will see:

         c:\djgpp\lib> nm --print-armap libc.a
         .
         .
         .
         _feof in stdio.o
         _ferror in stdio.o
         _fileno in stdio.o
         .
         .
         .

which tells us that the functions `feof', `ferror' and `fileno' are defined
in the module `stdio.o.'

`nm' is fully described in the GNU docs. See nm in "GNU Binutils Manual", or
point your Web browser to
http://www.delorie.com/gnu/docs/binutils-2.7/binutils_6.html#SEC5.

8.9 DJGPP uses a one-pass linker
================================

**Q*: I give all the libraries to gcc, but I still get unresolved externals
when I link.  What gives?*

*A*:  `Ld' is a one-pass linker:  it only scans each library once looking for
unresolved externals it saw *until that point*.  This means the relative
position of object files and libraries' names on the command line is
significant.  You should put all the libraries *after* all the object files,
and in this order:

      -lgpp -lstdcxx -lm

E.g., to link files main.o and sub.o into a C++ library, use the following
command line:

      gcc -o main.exe main.o sub.o -lgpp -lstdcxx

or, if you compile and link in one command:

      gcc -o main.exe main.cc sub.cc -lgpp -lstdcxx -lm

If you have any libraries of your own, put them *before* the above system
libraries, like this:

      gcc -o main.exe main.cc sub.cc -lmylib -lgpp -lstdcxx -lm

When you use the `gxx', the `gpp' or `g++' compilation drivers to compile a
C++ program, it automatically names the C++ libraries in the correct order.
(`gpp' and `gxx' are the alternative names for `g++' on DOS, which doesn't
allow the `+' character in file names.)

You can also force the linker to repeatedly scan a group of libraries until
all externals are resolved.  To this end, put the names of these libraries
between the `-(' and the `-)' options (if you invoke GCC to link, use the
`-Wl' or `-Xlinker' options to pass switches to the linker).  Check out the
linker docs for more info about `-( ... -)' groups.

If your installation tree is different from the default, i.e., if you keep
the libraries *not* in the default `lib/' subdirectory, then you should add
that directory to the line in the `[gcc]' section of your `DJGPP.ENV' file
which starts with `LIBRARY_PATH', or put into your environment a variable
called `LIBRARY_PATH' and point it to the directory where you keep the
libraries.  Note that if you invoke the linker by itself (not through the gcc
driver), then `LIBRARY_PATH' will have no effect, because this variable is
only known to the gcc driver.  So if you must call `ld' directly, use the
`-L' option to tell it where to look for the libraries.

8.10 Some functions still not found in C++ programs
===================================================

**Q*: I put all the libraries in the above order, but the linker still can't
find some C++ functions from `complex.h' and `iostream.h.'*

**Q*: I get many undefined references to symbols like `__eh_pc', `terminate',
and `__throw'...*

*A*:  Some C++ functions are declared `inline' and defined on header files.
However, GCC won't inline them unless you compile with optimizations enabled,
so it tries to find the compiled version of the functions in the library.
Workaround: compile with `-O'.

Another cause of missing external symbols might be that your versions of
`libgcc.a' and the compiler aren't in sync.  These cases usually produce
undefined references to symbols such as `__throw' and `__eh_pc'.  You should
only use `libgcc.a' from the same distribution where you got the compiler
binaries.  The reason for these problems is that the setup for supporting C++
exceptions is subtly different in each version of the compiler.

For C++ programs, be sure to compile all of your object files and libraries
with the same version of the compiler.  If you cannot recompile some of the
old C++ object files or libraries, try using the `-fno-exceptions -fno-rtti'
switches to GCC, it helps sometimes.

If you call C functions from a C++ program, you need to make sure the
prototype of the C function is declared with the `extern "C"' qualifier.
DJGPP header files take care about this, but headers you get with third-party
libraries might not.  Failure to use `extern "C"' will cause the linker to
look for a C++ function instead of a C function, which will fail because
names of C++ functions are mangled by the compiler.

8.11 Unresolved djgpp_first_ctor
================================

**Q*: I do everything like your praised FAQ says, but the linker complains
about unresolved symbols with strange names like `djgpp_first_ctor',
`djgpp_last_dtor', etc.  I looked in every library with `nm', and I cannot
find these creatures.  Where in the world are they??*

*A*: These symbols are defined by the `djgpp.djl' linker script that should
be in your `lib/' subdirectory.  When you call `gcc' to link a program, it
invokes `ld.exe' with the option `-Tdjgpp.djl.'  If you invoke `ld' directly
(this is generally not recommended), be sure to include that switch.  If you
did invoke it through `gcc', maybe your linker is set up incorrectly.  Add
`-v' to the GCC switches and check that the command line that GCC gives to LD
includes that switch, that your `lib/' subdirectory includes that script
file, and that the script file is intact and includes the definition of the
above symbols.

Another reason might be that you have edited your `DJGPP.ENV' file in a way
that prevents the linker from finding its `djgpp.djl' script.

Mixing an old v1.x installation with a v2.x one can also cause such problems.
Be sure to delete the entire v1.x tree, or rename it, before installing the
v2.x distribution.

8.12 C++ programs yield large `.exe' file
=========================================

**Q*: It seems that declaring a large `static' array has the effect of
bloating the program image on disk by that many bytes.  Surely there is a
more compact way of telling the loader to set the next N bytes of RAM to
zero?*

*A*:  This only happens in C++ programs and is a (mis-)feature of GCC.  You
can use the `-fconserve-space' switch to GCC to prevent this from happening,
but it also turns off the diagnostics of duplicate definitions, which, if
uncaught, might cause your program to crash.  Thus, this switch isn't
recommended for programs which haven't been completely debugged (if there is
such a creature).  The `-fconserve-space' switch is described in the GCC
docs, see -fconserve-space Option in "GNU C Compiler Manual", or point your
Web browser to http://www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_11.html#SEC14.

If the problems with using this switch doesn't deter you, you can even add
this switch to your `lib/specs' file to make it permanent.

8.13 Why are DJGPP `.exe' files so large?
=========================================

**Q*: I compiled a trivial "Hello world" program and got a 80KB executable
file.  That's ridiculously bloated!*

**Q*: I switched to GCC 2.8.1, and my C++ executables are considerably larger
than when compiled with GCC 2.7.2.1!*

*A*:  Did you link with `-s' switch to `gcc', or run `strip' on the output of
the linker?  If not, the executable includes the debugging symbols, which
makes it quite a lot larger.  (It is not recommended to strip the symbols
except when distributing production programs, because this makes debugging
very hard indeed; that is why `-s' is not passed to gcc by default.)

C++ programs could be further bloated because the release of Binutils 2.8.1
was configured in a way that caused the assembler to put into the symbol
table local labels generated when compiling code that uses exceptions.  Later
uploads of GNU Binutils should solve this problem, so consider upgrading to
the latest `bnuNNNb.zip'.

Judging code sizes by looking at the size of "Hello" programs is meaningless,
since most of the power of protected-mode programming goes wasted in such
programs.  There is no point in switching the processor to protected mode
(which requires a lot of code) just to print a 15-byte string and exit.  The
overhead induced by the code needed to set up the protected-mode environment
is additive; the larger the program, the smaller the overhead relative to the
program size.

Apart from getting to protected-mode, the DJGPP startup code also includes
such functionality as wildcard expansion, long command-line support, and
loading the environment from a disk file; these usually aren't available with
other DOS protected-mode compilers.  Exception and signal handling (not
available at all in v1.x), FPU detection and emulator loading (which were
part of `go32' in v1.x), are now also part of the startup code.

If your program doesn't need parts of the startup code, it can be made
smaller by defining certain functions with empty bodies.  These functions are
`__crt0_glob_function', `__crt0_load_environment_file', and
`__crt0_setup_arguments.'  By defining empty substitutes for all three of
these, you can make the "Hello" program be 28KB on disk.  These functions are
documented in the DJGPP libc reference, which see.  Here's an example of
definitions for these functions that will make the startup code as small as it
gets(1):

       char **__crt0_glob_function (char *arg) { return 0; }
       void   __crt0_load_environment_file (char *progname) { }
       void   __crt0_setup_arguments (void) { }

Note that if you define an empty substitute for `__crt0_setup_arguments',
your program will not be able to access its command-line arguments via the
`argv[]' array.  So this is only recommended for programs which don't accept
any arguments at all.

You can make your program image still smaller by compressing it with a
compressor called DJP
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2misc/mlp107b.zip). DJP is a
DJGPP-specific executable file compressor.  It is fast and has no memory
overhead.  It also knows about DJGPP "Dynamically Loaded Modules" (DLM)
technology.  (Note that DJP before version 1.06 was incompatible with
Binutils 2.8.1 and later(2), so you should always use the latest DJP version
available on SimTel.NET mirrors.)

---------- Footnotes ----------

(1) If you define an empty substitute for `__crt0_setup_arguments', you don't
need to define a substitute for `__crt0_glob_function'.

(2) In particular, running `strip' on a program and then compressing it with
DJP would produce a program that crashes upon startup.

8.14 Linker complains about `djgpp.lnk'
=======================================

**Q*: I run DJGPP under Windows 9X, but the linker complains about
`djgpp.lnk' file...*

*A*:  Do you use DJGPP v2.0 on Windows 9X and have a shortcut to DJGPP in
your current directory?  If so, and if you call that shortcut `djgpp',
Windows will create a file `djgpp.lnk' in your working directory.  In that
case, when `ld.exe' looks for its linking script, it will find this shortcut
instead, and will be totally confused by its format and contents.  In DJGPP
v2.01 and later, the linker script is called `djgpp.djl', so that this
conflict doesn't exist after you upgrade.

8.15 Linker fails to produce the EXE program under Novell
=========================================================

**Q*: When I link my program, it fails to produce the .EXE executable, but
only if I do this on a networked drive...*

**Q*: I run STUBIFY on a networked drive under Novell, but it doesn't produce
a .EXE file.  How come?*

*A*:  You might have another copy of the file with the same name that GCC is
creating in another directory somewhere on your networked drive.  If that
other directory is on your PATH, it is searched by Novell when the linker and
`STUBIFY' try to create the executable file, because that file doesn't exist
in the current directory.  So what might actually happen is that the linker
and `STUBIFY' are overwriting the files they find on your PATH instead of
creating new files in the current directory.

You can verify that this indeed is the problem by searching your networked
disks for files with the same name as those you are trying to build, and
looking at their time stamps.  If that is indeed the problem, then you have
several possible ways of solving it:

  1. You can remove the other files, rename them, or move them to another
     directory that isn't searched by Novell.

  2. You can rename the program you are trying to link.

  3. You can change the way Novell searches for files (a.k.a. "the search
     mode"), so that it won't look in the directories on your PATH.

  4. You can change your access rights to the directory on the PATH where the
     other files reside, so that you won't have write privileges to that
     directory.

  5. You can change the search mode for `STUBIFY' and the linker (or for any
     other program that gives you that trouble) by running commands like
     these:

            SMODE stubify.exe 2
            SMODE ld.exe 2


8.16 Linker fails for large object files or large libraries
===========================================================

**Q*: Whenever I define very large static arrays in my program, the linker
fails saying "could not read symbols: Bad value".  Huh??*

**Q*: I have some large libraries that I cannot link because the linker fails
on them with a message saying "memory exhausted".  I have plenty of virtual
memory on my system, so why would ld fail?*

*A*:  This is a known bug in `ld.exe' from GNU Binutils 2.5.2.  Please
upgrade to DJGPP v2.01 which comes with Binutils 2.7.  If you can't upgrade,
or if the latest `ld.exe' exhibits such bugs, these are your alternatives for
a work-around:

   * In case of a large library, split it into several smaller ones.

   * For a module that defines large data structures, move some of the static
     data to other files, or allocate the space at runtime with `calloc'.

`ld.exe' from GNU Binutils 2.7 (which comes with DJGPP v2.01) doesn't have
most of these problems, but there are still some cases where you might see
such messages.  One such case is the `POVRAY' package, where the failure is
caused by an object file called `_pmlite.o' in the `pmode.a' library.  The
problem here is that `_pmlite.o' is a TASM-compiled file, processed by
`EMXAOUT'.  `EMXAOUT' produces `a.out' object files which `ld.exe' cannot
link if they are in a library.  Either taking that object file out of the
library, or processing the original `_pmlite.obj' with another tool (such as
`OBJ2BFD' or `OBJ2COFF') will solve these problems.  Note however, that the
authors of `OBJ2COFF' have explicitly forbidden commercial use of their tool.

8.17 Building Allegro library fails
===================================

**Q*: When I try to build the Allegro library, liballeg.a, I get some cryptic
message about register-opcode mismatch.  What am I doing wrong?*

**Q*: It seems I miss one of the source files from the Allegro distribution,
because Make cannot find it when I try to build Allegro.*

**Q*: I can't build Allegro: it keeps telling me that I "need to install
gcc2721b.zip".  But I already have GCC installed!*

*A*:  You should get the latest version of Allegro that is available from
SimTel.NET
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/alleg30.zip) or from Shawn
Hargreaves' site (http://www.talula.demon.co.uk/allegro/).

Versions of Allegro before 3.0 are known to have bugs such as above.

8.18 C++ compiler says "NULL redefined"
=======================================

**Q*: When I compile a C++ program which includes some standard C header
files, the compiler prints error messages about redefinition of `NULL'...*

*A*:  This is because GCC 2.8.1 comes with C++ header files which redefine
`NULL' in a way that conflicts with the DJGPP headers.  It's a bug in the GNU
C++ headers, but until it is fixed, you will need to make sure you include
the C++ headers *after* the C headers.  If that doesn't help in your case,
you will need to hack your headers to reconcile them.

8.19 C++ exceptions support
===========================

**Q*: I've written a program that uses C++ exceptions, but instead of
catching an exception, the program prints "Abort!" and dies...*

**Q*: When linking C++ programs, I get messages about undefined references to
`__EH_FRAME_BEGIN__' and such likes.  Huh?*

**Q*: I cannot compile C++ programs that include the header `math.h': the
compiler complains about redefinition of class exception!*

*A*: C++ exceptions were not fully supported in DJGPP before version 2.8.1 of
GCC.  Either upgrade to the latest version or compile with the
`-fsjlj-exceptions' switch to GCC.  GCC support of exceptions before v2.8.0,
was minimal, so even this special switch won't work with previous versions.
If you still use GCC 2.7.2.1 and cannot upgrade, you need to compile with the
`-frtti' compiler switch and include the `typeinfo' header in your program.

Note that exception support with `-fsjlj-exceptions' is very slow, since it
has a significant runtime overhead, even if the exception doesn't occur.

If you already use GCC 2.8.1, these problems could happen if you failed to
replace the `specs' file with the version which comes with the GCC 2.8.1
distribution.  Read the file `README.DJGPP' in the GCC distribution, for more
details.

Exception support in GCC is generally not stable enough yet, so you need to
treat with some suspicion code produced by GCC 2.8.1 for programs that use
exceptions.

Undefined references to symbols like `__EH_FRAME_BEGIN__' are a symptom of
using an old linker script `djgpp.djl'.  You should remove this file from
your `lib' subdirectory, which lets GCC use the new version that installs
into the `lib/gcc-lib/djgpp/X.YZ/' directory (where `X.YZ' is the GCC version
number).  Again, `README.DJGPP' in the GCC distribution has more on this.

If GCC complains about "Redefinition of class exception" when you compile C++
programs which include the header `math.h', you need to replace that header.
GCC 2.8.1 comes with a header `exception' that conflicts with `math.h' from
DJGPP v2.01, which defines a `struct exception'.  Version 2.02 of DJGPP will
correct `math.h', and a corrected version is included in the `gcc281b.zip'
distribution.  The corrected `math.h' is installed into the
`lib/gcc-lib/djgpp/2.81/include' directory, so either delete or rename the
old version in the `include' directory, or copy the corrected version into
`include'.  Another solution is to compile with the `-posix' or `-ansi'
compiler switch, which cause `math.h' to not define `struct exception'.

8.20 How to get GCC to generate assembly code
=============================================

**Q*: How can I peek at the assembly code generated by GCC?*

**Q*: How can I create a file where I can see the C code and its assembly
translation together?*

*A*: Use the `-S' (note: *capital* S) switch to GCC, and it will emit the
assembly code to a file with a `.s' extension.  For example, the following
command:

       gcc -O2 -S -c foo.c

will leave the generated assembly code on the file `foo.s'.

If you want to see the C code together with the assembly it was converted to,
use a command line like this:

      gcc -c -Wa,-a,-ad [other GCC options] foo.c > foo.lst

which will output the combined C/assembly listing to the file `foo.lst'.

If you need to both get the assembly code *and* to compile/link the program,
you can either give the `-save-temps' option to GCC (which will leave all the
temporary files including the `.s' file in the current directory), or use the
`-Wa,aln=foo.s' option which instructs the assembler to output the assembly
translation of the C code (together with the hex machine code and some
additional info) to the file named after the `='.

8.21 What's wrong with `sys/movedata.h'?
========================================

**Q*: Whenever I try to compile a program that includes the `sys/movedata.h'
header file, I get "parse error" messages from the compiler.  Can't you guys
make your system headers right?*

*A*: This is a bug in the `sys/movedata.h' header file which comes with DJGPP
v2.01.  The bug will be fixed in v2.02, but in the meantime you should always
include the `sys/types.h' header before `sys/movedata.h' in your programs.

8.22 How do I create a library of object files?
===============================================

**Q*: I would like to distribute my package as a library that can be linked
into programs, but I'm unsure how to go about it...*

*A*: First, you need to compile all your sources into object `.o' files, like
this:

      gcc -c -Wall -O2 file1.c
      gcc -c -Wall -O2 file2.c
      gcc -c -Wall -O2 file3.c
      ...

The only GCC switch in this example that's required is `-c', the rest are
just recommended for better code generation and diagnostics.

Once you have the object files ready, use the `ar' ("Archiver") utility to
create a library, let's say we'll call it `libacme.a', like this:

      ar rvs libacme.a file1.o file2.o file3.o ...

The `rvs' flags tell `ar' to put named files in to the library, replacing any
previous versions of these files if necessary, print the names of object
files as it puts them into the library, and add an object-file index to the
library, which makes it link faster.

If you use RHIDE, you can create a library by specifying a file with a `.a'
extension as the main target in the project (choose `Project | Main Target
Name' and enter a file name such as `libfoo.a').

The library is now ready to use.  The simplest way to force the compiler to
use it while linking is to mention its name in the link command line, like
this:

      gcc -o myprog.exe myprog.c libacme.a

This is better than just listing in the command line all the object files in
the library, since the latter will cause the linker to link in *all* the
object files, even those which aren't used by the program.

The name of the library which begins with a `lib' and ends with a `.a'
extension is a convention used for convenience.  When the link command line
includes an argument `-lXXYYZZ', GCC (and all Unix compilers) will look for a
file `libXXYYZZ.a' in every directory they search by default.  So, if your
library `libacme.a' is installed in the DJGPP `lib' subdirectory, the user
can instruct GCC to look into it by appending `-lacme' to the link command
line.  Other systems might be configured to look for different names when a
switch such as `-lfoo' is mentioned.  For example, Linux might look in
`/usr/lib' for a file `libfoo.so.4.1', while Alpha/VMS will look for
`SYS$GNU:[LIBRARIES]FOO.LIB;19'.  Windows 98, of course, will look for
something monstrously long like
`C:\Windows\Program Files\Vendors\GNU\gcc\libraries\foo.lib'.  If you don't
follow this convention, you will need to type the full name of the library
file.

If you need to update a certain object file in a library, use the same
command `ar rvs library-name object-name' as above, but only with the name(s)
of the object file(s) you need to replace.

`ar' is documented in the Binutils docs.  To read, type this from the DOS
prompt:

      info binutils ar

9. Running Compiled Programs
****************************

  This chapter discusses various problems which may happen when running DJGPP
programs under different environments, and gives solutions to them.

9.1 My program crashes only in v2.0!
====================================

**Q*: I have this program which runs fine when compiled with DJGPP v1.12, but
crashes and burns in v2.  Isn't it obvious that you guys blew it with v2?*

**Q*: My v2 program crashes, but only under CWSDPMI; it runs OK under other
DPMI hosts like Windows, OS/2 or QDPMI.  Is this a bug in CWSDPMI?*

*A*:  Not necessarily so, it could still be a bug in your program which just
went unnoticed until now.  One area where such things can happen is use of
uninitialized memory.  In v1.x, memory first allocated to the stack or by a
call to `malloc' is always zeroed, but v2 doesn't behave this way, so your
program might exhibit erratic behavior or crash with `SIGSEGV' because of
such bugs.  In particular, if the program behaves differently depending on
which program was run before it, you might suspect bugs of this kind.

To check whether this is the source of your grief, include the header
`crt0.h' in your `main' and set `_crt0_startup_flags' to
`_CRT0_FLAG_FILL_SBRK_MEMORY'; this will fill the memory with zeroes when it
is first allocated.  If the program will run OK after recompilation, then
this is probably the cause of your problem.  To make spotting uninitialized
memory simpler, you can set `_crt0_startup_flags' to
`_CRT0_FLAG_FILL_DEADBEEF' (don't laugh!); this will cause the sbrk()'ed
memory to be filled with the value `0xdeadbeef' (`-559038737' in signed
decimal or `3735928559' in unsigned decimal) which should be easy to spot with
a debugger.  Any variable which has this value was used without initializing
it first.

Another possible cause of problems will most probably be seen only under
CWSDPMI; its telltale sign is a message "Page fault at ..." that is printed
when a program crashes, and an error code of 4 or 6.  Unlike other DPMI
hosts, CWSDPMI supports some DPMI 1.0 extensions which allow DJGPP to capture
and disallow illegal dereference of pointers which point to addresses less
than 1000h (a.k.a. "NULL pointer protection").  This feature can be disabled
by setting the `_CRT0_FLAG_NULLOK' bit in `_crt0_startup_flags'; if this
makes SIGSEGV crashes go away, your program is using such illegal pointers;
the stack trace printed when the program crashes should be a starting point
to debug this.  See how to debug SIGSEGV in Section 12.2, for more details
about these problems.

An insufficient stack size can also be a cause of your program's demise, see
setting the stack size in Section 15.9, below.

9.2 What is that gibberish printed when my program crashes?
===========================================================

**Q*: My program dies with a cryptic message like "Segmentation violation" or
"Unsupported DOS request" or "General Protection Fault" and prints some
funny-looking numbers.  Can't I get some decent human-readable traceback
information, so I could pinpoint where in the program did the problem happen?*

*A*:  Those "funny-looking numbers" *are* the traceback.  They describe the
sequence of function calls which led to the fatal error by giving you the
addresses where each function was called.  You can have these addresses
translated to source line numbers by using the `SYMIFY' program.  `SYMIFY' is
included in the basic DJGPP development environment distribution
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/djdev201.zip), and should be
in your `bin/' subdirectory.  To "symify" the traceback, make sure that your
program was compiled with the `-g' switch, linked *without* the `-s' switch
and *not* stripped.  Now invoke your program and do whatever it takes to make
it crash.  Then, with the traceback still on the screen, type this from the
DOS command line:

      symify your-program-name

Symify then walks through the crash traceback by reading back from video
memory, and matches the hex addresses to the source files and line numbers of
the program.  It then writes back the list of source files and line numbers
right next to their hex addresses.  Now you can start debugging.  More info
about this is available in how to analyze crash dumps in Section 12.2.

One problem with this translation is that it relies on info generated by GCC
that maps the instruction addresses to source line numbers.  This usually
works okay, but one notable exception is when you use inline assembly.  In
this case, GCC only records the last line of the inline assembly block, which
might be way off if the block is large.

You can ask `SYMIFY' to put the stack trace into a file (so you can consult
it later, e.g., from your editor while fixing the bug), by giving it an
output file, like this:

      symify -o problem.dmp yourprog

You can also save the raw stack trace (without source info) to a disk file
and submit it to `SYMIFY' later, like this:

      symify -i core.dmp yourprog

This comes in handy when your program grabs the screen (e.g., for some
graphics) and the stack trace can't be seen.  You can then redirect the stack
trace to a file in Section 6.14, e.g., with the `REDIR' program which comes
with DJGPP.

But what if you *didn't* compile your program with `-g', and you aren't sure
how to recreate the problem which crashed it, after you recompile?  Well, you
can submit the stack dump *after* you recompile your program.  Just press
that PrintScreen key or otherwise save the stack trace, then submit it to
`SYMIFY' from a file as described above, after you've recompiled the program.
Be sure to give gcc all the compilation switches (sans `-s') that you gave
it when you originally compiled your program (in addition to `-g'), including
the optimization switches, or else the addresses shown in the stack trace
might be invalid.

If all you have from the crash is the program counter, the eight-digit hex
number after "eip=", you can still find out the corresponding source line
using GDB.  Assuming that the EIP value is `NNNNNNNN', type this at the GDB
prompt:

      list *0xNNNNNNNN

9.3 Reading and writing binary files
====================================

**Q*: I'm reading/writing data files, but the data gets corrupted.*

**Q*: My program crashes when I read data files, but the same program on Unix
works OK.*

**Q*: When I read a file I get only a small portion of it.*

**Q*: I'm trying to open an existing binary file for read/write using the
`fstream' class, but no mater what I do, the file is always truncated after I
write to it...*

*A*:  Are your data files binary?  The default file type in DOS is "text",
even when you use the `read' and `write' library functions.  Text files get
their newlines converted to `CR-LF' pairs on write and vice versa on read;
reading in "text" mode stops at the first `^Z' character.  Reading binary
files as text will therefore corrupt the data and fail to read all the data
you need.  You must tell the system that a file is binary through the `b'
flag in `fopen', or `O_BINARY' in `open', or use the `setmode' library
function.

Note that the above distinction between binary and text files is written into
the ANSI/ISO C standard, so programs that rely on the Unix behavior whereby
there's no such distinction, are strictly speaking not portable.

You can also use the low-level `_read' and `_write' library functions which
give you the direct interface to the DOS file I/O; they always use binary I/O.

Problems with read/write access to binary files via `fstream' class in C++
programs are due to a bug in the GNU iostream library.  This bug causes
truncation of files, even if you never write to the file.  The library
distributed with GCC version 2.8.1 is free of that bug, so upgrade.  A
workaround is to do something like this:

      fstream inFile;
      int fd = open ("foobar", O_RDWR | O_BINARY);
      inFile.open (fd);

9.4 Buffered screen I/O surprises
=================================

**Q*: My program prompts the user to enter data from the keyboard, then reads
its response.  When compiled with a 16-bit compiler like BCC or MSC it works
as expected, but with gcc the prompt doesn't show, or is printed much later
in the program.*

**Q*: Help!  I cannot make `gotoxy' work!  The text I print appears on the
screen in incorrect locations after I use `gotoxy'!*

**Q*: Why does the text appear in the default colors even though I call
`textcolor' and `textbackground'?*

*A*:  Do you write to screen using buffered I/O (`fprintf', `fputs' and the
like) functions, or send your output to the C++ `cout' stream?  Then what you
see is the effect of the buffering of the standard output streams.  The
buffer is not written to screen until it's full, or until a newline is
output, which might produce very unpleasant and unexpected behavior when used
in interactive programs.

It is usually a bad idea to use buffered I/O in interactive programs; you
should instead use screen-oriented functions like `cprintf' and `cputs.'  If
you must use buffered I/O, you should be sure that both `stdout' and `stderr'
are line-buffered or unbuffered (you can change the buffering by calling the
`setvbuf' library function); another solution would be to `fflush' the output
stream before calling any input function, which will ensure all pending
output is written to the operating system.  While this will generally work
under DOS and DJGPP, note that in some cases the operating system might
further buffer your output, so sometimes a call like `sync' would be needed
to actually cause the output be delivered to the screen.

The functions that set text attributes only affect the screen-oriented output
(a.k.a. "conio") functions (`cputs', `cprintf' etc.), the text written by
`fprintf' and other "stdio" functions doesn't change.  This is unlike some
16-bit DOS compilers where `stdio' functions can also print colored text.

9.5 What do DJGPP programs need to run?
=======================================

**Q*: When I copy my DJGPP application program to another PC where no DJGPP
is installed, I can't run it.  It complains that it cannot find DPMI (??).
Do I really need all of your multi-megabyte installation to run compiled
programs?*

*A*:  No, you don't.  You can either (a) bring the `CWSDPMI.EXE' free DPMI
host to the target machine and put it in the same directory as your compiled
program or somewhere along the `PATH', or (b) install another DPMI host (such
as QDPMI, 386Max, Windows, etc.) on the target machine.

If your program could be run on a machine which lacks a floating-point
processor, you should also distribute an emulator, or link your program with
an emulator library.  See floating-point emulation issues in Section 11.1.

`PMODE/DJ' can be bound with your program, so that you have a single
self-sufficient executable, but remember that `PMODE/DJ' doesn't support
virtual memory, so such programs will only run on machines with enough free
physical RAM.

9.6 How many file handles can DJGPP use?
========================================

**Q*: The library reference tells me that DJGPP programs can use up to 255
file handles, but my program can only use much less, about 30...*

**Q*: I put a `FILES=60' directive in my `CONFIG.SYS', but my programs cannot
use more than 42 when they run on Windows.  Why is that?*

*A*: It's no wonder you are confused: this is one of the most complicated
issues related to the DOS filesystem.  I cannot discuss all the details
here(1), but I will try to explain at least those aspects which directly
affect a typical DJGPP user.

It is true that DJGPP library lets you open up to 255 handles--but only if
the operating system allows it.  The operating system further limits this
number, depending on several factors.

First, if you create new handles by calling the `dup' library function (or
the underlying function 45h of the DOS Interrupt 21h), you can always have up
to 255 such handles, even if the `FILES=' directive sets a much smaller
count.  All such handles refer to the same file or device and moving the file
pointer using one handle moves all the rest of them.

In nested programs (that is, programs that were invoked by other programs),
this is a bit more complicated.  By default, any handle that is open in the
parent program is "inherited" by the child, unless the parent sets the
special `O_NOINHERIT' bit when it opens the file.  Thus, if the parent had 10
files open when it invoked the child, the child program will have 10 less
available handles--245--to work with, even if it only calls `dup'(2).

The `FILES=' directive comes into play when you call `open' or any of its
brethren to create handles.  Unlike the handles created by `dup', `open' (and
the underlying functions 3Dh or 6Ch of Interrupt 21h) create handles that are
*independent* of each other, even if you open the same file over and over
again.  The operating system will not let you create more such handles than
the limit set by the `FILES=' directive.  This is because the `FILES='
directive sets the number of entries in the SFT, the "System File Table"
maintained by DOS, where all the information about every open file is
kept(3).  So, if your `CONFIG.SYS' specifies `FILES=60', you cannot `open'
more than 60 files.  After that, a call to `open' will fail with `ENFILE'
(Too many open files in system).

In practice, you won't even be able to get 60 handles if you have `FILES=60'
in your `CONFIG.SYS', since several handles are always preconnected.  On
plain DOS, 5 handles are already open when a program starts.  These
correspond to standard input, standard output, and standard error streams,
and the other 2 handles are connected to the AUX and PRN devices.  So, if you
have `FILES=60', DOS will only let you open up to 55 independent handles.

The plot thickens even more if you run DJGPP programs on Windows.  Since
Windows itself uses up 10-15 handles in the System Virtual Machine (VM), it
tries to make it up for the DOS programs by adding private file tables to
each DOS box with additional handles, beyond those maintained in the SFT.
The default is to add a private table with 10 handles to each DOS box, but
the `PerVMFiles=' entry in the `[386Enh]' section of the `SYSTEM.INI' file
can override that.  So on Windows, you need to consider the `PerVMFiles='
setting as well, and the resulting limit on open handles is less predictable
since the number of handles used by Windows isn't constant (for example, it
depends on how many fonts are loaded by Windows programs at any given moment).

If your system loads `SHARE.EXE' during bootstrap, things become even more
complicated.  `SHARE.EXE' prevents Windows from adding private file tables
(because it couldn't spy on files open via those private handles), so you get
10-15 less handles than what the `FILES=' directive says, and sometimes even
less than that.  That is how somebody who has `FILES=60' on their
`CONFIG.SYS' could only get 42 handles on Windows.  If you are looking for
reasons not to load `SHARE.EXE', here you have another one.

---------- Footnotes ----------

(1) Those who want *all* the details should consult a good book about DOS
internals, such as `Undocumented DOS, 2nd ed.' by Andrew Schullman, or Geoff
Chappel's `DOS Internals'.

(2) All DOS programs get the default 20-handle table when they start; DOS
only copies the first 20 handles into the child, so it is not possible to
inherit more than 20 handles.  The expansion of the default 20-handle table
to 255 handles is a special feature of the DJGPP library, and it only happens
when the programs exhausts all of the 20 handles while it runs.  Therefore,
when all of the first 20 handles are taken up by files inherited from the
parent program, the child program can fail to start because the DJGPP stub
loader needs one free handle to open and read the COFF executable into
memory.  The stub cannot use the enlarged 255-handle table, since it cannot
call the DJGPP library.  Such problems indeed happen in programs compiled
with DJGPP v2.01; v2.02 fixes this bug.

(3) Each handle created by a call to `open' uses up one slot in the SFT,
whereas a handle created by `dup' just increments the use count of a slot
that was already in use.

10. Writing and Running Graphics Programs
*****************************************

  This chapter discusses some problems and explains some subtle points related
to graphics programming under DJGPP.

Another important source of related information is a tutorial on graphics
programming with DJGPP (http://remus.rutgers.edu/~avly/djgpp.html).

10.1 What GRX driver to use with your SVGA
==========================================

**Q*: Why won't GRX work with my SVGA adapter in any resolution but the
standard VGA?*

**Q*: How do I tell GRX which driver to use with my SVGA?*

*A*:  In order for GRX to work with your SVGA, you should set the `GRX20DRV'
environment variable, like this:

       set GRX20DRV=et4000 gw 1024 gh 768 nc 256

To set that variable, you need to know the chip-set on your adapter; refer to
your SVGA documentation.  Currently, GRX supports the following chip-sets:

`ati28800'
     The ATI 28800 chip-set.

`cl5426'
     Cirrus Logic CL-GD5426 or higher (like CL-GD5428) chip-set.

`et4000'
     Tseng Labs ET4000 chip-set.

`mach64'
     The ATI Mach-64 SVGA.

`stdega'
     The standard EGA adapter.

`stdvga'
     The standard VGA adapter.

`VESA'
     For any VESA-compatible adapter.

After you set the `GRX20DRV' variable, run `modetest.exe' to see what modes
you have available.

If your chip-set is not one of the above, try the `VESA' driver because many
adapters support the VESA BIOS extensions.  If yours doesn't, try installing
a VESA BIOS emulator, like UNIVBE
(ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/univbe51.zip).  The latest
version of UNIVBE and related software is always available from SciTech Web
site (http://www.scitechsoft.com/).

10.2 Accessing the video memory
===============================

**Q*: I try to access the video memory at `0xa0000', but my program crashes
with SIGSEGV...*

**Q*: How can I access the text-mode video memory of my VGA?*

*A*:  Absolute addresses of memory-mapped devices are mapped differently
under DJGPP than what you might be used to under other DOS development
environments.  That's because DJGPP is a protected-mode environment, in which
you can't just poke any address:  that's what protected mode is all about!
To access such absolute addresses, use the so-called "farptr" functions like
`_farpeekb' and `_farpokew'; they are described in the C Library reference.
See more details on using "farptr" functions to access absolute addresses in
low memory in Section 18.4, below.

For text-mode screen updates, you can use the `ScreenUpdate' and
`ScreenUpdateLine' library functions to quickly update the screen from a text
buffer.

Using the `_farpeekX/_farpokeX' paradigm to access memory isn't much slower
than direct access (they compile into 2 machine instructions when
optimizations are enabled).  But if you need even faster access (and don't
want to write it in assembly), see using the "nearptr" access facilities in
Section 18.6, as described below.

If your video card supports the VBE 2.0 standard, you can access the linear
frame buffer as a normal array in memory.  For an example of such a
technique, see the VBE example code by Charles Sandmann
(ftp://ftp.neosoft.com/pub/users/s/sandmann/vbe.zip).  You can also reach this
file via the Web (http://www.rt66.com/~brennan/djgpp/vbe.zip).

Some examples of how to access video memory from DJGPP programs are available
from Brennan Underwood's Web page (http://brennan.home.ml.org/djgpp/).

10.3 Graphics screen restoring under Windows
============================================

**Q*: When I switch away from my DJGPP program under Windows 3.X, then switch
back to it, graphics mode is down, or my screen is all messed up.  Why?*

**Q*: I cannot run my program which uses Allegro: Windows 9X says the program
would work better in DOS Mode...*

*A*:  Windows 3.X only saves the VGA screen in standard VGA modes (1..13h)
when you task-switch away from a DOS application.  In any other mode it only
saves/restores the video mode *number*, but not the actual screen contents.
Your application is most likely still in the proper video mode (if not, it's
probably the fault of the Windows driver for your SVGA card), but the video
memory is messed up.  The beauty of all this is that your program has no way
of knowing that the screen has been taken away and then returned to it.

The only reasonable thing to do is to dedicate a "hotkey" in your application
(e.g., `Alt-R') whose action is to redraw the entire screen.  If you do that,
it's best to start all the way from the beginning, e.g. with a call to
`GrSetMode' (if you use GRX), as there are a few bad Windows video drivers
which do not restore SVGA graphics modes properly upon the switch back.

Windows 9X *does* save and restore the SVGA state, but only if you
task-switch with the `Alt-<TAB>' key.  If the switch happens because of
anything else, like a window popping up, or you pressing the `Start' button,
there's nothing your application can do to ensure it restores correctly,
because it just never gets moved back into focus.  As soon as the user tries
to restore it, Windows 9X comes up with this message:

      This application cannot be restored and will be terminated.

To prevent Windows 9X from getting in your way when running graphics
programs, like popping up messages that suggest to run the program in DOS
Mode, just disable one or more of the relevant properties for that program.
Here's a detailed procedure to disable them all:

   * Right-click on the program's `.exe' file in the `Explorer' or in `My
     Computer', then click on `Properties'.

   * Click on the `Program' tab, then press the `Advanced' button, and change
     the advanced properties as follows:

        - uncheck the `Suggest DOS Mode as necessary' option;

        - check the `DOS Mode' option;

        - uncheck the `Warn before entering DOS Mode' option;

        - check the `Prevent MS DOS programs from detecting Windows' option;

        - uncheck the `DOS Mode' option.

   * Finally, click the `OK' button twice.

Programs which use latest versions of Allegro should not usually trigger
warning messages from Windows, so upgrade to the latest Allegro version if
you keep getting such warnings.

11. Floating Point Issues and FP Emulation
******************************************

  This chapter deals with issues pertaining to floating-point code and
floating-point emulation under DJGPP.

11.1 Floating-point code without 80387
======================================

**Q*: I don't have an 80387.  How do I compile and run floating point
programs?*

**Q*: What shall I install on a target machine which lacks hardware
floating-point support?*

*A*: Programs which use floating point computations and could be run on
machines without an 80387 should either be linked with the `libemu.a'
emulation library (add `-lemu' to your link command line) or be allowed to
dynamically load the `emu387.dxe' file at run-time if needed.  Linking with
libemu makes distribution simpler at a price of adding about 20KB to the size
of the program `.exe' file (the emulator functions will be used only if no
hardware floating point support is detected at runtime).  You should *always*
do one of the above when you distribute floating-point programs.

A few users reported that the emulation won't work for them unless they
explicitly tell DJGPP there is no x87 hardware, like this:

       set 387=N
       set emu387=c:/djgpp/bin/emu387.dxe

This is probably due to some subtle bug in the emulator setup code.  This
code is hard to debug, because the people who developed it have machines with
hardware FP processors.  Volunteers with FPU-less machines are needed to help
debug the above problem.  If you have access to a system without an FPU and
are willing to fix this problem, write to Charles Sandmann
<sandmann@clio.rice.edu> and ask him for guidance.

There is an alternative FP emulator called `WMEMU' (get the file
`v2misc/wmemu2b.zip').  It mimics a real coprocessor more closely, but is
larger in size and is distributed under the GNU General Public License (which
generally means you need to distribute its source if you distribute
`wmemu387.dxe', or distribute the source or objects to your entire program,
if you link it with `libwmemu.a').  Its advantage is that with `WMEMU', you
can debug FP apps on a non-FPU machine.  (But you will need to get the
sources and recompile it, since it was compiled with a beta release of DJGPP
and will cause unresolved externals if you try linking against `libwmemu.a'
without recompiling it.)  Note, however, that even `WMEMU' doesn't solve all
the problems of debugging FP programs on a non-FPU machine (e.g., emulating
flags doesn't work).

11.2 Other FP emulators cannot be used with DJGPP
=================================================

**Q*: I have an 80387 emulator installed in my `AUTOEXEC.BAT', but
DJGPP-compiled floating point programs still doesn't work.  Why?*

*A*:  DJGPP switches the CPU to *protected* mode, and the information needed
to emulate the 80387 is different.  Not to mention that the exceptions never
get to the real-mode handler.  You *must* use emulators which are designed
for DJGPP.  Apart of `emu387' and `WMEMU', the only other emulator known to
work with DJGPP is `Q87' from QuickWare.  `Q87' is shareware and is available
from the QuickWare Web site (http://www.weblane.com/quickware).

11.3 Floating-point emulation under OS/2
========================================

**Q*: I run DJGPP in an OS/2 DOS box, and I'm told that OS/2 will install its
own emulator library if the CPU has no FPU, and will transparently execute
FPU instructions.  So why won't DJGPP run floating-point code under OS/2 on
my machine?*

*A*:  OS/2 installs an emulator for native OS/2 images, but does not provide
FPU emulation for DOS sessions.

11.4 DJGPP doesn't support `-msoft-float'
=========================================

**Q*: I've read in the GCC Info file that gcc has a `-msoft-float' option
which is said to generate library calls for floating point support.  Can this
facility be used for FP emulation on a machine without x87?*

*A*:  The GCC Info file also says that the library required by `-msoft-float'
is *not* part of the GNU C compiler.  As nobody wrote such a library for
DJGPP (yet), this option currently isn't supported.

11.5 Numeric exceptions--sometimes
==================================

**Q*: I have a program which works with FP emulation, but dies with "Numeric
Exception" when run on a machine with a co-processor.  It also runs OK when
compiled with Microsoft C.  Can't you people make your floating-point code
right?*

*A*: This might be still a problem with your program.  Under DJGPP, the 80x87
control word is set up so that it generates an exception when your program
feeds it with a "NaN" ("Not a Number"), while the emulator doesn't have this
behavior.  You should make sure that your program doesn't generate NaNs, or
set the 80x87 control word to a different value.  A library function called
`_control87' can be used from within a program to set the coprocessor to a
non-default state.

11.6 Floating point inaccuracies when using emulator
====================================================

**Q*: I am experiencing inaccurate results in some floating point
calculations, sometimes in the 2nd or 3rd significant digit (like getting
118.401 instead of 120.0).  This is really unacceptable!  (And no, I'm *not*
using a buggy Pentium CPU.)*

*A*:  Are you using the emulator?  If so, it might be that the emulator isn't
as accurate as you expect.  One particular known problem is that it does a
bad job when computing the `atan' function.  So if you use `atan(1.)' to get
the value of `Pi', that might be your problem.  Solution: make `Pi' a
constant, as God intended.  The header file `<math.h>' includes the constant
`M_PI' which you can use; or get the value of Pi from the net
(http://www.diku.dk/~terra/pi.html).

11.7 Floating point exception in Objective-C programs
=====================================================

**Q*: When I run my Objective-C programs on a machine without an FPU, it dies
with a floating point exception, even though I installed the emulator as the
docs say...*

*A*: There is a bug in GCC 2.7.2 whereby it sometimes emits Objective-C code
that crashes ObjC programs.  A patch that fixes it was posted to the DJGPP
news group; get it via the Web
(http://www.delorie.com/djgpp/mail-archives/djgpp/1996/05/05/11:05:21).

You will have to get the GCC source distribution `gcc2721s.zip', install the
above patch, rebuild `cc1obj.exe', and then recompile `libobjc.a' to make the
problem go away.

11.8 Floating point exception in libm functions
===============================================

**Q*: When I use the `ldexp' function, my program crashes with SIGFPE.
What's wrong?*

*A*: There is a bug in the scaling code in `libm.a' library released with
DJGPP v2.0 which affects several library functions such as `ldexp'.  A
work-around is to link without `-lm' switch; this will cause `GCC' to use
math functions from `libc.a'.  If you need math functions which are only in
`libm.a', or if you need `libm.a' for better numerical performance, a patched
version of libm is available
(ftp://ftp.lstm.ruhr-uni-bochum.de/pub/djgpp/libm.zip), courtesy of Tom
Demmer <Demmer@LStM.Ruhr-Uni-Bochum.De>.  DJGPP v2.01 corrects this bug, so
upgrade to that version if you can.

12. Debugging DJGPP Programs
****************************

  This chapter discusses the debuggers you can use with DJGPP and answers some
of the questions you might have when debugging DJGPP programs.

12.1 How to run a DJGPP program under debugger
==============================================

**Q*: How do I debug my programs?*

*A*: First, remember to use the `-g' switch when you compile and link.  This
puts debugging information into your executable.  When linking, don't use the
`-s' switch.  Here are a few examples of compilation and link command lines
when you intend to debug a program:

      gcc -Wall -c -g -O myfile.c
     
      gcc -Wall -O2 -g -o myprog.exe mymain.c mysub1.c mysub2.c -lm
     
      gcc -g -o myprog myprog.o mysub.o

Note that with `gcc', you can use optimization switches when compiling with
`-g.'  To use stabs debugging, compile with `-gstabs3' or `-gstabs+' instead
of `-g'.

Then, to debug the program, use a command line like this (here for `gdb'):

      gdb myprog.exe

Beginning with v2.01, DJGPP debuggers can debug both unstubbed COFF images
and DOS-style .exe executables (v2.0 only supported COFF files).  To debug a
COFF file, name it without the .exe extension, like so:

      gdb myprog

You can use one of several available debuggers with DJGPP:

  a. RHIDE, the DJGPP IDE by Robert Hoehne is available from the DJGPP
     archives
     (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/rhide14b.zip).  It
     includes an integrated source-level debugger based on GDB code and
     presents a user interface like that of Borland's IDE or Turbo Debugger.

  b. `RHGDB', a stand-alone version of GDB with a Turbo Vision user
     interface.  `RHGDB' is part of the RHIDE distribution; it only supports
     part of GDB features.

  c. `FSDB', the full-screen debugger, from the `djdev' distribution.  This
     presents a user interface like that of Borland's Turbo Debugger, but
     unlike TD, *it isn't a source-level debugger* (although it will show the
     source code together with the machine instructions).  It also supports
     data-write breakpoints: a powerful feature for hunting down code which
     overwrites data it shouldn't touch.  Another advantage of `FSDB' is that
     you can easily debug programs that grab the screen, because it can
     switch between the debugger screen and the application screen.  Also, it
     allows to examine the FPU registers.  The main disadvantage of `FSDB' is
     that you cannot easily examine the contents of complex data structures.
     Remember to prepend an underscore `_' to the names of C identifiers when
     you use them with `FSDB'; for C++ programs you will have to find out the
     mangled names of static class variables and methods to make `FSDB'
     understand them.

  d. `GDB' (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/gdb416b.zip),
     the GNU Debugger.  This is a powerful source-level debugger, but it uses
     a line-oriented user interface.  People who are familiar with using
     `GDB' on Unix should know about the following important differences in
     its operation on MS-DOS:

        * The command-line arguments can be only passed to the debuggee(1)
          from within the debugger (use the `set args' or `run' commands),
          not from the `GDB' command line.

        * `GDB' is currently configured for DJGPP in a way that makes loading
          a program and reading a source file when a breakpoint is hit
          *exceedingly* slow: it can take more than a minute for a very large
          program.  Be patient and don't decide that `GDB' is wedged unless
          you've waited several minutes.  A source-level patch to GDB was
          posted to the DJGPP News group, which corrects this problem; you
          can get this patch by searching the DJGPP mail archives.

        * `GDB' doesn't know about PC-specific keys, so you cannot use the
          arrow keys for command history editing.  Use ASCII control keys
          instead (`^F' for forward character, `^B' for backward character,
          `^P' for previous line, `^N' for next line, etc.).

        * The debugger and the debuggee share their file handles.  This
          means, for example, that if your program redirects or closes its
          `stdin' or `stdout', you will be unable to communicate with `GDB'.

        * The initial commands are read from a file named `gdb.ini' instead
          of `.gdbinit', because MS-DOS doesn't allow file names with leading
          dots.

        * `GDB' uses the GNU `readline' package for its input.  The
          `readline' init file (`~/.inputrc' on Unix) is called `/inputrc' on
          MS-DOS and should be in the root directory of the current drive.

  e. `EDEBUG32' is the most basic debugger you can use with DJGPP.  One case
     when you would need to use it is when you debug a DXE module (see
     explanation of what a DXE is in Section 22.14), because `GDB' doesn't
     support debugging DXEs.


You invoke any debugger like this:

      <debugger-name> <program> <args...>

---------- Footnotes ----------

(1) That's the program being debugged, in case you didn't know.

12.2 How to begin debugging using the crash dump info
=====================================================

**Q*: My program crashed with SIGSEGV, but I'm unsure how to begin debugging
it...*

**Q*: Can you help me figure out all those funny numbers printed when my
program crashes?*

*A*: Debugging should always begin with examining the message printed when
the program crashes.  That message includes crucial information which usually
proves invaluable during debugging.  So the first thing you should do is
carefully save the entire message.  On plain DOS, use the <PrintScreen> key
to get a hard copy of the message.  On Windows, use the clipboard to copy the
message to a text editor or the Notepad, and save it to a file.  If you can
easily reproduce the crash, try running the program after redirecting the
standard error stream, where the crash dump is printed, to a file, e.g. like
this:

       redir -e crash.txt myprog [arguments to the program go here]

(here I used the `redir' program supplied with DJGPP; the `-e' switch tells
it to redirect the standard error stream to the named file).

After you've saved the crash message, look at the name of the crashed
program, usually printed on the 4th line.  Knowing which program crashed is
important when one program calls another, like if you run a program from
RHIDE.  Without this step, you might erroneously try to debug the wrong
program.

The next step in the debugging is to find out where in the code did the
program crash.  The `SYMIFY' program will help you translate the call frame
traceback, which is the last portion of the crash message, into a list of
function names, source files and line numbers which describe the sequence of
function calls that led to the crash.  The top-most line in the call frame
traceback is the place where the program crashed, the one below it is the
place that called the function which crashed, etc.  The last line will
usually be in the startup code, in a function called `__crt1_startup', but if
the screen is too small to print the entire traceback without scrolling, the
traceback will be truncated before it gets to the startup.  See how to use
`SYMIFY' in Section 9.2, for more details about the call frame traceback and
`SYMIFY' usage.

If you compiled your program without the `-g' switch, or if you stripped the
debugging symbols (e.g., using the `-s' linker switch), you will have to
rebuild the program with `-g' and without `-s', before you continue.

Next, you need to get an idea about the cause of the crash.  To this end,
look at the first two lines of the crash message.  There you will find a
description of the type of the crash, like this:

      Exiting due to signal SIGSEGV
      Page Fault at eip=00008e89, error=0004

(the actual text in your case will be different).  The following table lists
common causes for each type of crash:

`Page Fault'
     This usually means the program tried to access some data via a NULL or
     uninitialized pointer.  A NULL pointer is a pointer which holds an
     address that is zero; it can come from a failed call to `malloc' (did
     your code check for that?).  An uninitialized pointer holds some random
     garbage value; it can come from a missing call to `malloc'.

     If the message says `Page Fault in RMCB', then it usually means that the
     program installed an interrupt handler or a real-mode callback (a.k.a.
     RMCB), but failed to lock all the memory accessed by the handler or
     functions it calls.  See installing hardware interrupt handlers in
     Section 18.11, for more about this.

`General Protection Fault'
     This can be caused by a variety of reasons:

        - use of an uninitialized or a garbled pointer (beyond the limit of
          the DS segment printed at the time of crash);

        - overwriting the stack, e.g. by writing (assigning values) to array
          elements beyond the array limits, or due to incorrect argument list
          passed to a function, like passing an `int' to a function that
          expects a `double', or passing buffers to a library function
          without sufficient space to hold the results;

        - stack overflow.

     Overrunning the stack frame usually manifests itself by abnormal values
     of the EBP or ESP registers, printed right below the first two lines.
     The normal case is when ESP is *slightly smaller* than EBP, smaller than
     the limit of the SS segment, and usually *larger* than EIP(1); anything
     else is a clear sign of a disaster.

     Another telltale sign of an overrun stack frame is that the symified
     traceback points to a line where the function returns, or to its closing
     brace.

     Suspect a stack overflow if the EBP and ESP values are close to one
     another, but both very low (the stack grows *downwards*), or if the call
     frame traceback includes many levels, which is a sign of deep recursion.
     Stubediting the program to enlarge its stack size might solve such
     problems.  See changing stack size in Section 15.9, for a description of
     how to enlarge the stack.  If you use large automatic arrays, try to
     make their dimension smaller, or make them global, or allocate them at
     run time using `malloc'.

`Stack Fault'
     Usually means a stack overflow, but can also happen if your code
     overruns the stack frame (see above).

`Floating Point exception'
`Coprocessor overrun'
`Overflow'
`Division by Zero'
     These (and some additional) messages, printed when the program crashes
     due to signal `SIGFPE', mean some error in floating-point computations,
     like division by zero or overflow.  Sometimes such errors happen when an
     `int' is passed to a function that expects a `float' or a `double'.

`Cannot continue from exception, exiting due to signal 0123'
     This message is printed if your program installed a handler for a fatal
     signal such as `SIGSEGV' (0123 in hex is the numeric code of `SIGSEGV';
     see the header `signal.h' for the other codes), and that handler
     attempted to return.  This is not allowed, since returning to the locus
     of the exception will just trigger the same exception again and again,
     so the DJGPP signal-handling machinery aborts the program after printing
     this message.

     If you indeed wanted `SIGSEGV' to be generated in that case, the way to
     solve such problems is to modify your signal handler so that it calls
     either `exit' or `longjmp'.  If `SIGSEGV' should not have been
     triggered, debug this as described below.

`Invalid TSS in RMCB'
     This usually means that a program failed to uninstall its interrupt
     handler or RMCB when it exited.  If you are using DJGPP v2.0, one case
     where this happens is when a nested program exits by calling `abort':
     v2.0 had a bug in its library whereby calling `abort' would bypass the
     cleanup code that restored the keyboard interrupt hooked by the DJGPP
     startup code; v2.01 solves this bug.

     Using the `itimer' facility can also cause such crashes if the program
     exits abnormally, or doesn't disable the timer before it exits.

`Double Fault'
     If this message appears when you run your program under CWSDPR0 and
     press the Interrupt key (`Ctrl-<C>' or `Ctrl-<BREAK>'), then this is
     expected behavior (the `SIGINT' generation works by invalidating the
     DS/SS selector, but since CWSDPR0 doesn't switch stacks on exceptions
     there's no place to put the exception frame for the exception this
     triggers, so the program double faults and bails out).  Otherwise, treat
     this as `Page Fault'.

`Control-Break Pressed'
`Control-C Pressed'
     These are not real crashes, but are listed here for completeness.  They
     are printed when `Ctrl-<BREAK>' or `Ctrl-<C>' is pressed, and by default
     abort the program due to signal `SIGINT'.

If you are lucky, and the crash happened inside your function (as opposed to
some library function), then the above info and the symified call frame
traceback should almost immediately suggest where's the bug.  You need to
analyze the source line corresponding to the top-most EIP in the call frame
traceback, and look for the variable(s) that could provide one of the reasons
listed above.  If you cannot figure it out by looking at the source code, run
the program under a debugger until it gets to the point of the crash, then
examine the variables involved in the crashed computation, to find those
which trigger the problem.  Finally, use the debugger to find out how did
those variables come to get those buggy values.

People which are less lucky have their programs crash inside library
functions for which `SYMIFY' will only print their names, since the libraries
are usually compiled without the debug info.  You have several possible ways
to debug these cases:

   * Begin with the last call frame that `SYMIFY' succeeded to convert to a
     pointer to a line number in a source file.  This line should be a call
     to some function in some library you used to link your program.  Re-read
     the docs for that function and examine all the arguments you are passing
     to it under a debugger, looking for variables that could cause the
     particular type of crash you have on your hands, as described above.

   * Link your program against a version of the library that includes the
     debug info.  You can either (a) download such a library from the net
     (see libc with debug info in Section 21.4), or (b) get the sources of
     the library, and recompile it with the `-g' compiler switch.  After
     re-linking the program, cause it to crash and run `SYMIFY' to get a full
     description of the place where it dies.

   * A variation of the previous technique is to paste into your program the
     source of the library function(s) whose names you see in the symified
     traceback, and recompile your program with `-g' switch.  Then run your
     program again, and when it crashes, `SYMIFY' should be able to find the
     line number info for the entire traceback.

   * If you cannot get hold of the sources for the library, you could still
     use assembly-level commands of the debugger to find out the reason for
     the crash.  Here's how:

        - Load the program into a debugger.

        - Display the instruction at EIP whose value is printed on the second
          line of the crash message.  For example, with GDB, use the `x/i
          eip-value' command.

        - Find out which registers are relevant to the crash.  For example,
          if the instruction dereferences a pointer, the register that holds
          that pointer is one possible candidate for scrutiny.

        - Look at the values for the relevant registers as printed in the
          crash message, and find the register(s) which hold abnormal values.
          Common cases include:

            a. A pointer whose value is below 4096 (1000 hex), or above the
               limit of the DS segment.

            b. An index of an array element or an offset into a struct whose
               value is negative, or beyond the last array element, or more
               than the offset of the last struct member.

            c. A linear address of a buffer in conventional memory whose
               value is more than 10FFFFh, or an offset into the transfer
               buffer which is larger than the transfer buffer size (16K by
               default).

        - Once you've found the register whose value is abnormal, find out
          what variables in your program caused that abnormal value, e.g. by
          stepping through the machine code from the point where your code
          called the library function.

---------- Footnotes ----------

(1) Programs that create machine code in `malloc'ed storage and then jump
into it could have their EIP above EBP.  The Allegro library utilizes this
technique in some of its functions.

12.3 You need QEMM 7.53 or later
================================

**Q*: Whenever I call any DJGPP debugger to debug my program, it crashes
immediately.*

*A*:  Are you running under Quarterdeck's QDPMI?  Then you should upgrade to
QEMM 7.5 patch-level #3 or later.  That patch corrects a subtle problem in
QDPMI which was triggered by DJGPP debuggers.  If you cannot or wouldn't
upgrade, for money or love, turn OFF the DPMI services of QDPMI and use
`CWSDPMI' as your DPMI host.  To disable QEMM DPMI services either uninstall
QDPMI, or go to the QEMM directory and issue the following command:

      qdpmi off

12.4 GDB would not debug unless it sees COFF output
===================================================

**Q*: I try invoking GDB on my program, but it says: "not in executable
format: File format not recognized."  Huh?*

*A*:  Most probably, you've invoked GDB from DJGPP v2.0 on a `.exe' program.
That version of GDB needs to be called with the name of un-stubbed COFF
executable as its argument.  To get both a `.exe' and a COFF file, you should
make your link command line look this way:

      gcc -o foo foo.o

instead of

      gcc -o foo.exe foo.o

(the latter will only produce `foo.exe', while the former produces both
`foo', the COFF executable which gdb needs, and `foo.exe').

To produce a COFF file from a `.exe' program, use the `EXE2COFF' program
which comes with DJGPP, like this:

      exe2coff foo.exe

Debuggers which come with DJGPP v2.01 can debug COFF and .exe programs alike,
so upgrading to v2.01 should solve this problem.

12.5 How to debug a graphics program
====================================

**Q*: How can I debug a graphics program?  The debugger runs my program fine,
but when a breakpoint is hit with the screen in a graphics mode I can't read
the text printed by the debugger.*

*A*:  Redirect the debugger output to your printer, like this:

      gdb myprog > prn

This will only work if the program itself doesn't write to stdout (graphics
programs usually don't); otherwise the debugger output will get mixed up with
your program's output.

Beginning with version 1.1, RHIDE and `RHGDB' support debugging graphics
programs, so upgrade to latest version of RHIDE and use its built-in debugger
or the stand-alone `RHGDB' subset.  This support doesn't work for all video
modes, but the standard VGA modes and VESA modes are supported.

The FSDB debugger can switch between the application screen and the debugger
screen, so you might use it, at a price of working with a low-level debugger.
Press `Alt-<F5>' to switch between the two screens.  Stock FSDB as
distributed with DJGPP can only do this with text screens, but a modified
version of FSDB with graphics support
(ftp://ftp.delorie.com/pub/djgpp/contrib/gnudebug.zip) is available that knows
about many graphics modes.  The same distribution can also be found on the
Oulu repository
(ftp://x2ftp.oulu.fi/pub/msdos/programming/djgpp2/gnudebug.zip).

As yet another possibility, consider using the `MSHELL' program which will
redirect I/O from any program to the monochrome monitor at the BIOS level, so
you can use it even with GDB.  `MSHELL' was written by DJ Delorie
<dj@delorie.com> and is available from DJ's server
(ftp://ftp.delorie.com/pub/djgpp/ofc/mshell10.zip).  Be sure that you don't
have some other TSR installed that catches screen writes and bypasses the
BIOS functions, or else `MSHELL' won't help you.  For example, changing the
code page (with the DOS `CHCP' or `MODE' commands) might do this.

RHIDE also supports dual-monitor systems for debugging, it allows you to use
the monochrome monitor for interface with the debugger, while leaving the
color screen for your program's display, with no need to swap between them.

If you have any problems with dual-monitor support, in particular with RHIDE,
make sure your memory manager doesn't grab the `B000' segment for its own
purposes.  This region should be available for the mono adapter, or your
system might crash when you try using it.

Another way to redirect the output of a program to a monochrome monitor is by
using the MDA display driver from BinaryInfosys.  It is a true DOS device
driver, and so can be opened as a file--handy for sending debug info, for
example.  This driver is free and is available from BinaryInfosys' home page
(http://www.binaryinfosys.com/bis/files/mda.exe).

12.6 GDB finds only `.cc' source
================================

**Q*: When I try to debug my C++ programs, the debugger claims it can't find
the source file:*

      file.cc: No such file or directory.

*The source file *is* there, but it's called `file.cpp', not `file.cc.'  Why
does this happen?*

*A*:  It's a bug in GCC 2.7.2 and earlier.  It erroneously assumes that a C++
source always has a `.cc' extension.  If you are using GCC 2.7.2.1 or
earlier, you'd better call your C++ files `*.cc'.  If this is unacceptable,
you can work around this bug by invoking `cc1plus' and the assembler pass
manually.  The bug in GCC manifests itself in that `cc1plus' is called with
the option `-dumpbase file.cc.'  If you replace this with
`-dumpbase file.cpp' (or whatever your extension is), the debugger will
happily find your sources.

GCC 2.8.0 and later corrects this bug, so upgrading is also a solution.

12.7 Can GDB print class members?
=================================

**Q*: It seems that GDB doesn't recognize C++ class members by their
original, unmangled names.  Do I really need to figure out the mangled names
of all my class variables and methods to be able to debug them?*

*A*:  No, you don't.  `GDB' *does* allow you to use the original names, it's
just that it usually treats the `::' in their names as word delimiters.
Include the name of the method or a class static variable in single quotes,
and `GDB' will recognize them as a single word.  For example, if your class
`CMPForward' has a method named `go' which you need to put a breakpoint in,
use the following command:

       b 'CMPForward::go'

Other `GDB' features that might be useful in this context are the various
demangling options, like `set print demangle', `set demangle-style' etc.;
look them up in the GDB on-line docs.

However, there are some cases where you won't be able to get GDB to demangle
C++ function names no matter how hard you try.  This is due to a lack of
sufficient debugging information in the COFF files with SDB debug data.
There's simply not enough info there for GDB to detect the source language
and use C++-specific support.  If you need a description of the GNU style of
mangling C++ names (so you could demangle them yourself), look in the GDB or
Libg++ source distribution, in the libiberty directory, for a file named
`cplus-demangle.c'.  If you really need full C++ support in DJGPP, you will
have to use the stabs debugging support.  GCC 2.8.0 and later are distributed
with built-in stabs support, so upgrade if you need this.  Caveat emptor:
`FSDB', `EDEBUG32' and `SYMIFY' don't understand stabs, so you will have to
compile with `-gcoff' option to use these utilities (RHIDE distribution
includes a utility called `gsymify' that can be used instead of `SYMIFY' with
stabs debugging info).

Note that, as the debugger built into RHIDE uses GDB code, it will also
sometimes have such problems with debugging C++ programs.

12.8 GDB cannot list source that was #include'd
===============================================

**Q*: My source file #include's another source file, but I cannot set a
breakpoint in that included code, because GDB says there is no such line, or
no such source file...*

**Q*: I cannot debug code produced by Flex, or Bison, or F2C, because GDB
somehow messes up all the source file and line number info!*

**Q*: Why can't I step with a debugger into an inline function defined in a
header file?*

*A*:  This is a genuine limitation of the COFF format used by DJGPP.  It can
only handle a single source file for a given object file.  It does include
correct line numbers, but the name of the source file is wrong, so debugging
such files just doesn't work.  Using stabs debugging info (see the previous
section) doesn't have this limitation, so upgrade to GCC 2.8.0 or later if
you can.

For source files that include other source files, you can work around this
even with COFF debugging, by just inserting the included source with your
editor while you debug the program.  For code produced by other programs,
like `F2C' or `Bison', Duncan Murdoch <D.J.Murdoch@bristol.ac.uk> suggests a
work-around: to copy the original source file (`.y', `.f', etc.) over the
generated C file.  For example, here's how you should go about debugging a
Fortran program `myprog.f' using `GCC', `F2C' and `GDB':

  1. Run `f2c' with the `-g' option:

           f2c -g myprog.f

  2. Compile using `gcc' with the `-g' option:

           gcc -g myprog.c -o myprog.exe -lf2c -lm

  3. Copy the original Fortran source over the generated C:

           copy myprog.f myprog.c

  4. Debug with `gdb':

           gdb myprog.exe


12.9 GDB cannot display or set static uninitialized variables
=============================================================

**Q*: Why can't I set or display the values of some static variables in my
program?*

*A*:  This seems to be a limitation of the COFF debugging information
currently used by GDB and its derivatives (RHGDB and the debugger built into
RHIDE): they cannot display or set the value of an uninitialized static
variables (those who are in the `.bss' section of the program).  A
work-around is to initialize these variables, which causes the linker to put
them into the `.data' section.  Another solution is to use the stabs
debugging support; latest versions of GCC include this support, so upgrade.

12.10 Debuggers choke on some programs ...
==========================================

**Q*: I cannot debug Emacs (or any program that requests raw keyboard input):
when I press Ctrl-C, any debugger I tried reported SIGINT.  But I cannot
operate the debugged program without Ctrl-C (in Emacs, it's necessary to exit
the editor)!*

**Q*: I cannot debug any program which catches signals!!??*

**Q*: I compiled my program with `-pg' switch, and now I cannot debug it...*

**Q*: When my program hits a breakpoint in GDB, the debugger reports SIGSEGV,
but only under Windows...*

*A*: There are currently a few limitations in debugging programs which use
interrupts or exceptions.  Programs compiled for profiling may crash under a
debugger with SIGSEGV or a GPF, with no addresses that `symify' can identify;
programs using `alarm' or `setitimer' can't be debugged, either.  You can't
hook the keyboard interrupt in a debugged program, and you can't debug a
program which uses floating point on a machine without FP hardware (unless
you use `WMEMU' as your emulator, but even `WMEMU' doesn't solve all the
problems).  The reason for all these problems is that any exceptions or
signals that happen when your program runs under a debugger will be caught by
the debugger instead, and they won't get passed to the debuggee.  To debug
programs which hook hardware interrupts, you will have to chain the old
real-mode interrupt handler to your new handler, which requires to write
special debug version of the program.

At least some of these limitations will be fixed in future versions of DJGPP.
In case you need a `Ctrl-<C>' key-press to go to the debuggee instead of the
debugger, a work-around is available: use the `Alt-Numeric-3' (that is, press
the <Alt> key, the press and release the <3> key on the numeric keypad.  Some
programs (but not Emacs) will also treat the `Ctrl-<2>' key-press as
`Ctrl-<C>'.

Beginning with version 1.1, the debugger built into RHIDE supports debugging
programs that hook keyboard and/or timer hardware interrupts, so if you need
e.g. to debug programs built with the Allegro library or programs compiled
for profiling, you can use RHIDE.

Another known problem is that `GDB' GP Faults when the program hits a
breakpoint under Windows 3.X (Windows 9X doesn't have this problem).  This is
because the breakpoint instruction causes a software interrupt (as opposed to
an exception) under Windows 3.X, and the DJGPP debug support currently only
catches debug exceptions.  The only work-around is to use the *hardware*
breakpoints (which use the special debug registers of the i386 and higher
CPUs, and which do work with DJGPP on Windows 3), and never have more than 4
of them active at the same time.  `FSDB' will automatically use the hardware
breakpoints for the first 4 breakpoints (so it works on Windows 3.X unless
you set more than 4 breakpoints simultaneously), but with `GDB', you will
have to explicitly use the `hbreak' and `thbreak' (instead of `break' and
`tbreak') commands which set hardware breakpoints.  This works with DJGPP
ports of GDB 4.16 and later.  Note that `GDB' uses the ordinary breakpoints
to implement the `step', `next' and similar commands, so you can't use these
on Windows 3.X; use the temporary hardware breakpoints instead.  The above is
also true for watchpoints (which watch for variables to change value): you
need to use hardware watchpoints with GDB (the total number of breakpoints and
watchpoints cannot exceed 4).  Same considerations apply to the debugger
built into RHIDE under Windows 3.X.

13. Profiling DJGPP Programs
****************************

  This chapter explains how to optimize your program for speed using the
profiler, and discusses some problems you might have with it.

13.1 How to profile a DJGPP program
===================================

**Q*: How can I profile my program to see where it spends most of its run
time?*

*A*:  DJGPP includes a profiling facility.  To use it, compile and link with
`-pg' option, run your program as you usually would, then run a program
called `gprof':

      gprof myprog

(change `myprog' to whatever name your program is).  This will print an
execution profile.  You can now look at the profile and try to optimize the
functions which take a large proportion of the execution time.

`Gprof' is further documented in the Binutils docs as part of the GNU
Binutils distribution
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bnu281b.zip).

13.2 Programs compiled with -pg crash when run
==============================================

**Q*: I cannot profile my program: when I compile it with -pg, it crashes or
wedges my machine!*

**Q*: When I compile my program with -pg, it runs much slower.  Does the
profiling code have such a huge overhead?*

**Q*: I profiled my program, but the profile contains an entry `_mono_putc'
which I don't use, and which eats up about 70% of execution time!*

**Q*: When I run a profiled program on my dual (VGA+MDA) display system, the
mono screen shows loads of meaningless numbers.  Is there a way to stop this
behavior?*

*A*: DJGPP v2.01 has a bug in one of its library functions which is linked
into your program when it is compiled with the `-pg' option.  The bug is that
the profiled program tries to write to the secondary mono screen, which
caused the profiled programs to crash in many environments, in particular
when a memory manager remaps some of the high memory.  On systems which
actually have the additional mono display, the profiled programs won't crash,
but would run significantly slower and print debugging info on the mono
display.

A patch which corrects this bug was posted to the DJGPP News group; you can
find it by searching the DJGPP mail archives.  The patched library (see a
better library in Section 21.4) includes a fixed version of the offending
function, so using the patched libc will solve these crashes (as will
upgrading to v2.02, when that is available).  A work-around is to run the
program compiled with `-pg' on vanilla DOS configuration (no memory managers
such as EMM386 or QEMM, and no Windows).  However, when you use this
work-around, your program might run much slower, although the profile that
you get is not affected.

13.3 Gprof won't work unless it can find COFF executable
========================================================

**Q*: When I run `Gprof', it complains that it cannot find my program.  But
I've just run it!!*

**Q*: I run `Gprof' on my program, and it says: "bad format".*

*A*:  `Gprof' from DJGPP v2.0 needs the original COFF file the linker
produced.  If you delete it, or feed `Gprof' with the `.exe' file instead, it
will be most unhappy.  The way to produce the COFF output is explained in
section dealing with GDB in Section 12.4, above.  Alternatively, upgrade to
DJGPP v2.01, where all Binutils programs know about .exe executables.

13.4 Where is Gprof docs?
=========================

**Q*: What about all those `Gprof' options?  Where can I find their docs?*

**Q*: I can't figure out some of the info in the `Gprof' report ...*

*A*:  `Gprof' documentation, `gprof.inf', was accidentally left out of the
Binutils binary distribution, `bnu27b.zip' in DJGPP v2.01.  If you don't have
`gprof.inf' in your info subdirectory, you will have to look for it in the
latest Binutils source distribution
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bnu281s.zip).

13.5 Why is `__dpmi_int' so heavily used?
=========================================

**Q*: I've profiled my program and found that the routine which takes 60% of
the running time is some obscure library function called `__dpmi_int.'  Can't
you guys make your library right?*

*A*:  Does your program use I/O or other real-mode services (like BIOS)
extensively?  All those services are invoked through a DPMI service call
which is issued by `__dpmi_int.'  So what the profile really says is that the
running time of your program is governed by time-consuming operations such as
disk I/O.

13.6 `gprof' doesn't produce output
===================================

**Q*: Every time I run the profiler it says "gmon.out: no such file or
directory" and no profile is produced.  What is this `gmon.out' and why won't
`gprof' compute the profile?*

*A*:  `gmon.out' is the file with raw execution counts and timing info that
`gprof' needs to produce the profile.  The file is written by the profiled
program when it exits.  If the file isn't created, it might be because one of
the following reasons:

   * You didn't compile and/or link your program with the `-pg' switch.  Note
     that *both* compilation and link need to be done with `-pg', because the
     functions that actually write the results to `gmon.out' are only linked
     in when `gcc' sees `-pg' on the link command line.

   * You have called `ld.exe' directly to link your program and forgot to
     mention the files and switches necessary for the profiled program
     operation.  You should use `gcc' to link your program instead of calling
     the linker directly; a `-pg' switch to `gcc' is all that it takes to
     make sure that the linker will get all the necessary arguments(1).

   * Your program exited abnormally.  The function which generates `gmon.out'
     is registered with the `atexit' library function, and won't be called if
     the program was terminated in an abnormal way.  Make sure that your
     program exits with a call to `exit' library function or with a `return'
     statement in your `main' function.  For example, if your program dies
     with an exception or a signal, install a signal handler and make it call
     `exit.'

---------- Footnotes ----------

(1) If you absolutely need to call `ld.exe' directly, invoke `gcc' once with
a `-v' switch and you will see what are the arguments that you should pass to
the linker in your case.

14. Run-time Performance of DJGPP Programs
******************************************

  This chapter deals with issues pertinent to run-time performance of DJGPP
programs.

14.1 How efficient is DJGPP-generated code?
===========================================

**Q*: How does DJGPP compare with other DOS-based C compilers in terms of
efficiency of generated code?*

**Q*: Won't my program run *much* slower when compiled by DJGPP, due to all
those CPU cycles wasted in switches between protected and real mode?*

*A*:  The quality of code generated by GCC with optimization turned on (`-O2'
switch to the compiler) is generally at least as good as what you will get
from top commercial products, like Borland, Microsoft and Watcom.  Mode
switches indeed have a certain performance hit, but in most programs it is
negligibly small, because only DOS and BIOS services require such a switch,
and most programs spend most of their time doing other things.

14.2 Comparing newer versions with old ones
===========================================

**Q*: I switched to v2 and my programs now run slower than when compiled with
v1.x...*

**Q*: I timed a test program and it seems that GCC 2.8.1 produces slower
executables than GCC 2.7.2.1 was, which in turn was slower than DJGPP v1.x.
Why are we giving up so much speed as we get newer versions?*

**Q*: I installed Binutils 2.8.1, and my programs are now much slower than
when they are linked with Binutils 2.7!*

*A*: In general, newer versions of GCC generate tighter, faster code, than
older versions.  Comparison between different versions of GCC shows that they
all optimize reasonably well, but it takes a different combination of the
optimization-related options to achieve the greatest speed in each compiler
version.  The default optimization options can also change; for example,
`--force-mem' is switched on by `-O2' in 2.7.2.1; it wasn't before.  GCC
offers a plethora of optimization options which might make your code faster
or slower (see the GCC docs for a complete list); the best way to find the
correct combination for a given program is to profile and experiment.  Here
are some tips:

   * Compile your code using the GCC switches `-O2 -mpentium
     -fomit-frame-pointer -ffast-math'.  (For PGCC use `-O6' instead of
     `-O2'.)  Omit `-ffast-math' if you link with `-lm' and need the `errno'
     variable to be set or the `matherr' function to be called in case of
     errors.

   * Profile your code and check which functions are "hot spots".
     Disassemble them, or compile with `-S' (see getting assembly listing in
     Section 8.20), and examine the machine code.

   * If the disassembly shows there aren't too many memory accesses inside
     the inner loops, try adding `-fforce-addr' option.  This option helps a
     lot if a couple of pointers are used heavily within a single loop.  If
     there are a lot of memory references, try adding `-fno-force-mem', to
     prevent GCC from repeatedly copying variables from memory into registers.

   * Try adding `-funroll-loops' and `-funroll-all-loops' and profile the
     effect.

   * Try compiling with `-fno-strength-reduce'.  In some cases where GCC is
     in dire need of registers, this could be a substantial win, since
     strength reduction typically results in using additional registers to
     replace multiplication with addition.

   * Sometimes, `-fomit-frame-pointer' might make things worse, since it uses
     stack-relative addresses which have longer encoding and could therefore
     overflow the CPU cache.  So try with and without this switch.

   * If different time-critical functions exhibit different behavior under
     some of the optimization options, try compiling them with the best
     combination for each one of them.

I'm told that the PGCC version of GCC has bugs in its optimizer which show
when you use level 7 or higher.  Until that is solved in some future version,
you are advised to stick with -O6.

Programs which manipulate multi-dimensional arrays inside their innermost
loops can sometimes gain speed by switching from dynamically allocated arrays
to static ones.  This can speed up code because the size of a static array is
known to GCC at compile time, which allows it to avoid dedicating a CPU
register to computing offsets.  This register is then available for
general-purpose use.

Another problem that is related to C++ programs which manipulate arrays
happens when you fail to qualify the methods used for array manipulation as
`inline'.  Each method or function that wasn't declared `inline' will *not*
be inlined by GCC, and will incur an overhead of function call at run time.

However, inlining only helps with small functions/methods; large inlined
functions will overflow the CPU cache and typically slow down the code
instead of speeding it up.

A bug in the startup code distributed with DJGPP versions before v2.02 can
also be a reason for slow-down.  The problem is that the runtime stack of
DJGPP programs is not guaranteed to be aligned on a 4-byte boundary.  This
usually only shows up on Windows (since CWSDPMI aligns the stack on its own),
and even then only sometimes.  But it has been reported that switching to
Binutils 2.8.1 sometimes causes such slow-down, and switching to PGCC can
reveal his problem as well.  In some cases, restarting Windows would cause
programs run at normal speed again.  If you experience such problems too
much, either upgrade to v2.02 or ask for a patch that solves it.  (The patch
is in the stub loader, so you will need to recompile the `stubify' utility and
point the `STUB' environment variable to a program with a new stub.)

14.3 DJGPP programs on a Pentium
================================

**Q*: Does DJGPP support Pentium-specific optimizations?*

**Q*: I run the same program on a 486 and on a Pentium, and it's slower on a
Pentium!!*

*A*: DJGPP doesn't add to, or otherwise change, the compiler features offered
by GCC.  DJGPP is just a port of GCC to MSDOS, and thus supports the same
Pentium-specific optimizations that the latest GCC release does.

Lately, the FSF has split the GCC development into two branches: one is the
regular GCC, while the other is called EGCS(1), the "Experimental GNU
Compiler System".  The latter is usually less stable than the GCC releases,
but supports more advanced features, like the so-called "Haifa scheduler", a
new global subexpression elimination engine, and multi-language stuff.  PGCC
is a derivative of EGCS which supports additional optimizations specific to
the x86 architecture; its optimizations for Pentium CPUs, and even for an
i486, are better than those of GCC.  So if you need to squeeze the last bits
of performance from programs that target Pentium machines, use EGCS/PGCC to
compile them.  One drawback of EGCS/PGCC is that compilation is slower than
with GCC and needs much more memory, sometimes an order of magnitude more,
especially at higher optimization levels.  PGCC was ported by Andrew Crabtree
<andrewc@rosemail.rose.hp.com>, and can be downloaded from the PCG site
(http://www.goof.com/pcg/).

A program might sometimes run slower on a Pentium due to alignment problems
in DJGPP.  GCC makes assumptions about how GAS (the assembler) handles
alignment, but when GAS is built with the default DJGPP configuration, it
treats alignment in a way that's different from what GCC assumes.  The
outcome of this is that longs are word-aligned, doubles are dword-aligned,
etc.  Depending on the DJGPP version, link order, library differences, you
might get lucky (or unlucky) with a 50/50 chance to get an improper
alignment.  Different CPUs have different penalties for unaligned accesses,
which may explain differences in speed.  DJGPP v2.01 has a bug in the startup
code, whereby the runtime stack isn't aligned; this could also be a reason for
slow-down, especially in programs compiled by EGCS/PGCC.

You might consider adding some slack static variables to induce changes in
alignment; if any of the changes suddenly cause a significant change in the
runtime performance, then alignment might be the reason.

---------- Footnotes ----------

(1)  Pronounced like "eggs".

14.4 My program's I/O is so slow!
=================================

**Q*: I measured the time required to read a 2 MByte file in DJGPP and in
Borland C.  It took the DJGPP program 2.5 seconds to do it, while Borland did
it in just under 2.  This is *horribly* slow: its 25% slower than Borland!*

**Q*: I tried to improve DJGPP I/O throughput by defining a 64KB-large buffer
for buffered I/O with a call to `setvbuf', but that had no effect.  Why is
that?*

**Q*: It is obvious that disk-bound programs compiled with DJGPP will run
*awfully* slow, since FAT is such a lousy filesystem!*

*A*: First, I would like to point out that waiting another 0.5sec for reading
a 2 MByte file isn't that bad: it is indeed about 25% longer than you can do
under DOS, but it's only half a second...  Besides, most programs read and
write files which are only a few hundreds of kilobytes, and those will suffer
only a negligible slow-down.

Doing I/O from protected-mode programs requires that low-level library
functions move the data between the extended memory and low memory under the
1 MByte mark, where real-mode DOS can get at it.  That area in the low memory
is called the "transfer buffer"(1).  This data shuffling means that some I/O
speed degradation is inevitable in any protected-mode program which runs on
top of DOS (including, for example, Windows programs when Windows 3.X is set
to 386-Enhanced mode).  By default, DJGPP moves data in chunks of 16 KB, so
defining a buffer larger than that won't gain anything.  The size of the
transfer buffer is customizable up to a maximum of 64 KB(2), so if your
program really reads a lot of large files, you might be better off enlarging
it (with the `STUBEDIT' program).

Some people think that FAT is such a lousy filesystem, that programs which do
a lot of disk I/O *must* run terribly slow when compiled with DJGPP.  This is
a common misconception.  The speed of disk I/O is determined primarily by how
efficient is the code in the operating system kernel that handles the
filesystem, and the device drivers for the I/O-related devices like the hard
disk, not by the disk layout.  It is true that DOS and BIOS don't implement
I/O too efficiently (they use too many tight loops waiting for low-level I/O
to complete), but a large disk cache can help them tremendously.  In
addition, Windows 9X bypasses DOS and BIOS I/O code entirely, and uses much
more efficient protected-mode code instead.  Experience shows that DJGPP
programs on plain DOS systems with a large (8MB and up) disk cache installed
run about 30% slower than a Linux system on the same machine; and Windows 9X
will run the same programs at roughly the same speed as Linux.  If you get
much slower performance on DOS/Windows, chances are that your system is not
configured optimally.

Some programs which only copy data between two files might gain significantly
if you write your custom low-level I/O functions that avoid moving data to
extended memory (only to move them back to the transfer buffer).  However,
these cases are rare.

---------- Footnotes ----------

(1) Here's a more detailed explanation.  DOS cannot access memory above 1MB
mark, where your DJGPP program lives, since real-mode addresses are 20-bit
wide, which covers only the first megabyte.  So, each time a DJGPP program
needs to call a DOS function (or any other real-mode service, like some BIOS
interrupt) and needs to pass data to or from that service, we must use some
buffer in conventional memory to communicate.  The transfer buffer is a block
of conventional memory that the DJGPP startup code allocates for this
purpose.  When a real-mode service is called, the data that needs to be
submitted to it is copied to the transfer buffer, and the address of the
transfer buffer is passed to the real-mode service.  If the service returns
some data (e.g., if you want to read a portion of a file), data is copied
from the transfer buffer when the service returns.

The transfer buffer primarily exists for library functions, but it can also
be used by an application, if it needs to invoke real-mode services.

(2) Actually, the maximum possible value is FEF0h, or 65254 in decimal,
because the transfer buffer is created by the startup code by resizing the
PSP memory block.  Since the resized block needs to leave 256 bytes for the
PSP, and needs to be aligned on a 16-byte boundary, you cannot have the
entire 65535 bytes for the transfer buffer.  If you invoke `stubedit' with a
`bufsize=64k' parameter, what you actually get is a 2KB buffer, since the
combined size of the PSP and the transfer buffer will wrap around in a 16-bit
variable when the startup code computes it.  The version of `stubedit' which
will come with DJGPP v2.02 will explicitly warn you about this case and will
reset any value that is too large to the maximum allowed size of FE00h (65024
decimal) bytes--this is less than FEF0h because the latter is not aligned on
the 512-byte DOS sector size, which could slow down disk I/O.

14.5 My ported program runs much slower!
========================================

**Q*: How come my program, which I ported from Borland/MS C and which doesn't
use much I/O, still runs much slower under DJGPP? *

*A*:  Explore the following possible causes for this:

  a. Your program extensively calls services other than I/O which require mode
     switch (like BIOS Int 10h, mouse services, etc.).

     You can tell how much your program switches to real mode by profiling
     your program.  In the profile, look at the proportion of time your
     program spends in low-level library functions called `__dpmi_int' (which
     calls real-mode DOS/BIOS services) and `__dj_movedata' (which moves data
     between the transfer buffer and your program).  If this proportion is
     large, try rewriting your program to minimize use of those functions
     which require a mode switch, even at a price of more computation (a mode
     switch usually eats up hundreds of CPU cycles).

  b. Your program uses a lot of floating-point math, and you run it on a
     machine without an FPU.  A telltale sign of this is that a function
     called `__djgpp_exception_processor' is high on the execution profile
     printed by `Gprof'.  Due to the way FP emulation is implemented in
     DJGPP(1), it might be significantly slower than the way real-mode DOS
     compilers handle it.  The solution is either to rewrite your code so
     that it doesn't use floating-point code in its inner loops, or buy an
     FPU.

  c. Your program uses library functions/classes which are implemented less
     efficiently by DJGPP libc and the GNU C++ libraries.  Or you might be a
     heavy user of functions which other compilers convert to inline code,
     while GCC doesn't inline most library functions.  If this is the case,
     you will see those functions as "hot spots" on the program histogram
     produced by the `Gprof' profiler.  If you find this to be the problem,
     write your own, optimized versions of those functions.  It's best to
     write them as inline assembly functions, for maximum performance.  If
     you find library functions which are inefficient, please inform the
     DJGPP news group by posting to comp.os.msdos.djgpp news group, so this
     could be fixed by people who maintain the library.

  d. If your program spends most of its time in a certain innermost loop, you
     should try enabling some of the optimization options which aren't
     enabled by default.  Some of these are described in this FAQ, see
     speed-related optimization options in Section 14.2.

  e. The size of the code/data in the innermost loop might be close to the
     size of the CPU cache (either L1 on-chip cache, or L2 cache on the
     motherboard).  Compiling your program with a different compiler or a
     different combination of optimization options can cause the code to
     overflow the cache, which will dramatically affect the performance
     (usually, by a factor of 2).  Running your program with the cache
     disabled will be instrumental to see whether this is your problem.  If
     it is, try to rearrange your data/code, or use a different combination
     of optimization options.

  f. If the slow program was compiled for profiling (with he `-pg' switch),
     the slow-down might be due to a bug in he DJGPP library.  See slow-down
     in profiled programs in Section 13.2, for more about this.

  g. Sometimes, some device driver that uses extended memory takes up a
     significant portion of it, and leaves less for DJGPP programs, which
     then begin to page and slow down.  For example, Novell Netware's VLM
     redirector and client software can use up to 0.5 MB of extended memory,
     even if you don't log into the network.  A solution is not to load such
     resident software, or to buy more memory.

---------- Footnotes ----------

(1) Without a real x87 FPU, an exception is generated by the CPU each time a
floating-point instruction is seen in the code.
`__djgpp_exception_processor' is called for each such exception and services
it by calling the emulator, `emu387.dxe', or functions from the emulator
library `libemu.a' (if the program was linked with `-lemu'), to emulate the
instruction.  Since exception processing incurs a lot of overhead, this
emulation is slow.

15. Run-Time Memory Issues
**************************

  This chapter answers questions which are related to DJGPP run-time memory
allocation.

15.1 How much virtual memory do you have?
=========================================

**Q*: How much virtual memory can I use in DJGPP programs?*

*A*:  That depends on the DPMI host you are using.  CWSDPMI (the free DPMI
host which comes with DJGPP) will let you use all available conventional and
extended memory (up to 256MB) and up to 256MB of disk space, for a grand
total of 512MB of virtual memory for your application.  Try a
`malloc(50*1024*1024)' some day.

With other DPMI hosts, your mileage may vary.  Quarterdeck's QDPMI, for
instance, has a bug in some of its versions which effectively disables
virtual memory under DJGPP (described in QDPMI VM bug in Section 15.3,
below), so you only have whatever free physical RAM is left.  Under Windows
3.X, the amount of virtual memory you get depends on various virtual memory
settings in the Control Panel and on the `.pif' file settings for the program
you run (see Windows allocation subtleties in Section 15.5, below).  Under
Windows 9X, the memory settings of the DOS Box Property Sheets define how
much virtual memory a DJGPP program will get (see Windows 9X allocation
details in Section 15.6, below).  OS/2  reportedly can be configured to
support up to 512MB of DPMI memory.

15.2 It seems `malloc'/`free' don't affect virtual memory...
============================================================

**Q*: I did `malloc(50*1024*1024)', but didn't see any paging happen, and I
only have 8 MBytes of RAM on my machine.  Is this virtual memory thing for
real?*

**Q*: I `malloc''ed a large chunk of memory, but when I check values returned
by `_go32_remaining_physical_memory' or `__dpmi_get_memory_information', I
don't see any change!*

**Q*: When I `free' allocated RAM, `_go32_remaining_physical_memory' reports
there was no change in the available RAM...*

**Q*: I'm looking for a way to tell how much memory is available, something
like `coreleft' in Borland C?*

*A*:  CWSDPMI (and, possibly, other DPMI hosts) only pages in memory when it
is actually accessed.  If you only `malloc' it, but don't actually access it,
it won't grab those pages.  Try `calloc' and see the *big* difference.

When you call `free', DJGPP library doesn't return memory to the system, it
just adds it to its internal pool of free pages.  So, from the system point
of view, these pages are not "free".

In addition, several widely-used DPMI servers, such as those built into
Windows, have their own quirks related to memory allocation.  For example,
some of them won't let you allocate more than half the available memory in a
single chunk.  As another example, under OS/2
`_go32_remaining_physical_memory' reports a constant very big value that
doesn't change in the course of the program.

Because of these peculiarities, there's no convenient and easy way to return
the amount of free memory available at any given moment.  Some programs only
care about available physical RAM (they don't want to page to disk, since
that causes a considerable slow-down); for these, I recommend to call the
`_go32_remaining_physical_memory' library function at program startup, and
then track memory usage with `sbrk(0);'.  Alternatively, disabling virtual
memory altogether (by using CWSDPR0 or by loading CWSDPMI with `-s-'
parameter), and checking values returned by `malloc' against `NULL', might be
all you need to know when you are about to run out of free physical memory.
Programs that need to know when they are about to run out of *virtual* memory
should call `_go32_remaining_virtual_memory' instead.

15.3 Failure to get more memory than is physically installed
============================================================

**Q*: When I try to access more memory than the free physical RAM, `malloc'
returns a `NULL' pointer, or I get some cryptic error message, like "Memory
Paging Violation" or "Unrecoverable Exception: 000Eh".*

*A*: This is typical of Quarterdeck's DPMI host called QDPMI which comes with
QEMM386 version 7.53 and earlier.  Some versions of QDPMI (those which come
with QEMM v6.x) fail to resize memory blocks when the new size is more than
the available physical RAM, even though virtual memory services are enabled;
other versions (those which come with QEMM v7.x) just don't let you allocate
more memory than is physically available.  If you must use more RAM than is
physically available, disable or uninstall QDPMI, as described in virtual
memory with QEMM in Section 12.3, and use CWSDPMI instead.

This bug was corrected in QDPMI version 1.10 or later, distributed with QEMM
beginning with version 8.0, so upgrading to the latest version of QEMM might
also be a solution.  With QEMM 6.x, make sure your programs don't override
the default type of `sbrk' behavior by setting `_crt0_startup_flags' to
`_CRT0_FLAG_UNIX_SBRK' (QEMM 8.0 and later can allocate virtual memory with
both types of `sbrk' algorithm).

If you use another DPMI host, make sure that virtual memory is enabled.
E.g., for 386Max, include the `swapfile=' parameter to establish a virtual
memory swap file; you can make it permanent (this will speed up DJGPP
start-up) with the `/p' option.

15.4 Memory allocation fails before all memory is used
======================================================

**Q*: OK, I've changed my program to never allocate more memory than is
physically available, to work around that QDPMI VM bug, described in previous
section in Section 15.3, but my program still gets a `NULL' pointer from
`malloc/calloc'!*

**Q*: Why is my program dying with SIGSEGV under CWSDPMI when allocating a
chunk of memory?*

*A*:  Another peculiarity of QDPMI which came with QEMM before version 8.0:
it will never let you allocate a chunk which is larger than half of what's
available.  Windows 3.X behaves in the same way, and several people reported
the same to be true under Windows 9X.

With some DPMI providers, this behavior might be triggered by a small
overhead of each `malloc' call: you might ask for half of available memory,
but the DJGPP implementation of `malloc' adds the overhead and then rounds
the amount of memory to the next power of 2 before calling `sbrk'; thus
`malloc(8MB)' will actually request 16MBytes from the DPMI host.  When in
doubt, call `sbrk' directly, especially if you don't plan to free that memory
during execution.

If your program asks for memory in lots of small allocations, then it might
crash when you use CWSDPMI as your DPMI host.  This is because CWSDPMI runs
out of its tables, allocated in the heap, where it tracks memory allocations.
Beginning with release 2, CWSDPMI defines a 6KB-large default heap that is
configurable by CWSPARAM program to be anywhere between 3K and 40K bytes,
without recompiling CWSDPMI.  The default heap size is enough for about
21MBytes in small chunks.  You should upgrade to the latest CWSDPMI if you
experience such problems, and bump up its heap size as needed.

15.5 Memory allocation fails under Windows
==========================================

**Q*: I'm running under Windows 3.X DOS box, but DJGPP complains about there
not being enough DPMI memory, although virtual memory is enabled.*

*A*:  You must make sure the size of your Windows swap file can be at least 2
times the largest virtual memory size you need.  Check if you have enough
free disk space; if you do, run a defragger (Windows needs the swap file to
be contiguous).  This size is normally limited by the "virtual = 4 times free
physical" rule, but you can change that by inserting the line

      PageOverCommit=n

in the `[386Enh]' section of your `SYSTEM.INI' file.  The parameter `n' is 4
by default, but can be set to be as large as 20.

15.6 Memory allocation peculiarities under Windows 9X
=====================================================

**Q*: I seem to be unable to get more than 16 MBytes of virtual memory under
Windows 9X, even though I have 32 MBytes of RAM installed on my machine, and
a lot of disk space...*

*A*:  You must set the maximum amount of DPMI memory to 65535K in the DOS
applications' Property Sheets.  Click on the `Properties' button of the DOS
box toolbar, then click on the `Memory' tab, and type the number `65535' in
the box under `DOS Protected Mode Memory'.  If you leave that setting at the
default "Auto", your programs are at Windows' mercy, and in many cases will
get only 16 MBytes.  You must actually type 65535 inside the dialog box, as
checking out the values from the list Windows offers will never get you past
16384 (i.e., 16MB).

If you have more than 64MB of physical memory installed, you can specify the
amount of memory on the `EMM386' command line in your `CONFIG.SYS', like this:

      DEVICE=C:\WINDOWS\EMM386.EXE NOEMS L=131072

I'm told that this line (here for 128MB of installed memory) together with an
"Auto" setting of the DPMI memory for the DOS box allows DJGPP programs to
use up to 117MB of memory when running from the DOS box under Windows 9X.

Note that you cannot allocate more than half the available memory in one
chunk under Windows 9X, exactly as the things are under Windows3.X, and you
cannot have more than 64 MBytes of virtual memory available to DJGPP programs
running on Windows, unless you have more than 64MB physical memory installed.

15.7 Memory allocation fails under EMM386 or HIMEM
==================================================

**Q*: My machine has 48 MBytes of RAM, but when I run DJGPP programs, they
start paging after 32 MBytes have been used...*

**Q*: I have 5 MBytes of free RAM on my machine, but DJGPP programs start
paging after only 256KBytes of memory were used??*

*A*:  This might be caused by some old versions of the memory manager
installed in your machine (like HIMEM or EMM386 from an old version of DOS),
which were limited to 32 MBytes of expanded memory.  Try running without them
(CWSDPMI can use raw extended memory), or upgrade to a newer version of DOS.

If your programs start paging after only 256KBytes of memory were used, most
probably you are using EMM386 and CWSDPMI, and your `CONFIG.SYS' specifies no
amount of memory when it installs EMM386.  Some versions of EMM386 default to
256K in this case; you should tell EMM386 explicitly how much memory it
should take over.  You can use the `go32-v2' program to see what amount of
extended memory your DJGPP programs will get.

15.8 How much memory do parent DJGPP programs leave for their child?
====================================================================

**Q*: How much memory is available when I call the `system' library function?*

*A*:  In the conventional (below 640K mark) memory, you are left with
everything which was free before your program started, except what the DPMI
host uses.  The amount of conventional memory required by the DPMI host
depends heavily on the host you use.  For the first DJGPP program, QDPMI uses
about 97K, CWSDPMI uses about 70K, Windows 3.X only 18 KBytes.  Each
subsidiary call to `system' (like in recursive invocation of `Make') eats up
about 18K (16K for the transfer buffer and 2K for the PSP and environment)
for most DPMI servers; a notable exception is QDPMI which needs 97K bytes of
low memory for the subsequent calls too.  If you change the size of the
transfer buffer (with `STUBEDIT'), the amount of free conventional RAM left
when shelling out of it will change accordingly.

Extended memory management is left to the DPMI server; DJGPP does nothing
special about XMS when `system' is called.  This means that all the extended
memory used by the parent program is *not* freed when the child program
starts; if the child requests more memory than is physically free, the DPMI
server is expected to page some of the parent out to honor the request.
(This is unlike DJGPP v1.x, where the `go32' extender would completely page
out the parent before starting the child.)  The advantage of this is that
spawning a child or shelling out is much faster in v2 than it used to be with
v1.x, except on machines with low amounts of installed RAM.  A disadvantage
is that if you spawn a real-mode program that uses XMS, the extended memory
used up by your DJGPP program will be unavailable to it, unless you use a
memory manager (as opposed to when CWSDPMI uses raw XMS or HIMEM).  The only
way around this problem is to buy more RAM, or to install a real memory
manager.

Note that if you use a memory manager such as EMM386 or QEMM386 with the
NOEMS and NOVCPI parameters, CWSDPMI will use the XMS (as opposed to VCPI)
services to allocate extended memory, and will allocate all of the available
XMS memory for itself.  So if, while your DJGPP program runs, some resident
software such as device driver or TSR will try to allocate XMS, the
allocation will fail.

15.9 How much stack can I have in DJGPP programs?
=================================================

**Q*: My program bombs when I use very large automatic arrays.*

**Q*: How much stack space do I have in my program?*

**Q*: My program seems to overflow the stack, but only when I run it under a
debugger...*

**Q*: My program crashes with SIGSEGV, but the traceback makes no sense: it
points to something called ___djgpp_exception_table...  When I try to debug
this, the traceback mysteriously changes to some innocent library function,
like getc().  The same program works flawlessly when compiled with DJGPP v1.x
What is going on??*

*A*: DJGPP v2 programs get fixed-size stack which is allocated by the startup
code and then stays fixed for the entire lifetime of the program; this is a
bug/feature of the DPMI 0.9 specification.  By default, you have a 256KB-long
stack, but some programs which use large automatic arrays, or are deeply
recursive, might need more.  If the default stack size is not enough, you can
change it with the `STUBEDIT' program (change the parameter "Minimum amount
of stack space"), or by setting the global variable `_stklen' in your
program.  Example:

      unsigned _stklen = 1048576;  /* need a 1MB stack */

The DJGPP startup code checks both the value in the stub info and the value
of `_stklen', and uses the larger of these two.  Therefore, programs that are
known to require large stack size should set `_stklen' to make sure they will
always work, even if somebody stub-edits them to a lower value.  This
technique is also safer when you need to debug your program with `gdb' (see
below).  However, you might need to use `STUBEDIT' with programs for which
you don't have the sources.

Programs which need an unusually large stack might crash with bogus stack
traces, because part of the heap gets overwritten by the overflowing stack.
To see if that is the cause of such crashes, run `STUBEDIT' on your program
and crank up the stack size to a large value (like 4MBytes).  If that makes
the problem go away, tune the stack limit to the minimum value your program
can live with, then set `_stklen' to an appropriate value as explained above
and recompile the program.  (Some DPMI hosts will actually allocate the
entire stack, even if not all of it is used, so leaving it at unnecessarily
large value will hurt the program on low-memory machines.)

Some users have reported that they needed to enlarge the stack size of the
C++ compiler, `cc1plus.exe', to prevent it from crashing when compiling some
exceedingly large and complex C++ programs.  Another program that was
reported to need a stack larger than the default is `bccbgi.exe' from the
`BCC2GRX' package.

After you've used `STUBEDIT' to change the stack size, run it again to make
sure it displays as default the value you thought you entered.  This is
because `STUBEDIT' will sometimes silently set the stack size to 0 (and then
you will get the default 256K stack) if it doesn't like the value you type
(e.g. if it has a wrong syntax).

When you run a program under a debugger, the stack size field in the stub
info is ignored, so the only way to change the default stack size is to set
`_stklen'.

Under Windows 3.X, be sure you've allocated a sufficiently large swap file
(let's say, 40MBytes) from the Windows' Control Panel, and make sure the
`.PIF' file for your program doesn't have too low limit on EMS/XMS usage
(better make them both -1).  What's that?  You don't have a `.PIF' file for
this program?  Then Windows uses the default file `DOSPRMPT.PIF', which
almost surely defines very low limits on these two, and your program might
have problems getting the memory it needs for its stack.

DJGPP v2.0 has a subtle bug in its startup code that is seen very rarely, and
that manifests itself by a program crashing with Page Fault or SIGSEGV.  If
you are using v2.0 and enlarging the stack and the CWSDPMI heap size didn't
help, try adding some (e.g., 4KB) static data to your program and see if that
helps.  But the best way to overcome this is to upgrade to DJGPP v2.01 or
later.

16. Command-line Arguments Handling in DJGPP
********************************************

  DJGPP handles command-line arguments differently from most DOS-based
compilers, to make it closer to Unix platforms (so that porting of Unix
programs will be easier).  This chapter answers some questions about this
aspect of DJGPP.

16.1 Filename wildcards expansion under DJGPP
=============================================

**Q*: Can I do filename globbing with DJGPP?*

**Q*: I call my program with an argument `x*y' and it complains about
something called `xyzzy'??...*

**Q*: I cannot find a way to use the `/?' switch with my programs!*

*A*:  The filename globbing in DJGPP is done by the start-up code, before
your `main' function is called.  Unlike other DOS-based compilers, where you
must link your program with a special object module if you want the program
to get expanded filenames, in DJGPP this is considered normal behavior and
performed by default on behalf of every DJGPP program.  The `x*y' above was
expanded to a file called `xyzzy' which was probably present in the current
working directory; and `/?' is by default expanded to the list of one-letter
files/directories you happen to have in the root directory of the current
drive.  (If you don't want the default expansion, see how to disable globbing
in Section 16.2.)

In DJGPP, filename globbing works like in Unix, which is more general than
the usual DOS wildcard expansion.  It understands the following constructs
with special meta-characters:

`?'
     any single character.

`*'
     zero or more arbitrary characters, including a dot `.'

`[aA_]'
     any one of characters `a', `A', or `_'.

`[a-d]'
     any one of characters `a', `b', `c', or `d'.

`[!a-z]'
     anything *but* a lowercase letter.

`...'
     all the subdirectories, recursively (VMS aficionados, rejoice!).

`.../*'
     all the files in all subdirectories, recursively.

Unlike DOS, the `*' and `?' meta-characters can appear *anywhere* in the
filename pattern, like in `[a-z]*[0-9].*pp.'  You can also use `*' instead of
directories, like in `*/*/*.c', but *not* on drive letters (e.g., `[a-c]:/'
won't work).

Note that `*.*' only picks up files that actually have an extension.  This is
contrary to the usual DOS practice where it means *all* the files, with or
without extension.

An argument which cannot be expanded (no filenames matching that particular
pattern) will be passed to the program verbatim.  This is different from what
you might see under Unix, where some shells (like `csh') would say something
like "No match" and won't call your program at all.  DJGPP's behavior in this
case is like shells of the Bourne legacy (`sh', `ksh', and `bash').

If the wildcards include upper-case or mixed upper- and lower-case letters,
the letter-case of the files is not ignored on Windows 9X when expanding the
wildcards.  For example, `[A-D]*' will *not* match a file called `aFileName'.
Upper-case letters in wildcards also disable automatic down-casing of short
8+3 file names returned by the code that expand wildcards (even on plain
DOS).  If the wildcards include only lower-case letters, the letter-case is
ignored during expansion, and short 8+3 file names are automatically
down-cased, unless the environment variable `FNCASE' is set to `y'.  The
effect of setting `FNCASE' is fully described in the `DJGPP C Library
reference', under the `_preserve_fncase' function; type `info libc alpha
_preserve_fncase' from the DOS prompt.

16.2 How to disable filename wildcards expansion
================================================

**Q*: OK, but I don't want my program to glob its arguments (they aren't
files at all, but they include characters like `*' and `?').  What should I
do?*

*A*:  You have these alternatives:

   * Surround your arguments with single or double quotes (this is what you
     would do under a Unix shell).

   * Disable globbing for your program by linking it with your custom version
     of the function with the special name `__crt0_glob_function' and make it
     always return a `NULL' pointer.  See the documentation of this function
     in the library reference, for more details.  Here's an example:

           char **__crt0_glob_function (char *arg)
           {
             return 0;
           }

16.3 How to pass command-line arguments with quotes or `@'
==========================================================

**Q*: I have a file with a single quote in its name, but the quote seems to
be stripped away when I pass it to my program ...*

**Q*: How do I pass a command-line argument which contains double quotes? *

**Q*: How do I pass an argument which begins with the `@' character?*

*A*: These special characters on the command-line arguments are handled by
the filename expansion ("globbing") code before they are passed to the `main'
function (see description of filename expansion in Section 16.1), and the
quote characters serve to protect the arguments from expansion.  You should
escape-protect the quote characters with a backslash in order for them to be
treated as literal characters.  For example, if you have a file called
`myfile.c'v', type it as `myfile.c\'v' when you call your program.  If you
have single quotes in your program arguments *and* you don't want those
arguments to be expanded, then surround them by double quotes, like this:
`"*.c'v".'  The program will get the string `*.c'v' with the double quotes
stripped away.

Note that backslashes are only special if they are in front of a quote,
whitespace, or backslash (they also serve as DOS directory separators,
remember?).  This is also different from what you get under a Unix shell.

The `@' character serves to signal a "response file" (see the description of
response file method in Section 16.4), so it's also special.  To pass an
argument whose first character is `@', surround that argument with single or
double quotes, otherwise it will be taken as a name of a response file which
holds the actual command line.

Note that you can quote parts of the wildcard to protect only those parts
from expansion; the unquoted parts will still be expanded.  This allows to
use wildcards with embedded whitespace and expand file names with special
characters which need to be quoted, like in `c:/Prog*' 'F*' (which should
expand into `c:/Program Files') and `*.c"'"v' (which should expand into all
files with the `*.c'v' extension).

16.4 How to pass command lines longer than 126 characters
=========================================================

**Q*: Can I invoke my program with a command line longer than the infamous
DOS 126-character limit?*

**Q*: I have a Makefile of Unix origin which contains some *very* long
command lines.  Will it work with DJGPP?*

*A*:  Yes and yes.  DJGPP supports several methods of passing command-line
arguments which allow it to work around the DOS 126-character limit.  These
are:

   * The `!proxy' method.  If you invoke the program from within another
     DJGPP program (like Make or Gcc compilation driver), it gets the address
     of the memory block where the actual command line is stored.  The
     start-up code will detect this and use that info to retrieve the
     command-line arguments.

     This method is suitable only for invoking DJGPP programs from other DJGPP
     programs.  You don't have to do anything special to use this method, it
     is all done automagically for you by the library functions like
     `system', `spawnXX' and `execXX' on the parent program side, and by the
     start-up code on the child side(1).

   * The environment method.  This is the same as the `!proxy' method above,
     but the information about the long command line is stored in an
     environment variable called " !proxy" (with the leading blank and in
     lower-case).  The reason for two similar, but different methods is that
     command-line arguments passed by `system' library functions should be
     globbed by the child, while the arguments passed by `spawnXX' and
     `execXX' family of functions should not; thus the former uses the
     environment method while the latter use the `!proxy' method.

   * The response file method.  Any argument which starts with a `@'
     character (like in `myprog @file') will cause the named `file' to be
     read and its contents used as command-line arguments, like in many
     DOS-based compilers and linkers.  If you invoke your DJGPP program from
     the DOS command line, this would be the only method available for you to
     pass long command lines (like when calling `Gawk' or SED without `-f'
     option).

     Note that this method makes `@' special when it is the first (or the
     only) character of a command-line argument, which should be
     escape-protected if you want to use it verbatim (see how to pass the @
     character in Section 16.3).

Of course, if the start-up code doesn't see any of the above methods, it will
use the command line by default.

Since the long command lines are a very important feature, DJGPP's version of
the `system' library function avoids calling the DOS command processor,
`COMMAND.COM', unless it needs to run a batch file or an internal command of
`COMMAND.COM'.  Other features of the command processor, like redirection and
pipes, are emulated internally by `system'.  See the library reference for
`system', for more details about its extended functionality.

---------- Footnotes ----------

(1) In case you wonder, the name `!proxy' comes from the string which
identifies the use of this method: instead of getting the actual command
line, the program gets `!proxy' followed by the address of the actual command
line.

16.5 What is the maximum length of command line under DJGPP
===========================================================

**Q*: What is the longest command line I can pass to gcc when it is invoked
by `Make'?*

*A*:  The arguments are passed to DOS Exec call (Int 21h function 4Bh) via
the transfer buffer which is 16KB-long.  Apart of the command line, it is
also used to pass other info, such as the `!proxy' parameters and the copy of
the environment for the child program (let's say, less than 2000 bytes in
most cases, but your mileage may vary).  This leaves at least 13K bytes for
arguments (including a separating blank between any two arguments).  So
unless your arguments span more than 160 screen lines, you shouldn't worry.
However, if your environment is *very* large (some people need as much as 6KB
to accommodate for all the variables used by the various packages installed
on their machine), be sure to stub-edit the programs that spawn other
programs to a larger transfer buffer, or else they could fail.

The above limit depends on the size of the transfer buffer, so check the size
of the value recorded in the stub header of the *parent program* before you
pass extremely long command lines to its children.  GCC is the first program
you should worry about, because the linker (`ld.exe') usually gets long
command lines from GCC (they include the list of all the object files and
libraries to be linked).

16.6 Why Make passes only 126 characters to programs?
=====================================================

**Q*: I use Make to compile with GCC, but GCC gets only the first 126
characters of its command line.  Didn't you just explain in so many words
that invoking a DJGPP program (GCC) from another DJGPP program (Make) can
safely pass up to 13K characters of command-line arguments using the `!proxy'
method?*

**Q*: I use RHIDE, but it only passes the first 126 characters of my long
command lines to the compiler!*

*A*:  If you use Make 3.73, check your Makefile for `SHELL = command.com'
statements, or for commands which include pipe or redirection characters like
`>', `|', etc.  If Make sees any such statements, it will invoke
`COMMAND.COM' to run GCC, and `COMMAND.COM' can't pass more than 126
characters to GCC.  To work around, comment-out the `SHELL=' line, and change
your commands to work without redirection/pipe characters.  One easy way to
get rid of redirection characters without losing their effect is to use the
`redir' program which comes with DJGPP.  For example, the following command:

       frobnicate foo.bar > myfile.tmp

can be re-written instead like this:

       redir -o myfile.tmp frobnicate foo.bar

The ports of Make 3.75 and later doesn't call `COMMAND.COM' in the above
cases, but rather emulates pipes and redirection internally, so upgrading to
the latest version of Make will solve such problems.  If you think about
using Make 3.75 with DJGPP v2.0, don't: invoking v2.0 programs from v2.01
programs will cause subtle and hard-to-debug problems due to
incompatibilities between these two versions regarding the methods of
invoking child programs (in particular, v2.0 doesn't support the environment
method of passing long command lines described above).

Problems with passing long commands from RHIDE are usually caused by invoking
old programs compiled with DJGPP v2.0.  Upgrade to the latest binaries.

17. Converting DOS Programs/Libraries to DJGPP
**********************************************

  If you have a program or a library developed under some other DOS-based
compiler, which you want to port to DJGPP, read this chapter.

17.1 GCC/Gas won't accept valid assembly code ...
=================================================

**Q*: I have some code written in assembly which compiles under MASM and
TASM, but GCC gives me a long list of error messages.*

*A*: The GNU Assembler (`as.exe'), or `Gas', called by GCC accepts the "AT&T
syntax", which is different from the "Intel syntax".  Notable differences
between the two syntaxes are:

   * AT&T immediate operands are preceded by `$'; Intel immediate operands
     are undelimited (Intel `push 4' is AT&T `pushl $4').

   * AT&T register operands are preceded by `%'; Intel register operands are
     undelimited.  AT&T absolute (as opposed to PC-relative) `jump'/`call'
     operands are prefixed by `*'; they are undelimited in Intel syntax.

   * AT&T and Intel syntax use the opposite order for source and destination
     operands.  Intel `add eax, 4' is `addl $4, %eax' in AT&T syntax.

     The `source, dest' convention is maintained for compatibility with
     previous Unix assemblers, so that GCC won't care about the assembler with
     which it is configured, as some of GCC installations (on systems other
     than MS-DOS) don't use GNU Binutils.

   * In AT&T syntax, the size of memory operands is determined from the last
     character of the opcode name.  Opcode suffixes of `b', `w', and `l'
     specify byte (8-bit), word (16-bit), and long (32-bit) memory
     references.  Intel syntax accomplishes this by prefixing memory operands
     (*not* the opcodes themselves) with ``byte ptr'', ``word ptr'', and
     ``dword ptr'.'  Thus, Intel `mov al, byte ptr FOO' is `movb FOO, %al' in
     AT&T syntax.

   * Immediate form long jumps and calls are `lcall/ljmp $SECTION, $OFFSET'
     in AT&T syntax; the Intel syntax is `call/jmp far SECTION:OFFSET.'
     Also, the far return instruction is `lret $STACK-ADJUST' in AT&T syntax;
     Intel syntax is `ret far STACK-ADJUST.'

   * The AT&T assembler does not provide support for multiple-section (a.k.a.
     multi-segment) programs.  Unix style systems expect all programs to be
     single-section.

   * An Intel syntax indirect memory reference of the form

           SECTION:[BASE + INDEX*SCALE + DISP]

     is translated into the AT&T syntax

           SECTION:DISP(BASE, INDEX, SCALE)

Examples:

         *Intel:*  [ebp - 4]         *AT&T:*  -4(%ebp)
         *Intel:*  [foo + eax*4]     *AT&T:*  foo(,%eax,4)
         *Intel:*  [foo]             *AT&T:*  foo(,1)
         *Intel:*  gs:foo            *AT&T:*  %gs:foo

For a complete description of the differences, see i386-dependent features in
"GNU assembler documentation", or point your Web browser to
http://www.delorie.com/gnu/docs/binutils-2.7/as_164.html#SEC192.  If you don't
read this FAQ with an Info browser, download GNU Binutils
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bnu281b.zip), unzip the
files named `as.iN' (where `N' is a digit) from it, then type at the DOS
prompt:

      info as machine i386

You will see a menu of `Gas' features specific to x86 architecture.

A guide is available which was written by Brennan Underwood
<brennan@rt66.com>; it describes how to use inline assembly programming with
DJGPP and includes a tutorial on the AT&T assembly syntax.  Check out the
DJGPP inline assembly tutorial
(http://brennan.home.ml.org/djgpp/djgpp-asm.html).

Another useful tutorial about writing separate assembly-language modules for
DJGPP was written by George Foot <george.foot@merton.oxford.ac.uk> and is
available from George's home page
(http://users.ox.ac.uk/~mert0407/asmfuncs.txt).

The DJGPP User's Guide also has a tutorial on writing assembly-language code
(http://www.delorie.com/djgpp/doc/ug/asm/).

Many people who used Intel syntax and then converted to the AT&T style say
that they like the AT&T variant more.  However, if you prefer to stick with
the Intel syntax, download and install NASM
(ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutl/nasm096.zip), which is a
free portable assembler.  It is compatible with DJGPP and accepts a syntax
which is much more similar to the Intel style.  A guide for using NASM with
DJGPP was written by Matthew Mastracci <mmastrac@acs.ucalgary.ca> and is
available from Matthew's Web page
(http://www.acs.ucalgary.ca/~mmastrac/files/djgppasm.html).

17.2 Converting between Intel ASM syntax and AT&T syntax
========================================================

**Q*: Where can I find an automated conversion tool to convert my
`Intel'-style assembly code into a code acceptable by `Gas'?*

**Q*: Where can I find a converter from `AT&T' assembly to `Intel' style?*

*A*:  A SED script which should do most of the conversion was posted to the
DJGPP news group
(http://www.delorie.com/djgpp/mail-archives/djgpp/1995/06/06/05:48:34).

A program called `TA2AS' which can convert TASM assembly source to AT&T style
can be found on the DJGPP server
(ftp://ftp.delorie.com/pub/djgpp/contrib/ta2asv08.zip) and on Oulu
(ftp://x2ftp.oulu.fi/pub/msdos/programming/convert/ta2asv08.zip).  `TA2AS'
was written by Frank van Dijk of the Spirit group; if you have questions
about this tool, you may contact Jan Oonk <jan@stack.nl>.  The authors say
that the program is far from finished, but the sources are available with the
package so you can fix whatever is broken for your needs.

Alternatively, here is what you can do to make your code linkable with DJGPP
programs:

   * Get and install NASM, a portable x86 assembler which supports most of
     the Intel syntax and can generate DJGPP-compatible COFF object files (as
     well as lots of other formats, such as Microsoft 16-bit OBJ and Win32,
     a.out, and ELF).  It also supports Pentium and Pentium Pro opcodes, and
     MMX.  NASM is free for non-commercial use (see the docs for commercial
     use restrictions) and can be compiled with DJGPP.  NASM sources are on
     SimTel.NET
     (ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutl/nasm096s.zip).  A
     pre-compiled MS-DOS executable binary of NASM is available from
     SimTel.NET
     (ftp://ftp.simtel.net/pub/simtelnet/msdos/asmutl/nasm096.zip).  The
     author and maintainer of NASM is Simon Tatham <anakin@pobox.com>.

     Be warned that NASM is *not* 100% identical to MASM or TASM.  Even
     experienced assembly programmers might need some time to adapt to the
     slightly different flavor of NASM.  If you want something much more
     similar to TASM, get JAS.  JAS is available from OULU
     (ftp://x2ftp.oulu.fi/pub/msdos/programming/djgpp2/jas31.zip).

   * For a small number of relatively short files, consider converting them
     with a smart editor (like Emacs or its work-alikes).

   * Obtain a copy of Microsoft MASM 6.11. It has a `-coff' option to
     generate object code in COFF format which can be submitted to GCC, so
     you can compile your original source.  You can also use the `LIB32'
     librarian from Microsoft C8 to convert object files to COFF by putting
     them into a `.lib' library, then extracting them as COFF files.  (1)

   * Use a disassembler to disassemble the object code, then convert it to
     the AT&T format either by hand or using `TA2AS'.  One place to look for
     such a disassembler is on SimTel.NET mirrors
     (ftp://ftp.simtel.net/pub/simtelnet/msdos/disasm/).

Keep in mind that syntax is only one of the aspects of converting code
written for DOS to DJGPP.  You should also make sure your code doesn't
violate any of the rules for protected-mode programming (see next question in
Section 17.3).

If you need to perform the opposite conversion, from the `AT&T' style to the
`Intel' style, try the `Att2Intl' converter written by Greg Velichansky
<hmaon@umiacs.umd.edu>.  Its output is intended for NASM or TASM.  `Att2Intl'
is available from Greg's home page (http://www.wam.umd.edu/~gvelicha/a2i/).

---------- Footnotes ----------

(1) If you use MASM or LIB32, please post your experiences to
comp.os.msdos.djgpp news group, so that I can make the above instructions
less vague.

17.3 Converted code GP Faults!
==============================

**Q*: OK, I've succeeded in converting and compiling my assembly-language
program, but when I run it, I get "Segmentation Violation" and "General
Protection Fault".  This program works when compiled with MASM, so how can
this be?*

*A*: In DJGPP, your program runs in *protected mode*.  There are certain
things you can't do in protected-mode programs (that's why it is called
protected mode).  This issue is too complex to describe here, so only a few
of the more important aspects will be briefly mentioned.  If you are serious
about writing assembly language protected-mode code, or have a large body of
existing code to convert to protected mode, you should read any of the
available books about protected-mode programming with 80x86 processors.

Here is a short list of some of the techniques found in many real-mode
programs, which will trigger protection violation or erratic behavior in
protected mode:

   * Loading arbitrary values into segment registers, then using them to
     reference code or data.

   * Referencing code with data segment register, or vice versa.

   * Assuming certain locations (like BIOS area or video memory) will be found
     at certain absolute addresses.

   * Calling DOS or BIOS services with `INT NN' instruction.

   * Hooking interrupts by poking absolute addresses.

17.4 Which registers need to be saved in assembly code?
=======================================================

**Q*: Which register can I safely change in my assembly code that is called
from a C program?*

**Q*: How come my program crashes with a GPF, but only if I compile it with
-O2?*

*A*: You can safely clobber EAX, ECX, and EDX, but must save and restore all
other registers at the end of your assembly function.  Failure to preserve,
e.g., ESI, EDI, or EBX in functions written in assembly can cause a C program
linked with such functions to crash, since GCC expects those registers to be
preserved across function calls.

17.5 I want to use a `.obj' or `.lib' code with DJGPP
=====================================================

**Q*: I have a set of useful functions in a `.obj' format, but no source
code.  Can I use them with my DJGPP program?*

**Q*: I have this `ACMELUXE.LIB' library of functions which I want to use.
I've extracted all the `.obj' files, but when I try to link them with my
program, GCC complains: "File format not recognized".  Can't I use these
object files?*

**Q*: I've got a bunch of `.obj' files I want to use.  I've ran AR to make a
GCC-style `.a' object library, but got an error message from GCC saying
"couldn't read symbols: No symbols".  How can I link them with my code?*

*A*: Sorry, you probably can't.  The GNU linker called by GCC doesn't
understand the format of `.obj' files which other DOS-based
compilers/assemblers emit.  Unless you can get the source of those functions,
convert it to protected-mode, flat-address model code and compile them with
GCC, you most probably won't be able to use them(1).

However, if you are really desperate, one conversion tool you might try is
`OBJ2BFD'.  It was written by Robert Hoehne <robert.hoehne@gmx.net> based on
the `EMXAOUT' utility from the `emx/gcc' package.  `OBJ2BFD' requires the
`.obj' files to be written for the flat-address memory model and will
reportedly complain if you feed it with code written for segmented memory
models.  `OBJ2BFD' is available from the DJGPP sites
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/o2bfd01b.zip).

Another automated conversion tool called `OBJ2COFF' was written by the SPiRiT
team, and it can be used to convert `.obj' object files and `.lib' libraries
to `COFF' format, provided that the original `.obj' files have been written
for flat-address memory model.

`OBJ2COFF' is available via anonymous FTP transfer from the Oulu MSDOS
repository (ftp://x2ftp.oulu.fi/pub/msdos/programming/convert/o2cv10.arj).
If you have any problems with it or questions about it, send them to its
author Rico <mb002@hi.ft.hse.nl> or to George van Venrooij
<george@il.ft.hse.nl>.  Note that the authors of `OBJ2COFF' have explicitly
prohibited commercial use, so you shouldn't use `OBJ2COFF' for converting
commercial object files.

You can also try using LIB32 librarian from Microsoft C8 to convert object
files to COFF.

The main problem with these conversion methods is, of course, that most
object files you'd want to converted were written for real-mode programs in
memory models other than flat, and without extensive modifications would
crash your program anyway... (See previous question in Section 17.3.)

---------- Footnotes ----------

(1) Note that mixing object files from different compilers generally doesn't
work at all, even if all the object files are in `.obj' format.

17.6 I *must* use my 16-bit code with DJGPP!!
=============================================

**Q*: If that's how it is, then I would have to give up using DJGPP.  I
simply cannot live without these `.obj' files.  Are you *really* sure there
is nothing I can do??*

*A*: If you need your old code *that* badly, then there might be a way,
albeit a cumbersome one.  You can write a 16-bit, real-mode program and link
it with your precious functions you can't live without.  Have this program
spawn a DJGPP-compiled program and make the two communicate with each other
via a buffer allocated in low memory, or via command-line parameters passed
to the 32-bit program by the `spawnXX' function call.  On the DJGPP side, you
can directly call 16-bit functions from the real-mode program using the
library function called `__dpmi_simulate_real_mode_procedure_retf', provided
the 16-bit program passes the CS:IP values of these functions to the 32-bit
program.  You can even put your 16-bit code as binary instructions into a
buffer allocated in low memory and call it with
`__dpmi_simulate_real_mode_procedure_retf' (but if you can do that, you can
probably also disassemble the code into a source form and submit it to `Gas').

*Now* will you consider sticking with DJGPP?  *Please??...*

17.7 What should I do with those "near" and "far" declarations?
===============================================================

**Q*: I have this program that I need to port to DJGPP, but it is full of
pointers and functions declared with the "near" and "far" keywords which GCC
doesn't grok.  What shall I do?*

**Q*: A program written for a 16-bit compiler uses the MK_FP or _MK_FP macro,
but DJGPP doesn't seem to have it.  How should I port it?*

**Q*: How do I compute a segment and an offset of a protected-mode address?*

*A*:  In DJGPP you use a flat address space with no segmentation (it is a
kind of tiny model, since CS = DS = SS, but with a *very* large segment), so
you don't need far pointers in the sense they are used in 16-bit code. Just
define away those keywords and you will be fine:

       #define far
       #define near
       #define huge
       #define _far
       #define _near
       #define _huge

Alternatively, you could add suitable `-D' switches to the GCC command line,
like this:

       gcc -Dfar= -Dnear= -Dhuge= -c myprog.c

Macros that create far pointers from the segment and offset (usually called
`MK_FP' or `_MK_FP') are mostly used in 16-bit code to access certain
absolute addresses on memory-mapped peripheral devices, like the video RAM.
These chores are done differently in DJGPP.  Here's one possible way to
express `MK_FP' in DJGPP (courtesy of Charles Sandmann
<sandmann@clio.rice.edu>):

       #include <sys/nearptr.h>
       #include <crt0.h>
     
       void * MK_FP (unsigned short seg, unsigned short ofs)
       {
         if ( !(_crt0_startup_flags & _CRT0_FLAG_NEARPTR) )
           if (!__djgpp_nearptr_enable ())
             return (void *)0;
         return (void *) (seg*16 + ofs + __djgpp_conventional_base);
       }

The above uses the DJGPP nearptr facility; if you prefer to use farptr
functions (which are safer and work with all known DPMI hosts), you will need
to rewrite the code that uses these macros, so don't bother writing a
replacement for the macro itself.  The details are described in Accessing
absolute addresses in Section 18.4, below.

Macros that extract the segment and the offset from a far pointer (called
`FP_SEG' and `FP_OFF') are required in 16-bit code to pass addresses in
registers when calling real-mode DOS or BIOS services, like functions of
interrupt 21h.  See How to call real-mode interrupt functions in Section
18.2, which describes how that should be done in DJGPP; here, too, you won't
need to port the macros but instead rewrite the code that calls the DOS or
BIOS service.  In particular, you *cannot* compute a real-mode segment and
offset of a protected-mode address, because real-mode addresses can only
access the first 1MB of memory, whereas the variables of DJGPP programs all
live above the 1MB mark.

17.8 How to convert _AX pseudo-registers?
=========================================

**Q*: Since DJGPP doesn't recognize Borland-style pseudo-register variables
like _AX, how should I port code which uses them to DJGPP?*

*A*:  These pseudo-variables are typically used in two different contexts:

   * When calling real-mode interrupt services.

     To port such code to DJGPP, use the fields of the `__dpmi_regs'
     structure (declared on the `dpmi.h' header file) to set the register
     values, and library function `__dpmi_int' to invoke the interrupt
     service.  For example, consider the following code snippet:

            #include <dos.h>
            void _highcolor (void)
            {
              _AH = 0x10;
              _AL = 0x03;
              _BL = 0;
              geninterrupt (0x10);
            }

     Here's one way to express this in DJGPP(1):

            #include <dpmi.h>
            void _highcolor (void)
            {
              __dpmi_regs r;
          
              r.h.ah = 0x10;
              r.h.al = 0x03;
              r.h.bl = 0;
              __dpmi_int (0x10, &r);
            }

     Please read how to call real-mode interrupt functions in Section 18.1,
     elsewhere in this document, for further details on how call real-mode
     services from DJGPP programs.

   * Immediately before or after an inline assembly code.

     GCC features extensive inline assembly facilities which allow you to
     assign values to, or read values from registers from the inline assembly
     code.  See description of inline assembly in Section 18.13, for further
     info.

---------- Footnotes ----------

(1) This function calls the video BIOS interrupt 10h to allow bright
background colors to be used instead of blinking characters.  DJGPP has a
library function, called `intensevideo', to do that, but let's assume we have
reasons not to use it.

18. Low-level DOS/BIOS and Hardware-oriented Programming
********************************************************

  This chapter sheds some light on a few aspects of writing DJGPP programs
which interact with hardware or use interrupts.

18.1 Got "Unsupported INT 0xNN" calling `int86'
===============================================

**Q*: Why does my program crash with "Unsupported DOS request 0xNN" or
"Unsupported INT 0xNN" when I call `int86' or `intdos' functions to invoke a
software interrupt?*

*A*:  Calling real-mode DOS or BIOS services from protected-mode programs
requires a switch to real mode, so the `int86' family of functions in the
DJGPP library should reissue the INT instruction after the mode switch.
However, some services require pointers to memory buffers.  Real-mode
DOS/BIOS functions can only access buffers in conventional memory, so `int86'
has to move data between your program and low memory to transparently support
these services.  But this means it should know about all these services to
perform these chores correctly, because each service has its own layout and
size of the buffer(s).  While `int86' supports many of these services, it
doesn't support all of them.  The supported functions are listed in the
library reference.  See int86 in "libc.a reference", or point your Web
browser to http://www.delorie.com/djgpp/doc/libc-2.01/libc_411.html#SEC411.
For those it doesn't support, you will have to call the `__dpmi_int' library
function instead.  It is also documented in the library reference, see
__dpmi_int in "libc.a reference", or point your Web browser to
http://www.delorie.com/djgpp/doc/libc-2.01/libc_208.html#SEC208.
`__dpmi_int' requires that you set up all the data as required by the service
you are calling, including moving the data to and from low memory (see how to
use buffers with DOS/BIOS services in Section 18.2).

Note that calling `int86' and `intdos' can sometimes cause trouble due to
size (16 bits as opposed to 32 bits) of the members in the `union REGS'
structure.  Do *not* assume that e.g. `regs.x.ax' is always 16 bit!  This
problem and the facilities available to specify the width of the registers
are all described in the library reference; see description of the int86
function in "libc.a reference", or point your Web browser to
http://www.delorie.com/djgpp/doc/libc-2.01/libc_411.html#SEC411.

In particular, programs which interface with the mouse via calls to the
`int86' library function, should mask off the high 16 bits of the registers
which report mouse position and other values, since the high 16 bits aren't
necessarily zeroed (which will wreak havoc in any program that interfaces to
the mouse).

18.2 How to use buffers with DOS/BIOS services
==============================================

**Q*: I want to call a DOS/BIOS function which requires a pointer to a buffer
in, e.g. ES:DI (or any other) register pair.  How do I get the segment to put
into the ES register?*

**Q*: I have some real-mode code that calls the `segread' function.  How can
I make it work with DJGPP?*

*A*: If you use `int86x' or `intdosx' for a DOS or BIOS function supported by
them, then just put the address of your buffer into the register which
expects the offset (`regs.x.di'), forget about the segment, and call `int86'
or `intdos' instead of `int86x' and `intdosx'.  The DOS/BIOS functions
supported by `int86' and `intdos' are processed specially by the library,
which will take care of the rest.  Note that calling `int86x' and `intdosx'
will usually crash your program, since they expect that you pass them a
real-mode segment:offset address to a buffer in conventional memory; this is
done more easily with `__dpmi_int', see below.

If you call `__dpmi_int', then you must put into that register pair an
address of some buffer in *conventional* memory (in the first 1 MByte).  If
the size of that buffer doesn't have to be larger than the size of transfer
buffer used by DJGPP (at least 2KB, 16KB by default), then the easiest way is
to use the transfer buffer.  (Library functions don't assume the contents of
the transfer buffer to be preserved across function calls, so you can use it
freely.)  That buffer is used for all DOS/BIOS services supported by DJGPP,
it resides in conventional memory, and is allocated  by the startup code.
DJGPP makes the address and the size of the transfer buffer available for you
in the `_go32_info_block' external variable, which is documented the library
reference.  Check the size of the buffer (usually, 16K bytes, but it can be
made as small as 2KB), and if it suits you, use its linear address this way:

     dpmi_regs.x.di =
      _go32_info_block.linear_address_of_transfer_buffer & 0x0f;
     dpmi_regs.x.es =
      _go32_info_block.linear_address_of_transfer_buffer >> 4;

For your convenience, the header file `go32.h' defines a macro `__tb' which
is an alias for `_go32_info_block.linear_address_of_transfer_buffer.'

Here's a simple example of calling a real-mode service.  This function
queries DOS about the country-specific information, by calling function 38h
of the DOS Interrupt 21h, then returns the local currency symbol as a C-style
null-terminated string in `malloc'ed storage.  Note how the transfer buffer
is used to retrieve the info: the address of the transfer buffer is passed to
DOS, so it stores the data there, and the function then retrieves part of
that data using `dosmemget'.

      #include <sys/types.h>
      #include <sys/movedata.h>
      #include <dpmi.h>
      #include <go32.h>
     
      char * local_currency (void)
      {
        __dpmi_regs regs;
     
        regs.x.ax = 0x3800;        /* AH = 38h, AL = 00h  */
        regs.x.ds = __tb >> 4;     /* transfer buffer address in DS:DX  */
        regs.x.dx = __tb & 0x0f;
        __dpmi_int (0x21, &regs);  /* call DOS  */
        if (regs.x.flags & 1)      /* is carry flag set?  */
          /* The call failed; use the default symbol.  */
          return strdup ("$");
        else
          {
            /* The call succeeded.  The local currency symbol is stored
               as an ASCIIZ string at offset 2 in the transfer buffer.  */
            char *p = (char *)malloc (2);
            if (p != 0)
              dosmemget (__tb + 2, 2, p);
            return p;
          }
       }

If the size of the transfer buffer isn't enough, you will have to allocate
your own buffer in conventional memory with a call to the
`__dpmi_allocate_dos_memory' library function.  It returns to you the segment
of the allocated block (the offset is zero).  If you only need a small number
of such buffers which can be allocated once, then you don't have to worry
about freeing them: they will be freed by DOS when your program calls `exit.'

For bullet-proof code, you should test the size of the transfer buffer at
runtime and act accordingly.  This is because its size can be changed by the
`STUBEDIT' program without your knowledge (however, it can never be less than
2KB, the size of the stub, because memory used by the stub is reused for the
transfer buffer).

The function `segread' used by some real-mode compilers does not exist in
DJGPP.  It is used in real-mode code to store the values of the CS, DS, SS,
and ES registers into a `struct SREGS' variable, when some service that needs
one of these registers is called from code written for small and tiny memory
models.  DJGPP has the functions `_my_cs', `_my_ds', and `_my_ss' for that
purpose (ES and DS always hold the same selector in code produced by GCC from
a C or C++ source, so you don't need a fourth function).  However, these will
not be useful if the original real-mode code used the segment registers to
invoke DOS/BIOS services.  For these cases, you will need to rewrite the code
so that it copies the data to/from the transfer buffer and passes its address
via `__dpmi_int', as described above.

18.3 How to call software interrupt functions
=============================================

**Q*: My program crashes/doesn't do what it should when I call
`__dpmi_simulate_real_mode_interrupt.'*

*A*: You should zero out some of the members of the `__dpmi_regs' structure
before you call that function.  Random values in these members can cause your
program to behave erratically.  The members in point are `.x.ss', `.x.sp',
and `.x.flags'.  When `.x.ss' and `.x.sp' are zeroed, the DPMI host will
provide a stack for the interrupt call.  This stack is locked and is 4KB-long
for any handling done in protected mode (such as real-mode callbacks), and at
least 512 bytes in size for interrupts reflected into real mode.  This is
usually enough, but sometimes you'll need to use your own, larger stack, e.g.,
if you expect interrupts to nest, or if your handler needs a lot of stack
space(1).  In these cases you should point `.x.ss' and `.x.sp' to a larger
buffer which is in conventional memory (possibly part of the transfer buffer).

If SS:SP isn't zero, it will be used as the address of the stack for the
interrupt handler, so if it points to a random location, your program will
most certainly crash.  A non-zero FLAGS member can also make the processor do
all kinds of weird things (e.g., imagine that the single-step or the debug
bit is set!).

If you don't have any reason to set SS:SP to a user-defined stack, it's
easier to call the `__dpmi_int' library function, which zeroes out the stack
pointer and the FLAGS fields for you (and also doesn't force you to type long
function names!).

---------- Footnotes ----------

(1) The DPMI spec indicates that you should *not* use the default stack if
your procedure/interrupt handler uses more that 60 bytes, or 1/8 of the total
stack space available by default.

18.4 How to move data between your program and conventional memory
==================================================================

**Q*: How can I move data between my program and the transfer buffer?*

**Q*: How do I access my peripheral card which is memory-mapped to an address
between 640K and 1M?*

**Q*: How can I read or change a value of one of the variables in the BIOS
data area?*

**Q*: How can I peek at an address whose far pointer I get from an INT 21h
call?*

*A*: Usually, memory-mapped devices or absolute addresses below 1MB mark are
outside your program's address space, so you cannot access them directly.
"Direct access", when you just dereference a pointer, means in DJGPP that you
use your program's DS selector, and all the addresses are offsets relative to
the base of that selector.  So first, you will need a special selector that
will allow you to access your device or absolute address.  There are several
methods you can get such a selector:

   * Use the selector that DJGPP creates for itself to access conventional
     memory.  DJGPP makes this selector available to you via the `_dos_ds'
     macro (defined on the `go32.h' header file).  This selector has base
     address of 0 and a limit of 1MB+64KB, so you can use it to access any
     address in the conventional memory, including the UMBs, but the
     relatively large limit allows a buggy program to overwrite portions of
     DOS memory(1).  The advantage of `_dos_ds' is obviously that you don't
     have to create it, and that it is good for accessing every region in the
     first MByte range.

   * Create your own selector that spans only the region of memory that you
     want to access, and use that selector instead of `_dos_ds'.  For
     example, here's a code snippet to set up a selector which provides
     access to 32KB of text-mode video memory at `0xB800:0000', courtesy of
     Bill Currie <bill@tanihwa.tssc.co.nz>(2):

            int TxtVRAMSetupSelector (void)
            {
               static char selectorData[8] = {
                 0xff, 0x7f, 0x00, 0x80,
                 0x0b, 0xf3, 0x40, 0x00
               };
               int screenSelector = __dpmi_allocate_ldt_descriptors (1);
               if (__dpmi_set_descriptor (screenSelector, selectorData) < 0)
                 abort ();
               return screenSelector;
            }

     The advantages of this method are that (a) you can set up the selector
     limit such that it only covers the memory region that you need, thus
     protection of the rest of memory is retained; and (b) you may set the
     base address to point to the beginning of the specific memory region you
     need to access, so that you don't have to add the base address for every
     access, making the access faster.

   * Use the DPMI service which creates a selector to access a specific
     real-mode segment address.  The DJGPP library has a function
     `__dpmi_segment_to_descriptor' which is a wrapper around that DPMI
     service.  It is easier to use than the `__dpmi_set_descriptor' function
     above, since you don't have to mess with the 8-byte descriptor buffer,
     but it always defines a 64KB limit by default.  Here is an example of
     code which gets a selector to access 64KB of video RAM beginning at
     `0xA000:0000':

            short video = __dpmi_segment_to_descriptor(0xa000);

     Note that descriptors created by this function should never be modified
     or freed.  For this reason, you should use this function sparingly.  For
     instance, if your program needs to examine various real mode addresses
     using the same selector, you should allocate a descriptor and change the
     base using the `__dpmi_set_segment_base_address' library function
     instead of using `__dpmi_segment_to_descriptor' to allocate separate
     descriptor for each address.

Once you have a selector, you can use one of three methods to access your
absolute addresses using that selector:

   * If you want to access a byte, a 16-bit word, or a 32-bit double word,
     use the "far pointer" functions declared on the `<sys/farptr.h>' header
     file.  You should convert any real-mode far pointer segment:offset pair
     into a "linear address" (i.e., segment*16 + offset), and use `_dos_ds'
     or any other selector which allows access to conventional memory, like
     this:

           unsigned char value = _farpeekb(_dos_ds, segment * 16 + offset);

     For access to memory-mapped devices for which you have allocated a
     dedicated descriptor, use the selector of that descriptor instead of
     `_dos_ds' in the above example, and use the offset into the on-board
     device memory as the offset.  For example, the following snippet writes
     a value of 3 to the 10th dword of the device:

           long lword = 3;
           _farpokel (selector, 9, lword);

     Use `_farpeekw' to peek at 16-bit shorts and `_farpeekl' to peek at
     32-bit longs.  If you need to access several (non-contiguous) values in
     a loop, use the corresponding `_farnspeekX' functions which allow you to
     set the selector only once, as opposed to passing it with every call
     (but be sure the loop doesn't call any function that itself sets the
     selector; see the library reference for more details).

     There is a corresponding set of `_farpokeX' and `_farnspokeX' functions
     to poke (change the values of) such memory locations.

     These functions have an advantage of emitting inline assembly code when
     you compile with optimizations, so they are very fast.  See the library
     reference Info file for further details about these functions.

   * If you need to access more than 4 contiguous bytes, use `dosmemget' and
     `dosmemput' library functions.  They also require you to convert the
     segment:offset pair into a linear address, but they don't need the
     conventional memory selector, as they can only be used to access the
     conventional memory (they use `_dos_ds' internally).

     Note that some memory-mapped peripheral devices might require 16-bit word
     accesses to work properly, so if `dosmemXXX' yields garbled results, try
     `dosmemXXXw' or set up a loop which calls "farptr" functions.

   * For moving buffers to selectors other than `_dos_ds' (e.g., created by
     one of the methods explained above), use the `movedata' library
     function.  It requires that you pass a selector and an offset for both
     the memory-mapped address and for the buffer in your program's address
     space.  Use the `_my_ds()' function (note that it's a *function*, not a
     variable!) to get the selector of any variable in your program, and use
     the address of the variable (cast to an `int') as its "offset" or linear
     address.  `movedata' is fast because it moves by 32-bit longs, but be
     careful with its use when moving data to and from peripheral cards: some
     of them only support 8- or 16-bit wide data path, so moving data 4 bytes
     at a time won't gain you much, and might even get you in trouble with
     some buggy BIOSes.  The functions `movedatab' and `movedataw' are
     provided for moving by bytes and by 16-bit words, respectively.

     For example, here is a code snippet that combines one of the methods for
     allocating a descriptor for video RAM access with a call to `movedata'
     to move a buffer to the graphics screen:

            short video = __dpmi_segment_to_descriptor(0xa000);
            movedata(_my_ds(), buffer, video, 0, 320*200);

   * For the fastest access to memory outside your usual address space, you
     might consider using the "nearptr" functions declared on the
     `sys/nearptr.h' header file; see the library reference for more details.
     Also see description of how to get the fastest direct access to
     peripheral devices in Section 18.6, below.

---------- Footnotes ----------

(1) DJGPP v2.01 makes the limit of `_dos_ds' be 4GB, which effectively
disables memory protection when you use that selector.  However, since no
memory outside the first 1MB is properly mapped into your program's address
space without additional DPMI calls, and the DPMI host is then free to put
memory-mapped devices, such as Weitek I/O space or the linear frame buffer of
an SVGA, on any address it sees fit, that huge limit is an unjustified
security hole.  DJGPP v2.02 will really be limited by 1MB+64KB.

(2) If you want to decipher the 8-byte structure that is passed to
`__dpmi_set_descriptor' in this example, read the documentation of the
`__dpmi_get_descriptor' library function in the library reference.  This
structure is the descriptor maintained by the processor for each
protected-mode segment, such as those loaded into the CS and DS registers.

18.5 How to move structs returned by real-mode services?
========================================================

**Q*: My program uses the contents of a structure returned by a VBE function,
but some of the struct members are garbled!*

*A*: Most probably, this happens because of incorrect declaration of the
structure in your program.  Many people copy a declaration from some
real-mode program, and that is exactly what gets them into trouble.

Here are some gotchas in this context:

   * The structure should be declared with `__attribute__((packed))', to
     prevent GCC from inserting gaps between some members to make them
     properly aligned for faster access (see how gcc aligns structs in
     Section 22.10).  C programs can declare the entire struct with the
     packed attribute, but C++ programs will need to declare each member with
     it, see __attribute__((packed)) in Section 22.10.

   * If the real-mode struct has members which are pointers, you need to
     replace each pointer with a pair of an offset and a segment (in that
     order, due to Intel's little-endian byte order).  This is because
     real-mode far pointers cannot be used as protected-mode pointers: you
     cannot dereference them to get access to the object they point to.
     Declaring them as a segment:offset pair will force you into correct
     usage, see below.

   * To use pointers which are members of the structure, you will have to
     employ some of the methods described in section about using the transfer
     buffer in Section 18.4.  For example, to copy data whose real-mode
     address is returned in a struct, use `dosmemget' or one of the
     `_farpeekX' family of functions in conjunction with the `_dos_ds'
     selector, and don't forget to compute the linear address as `segment *
     16 + offset'.

   * If the pointer is to a function, you will need to use the library
     function `__dpmi_simulate_real_mode_procedure_retf' to call it (don't
     forget to zero out the `.x.ss' and `.x.sp' members of the `__dpmi_regs'
     structure!).

   * Many real-mode compilers use 16-bit `int's, whereas in DJGPP, an `int'
     is 32-bit wide.  You need to change the declaration of all struct
     members from `int' to `short', and from `unsigned' to `unsigned short'.

For example, the following real-mode structure declaration:

      struct ncb {
        unsigned ncb_command;
        int ncb_status;
        char far *ncb_buffer;  /* a far pointer to a buffer */
        char ncb_name[32];
        int far (*ncb_dispatch)();  /* a pointer to a far function */
      };

should be converted to this in a DJGPP program:

      struct ncb {
        unsigned short ncb_command __attribute__((packed));
        short ncb_status __attribute__((packed));
        unsigned short ncb_buf_offset __attribute__((packed));
        unsigned short ncb_buf_segment __attribute__((packed));
        char ncb_name[32] __attribute__((packed));
        unsigned short ncb_dispatch_offset __attribute__((packed));
        unsigned short ncb_dispatch_segment __attribute__((packed));
      };

18.6 Fast access to absolute addresses
======================================

**Q*: The "farptr" functions are too slow for my application which *MUST*
have direct access to a memory-mapped device under DPMI.  How can I have this
in DJGPP?  My entire optimized graphics library is at stake if I can't! :-(*

*A*:  The following so-called Fat DS, or "nearptr" method was suggested by
Junaid A. Walker <junaid@barney.eng.monash.edu.au> (he also posted a program
which uses this technique to access the video RAM; you can look it up by
searching the mailing list archives).  But first, a word of warning: the
method I'm about to describe effectively disables memory protection, and so
might do all kinds of damage if used by a program with a wild pointer.  It is
depressingly easy, e.g., to overwrite parts of DOS code or data with "Fat DS"
on.  Or, as Stephen Turnbull <turnbull@shako.sk.tsukuba.ac.jp> has put it
when he read the description of this trick:

     *Surgeon General's WARNING*:  The description below uses the "Fat DS
     hack", a steroid derivative which gives your program great strength, a
     thick neck, baldness, and is known to be closely linked with the
     Alzheimer's disease.

In addition to the above warning, experience shows that many programs which
use the safer "farptr" functions do not sacrifice performance.  So, with the
exception of a small number of programs, "nearptr" is really a convenience
trick: it allows you to treat memory-mapped devices with usual C pointers,
rather than with function calls.  Therefore, I would generally advise against
using "nearptr" unless your program absolutely needs the last percent of
speed.

Having said that, here is the trick: you change the limit of the segment
descriptor stored in DS to `0xffffffff' (i.e., -1), using library function
`__djgpp_nearptr_enable'.  After that, you have access to all the memory
which is currently mapped in.  This works due to 32-bit wrap-around in the
linear address space to access memory at, say, linear address 0xa0000 (which
belongs to the VGA), or any other address on your memory-mapped device, by
adding the value of the global variable `__djgpp_conventional_base' to the
target address.  `__djgpp_conventional_base' is the negated base address of
the DS selector that you program is using to access its data.  By adding the
value of `__djgpp_conventional_base', you effectively *subtract* the DS base
address, which makes the result zero-based, exactly what you need to access
absolute addresses.

You should know up front that this trick won't work with every DPMI host.
Linux's DOSEmu and Windows/NT won't allow you to set such a huge limit on the
memory segment, because these operating systems take memory protection
seriously; in these cases `__djgpp_nearptr_enable' will return zero--a sign
of a failure.  CWSDPMI, QDPMI, Windows 3.X and Windows 9X all allow this
technique (OS/2 Warp seems to allow it too, at least as of version 8.200),
but some events break this scheme even for those DPMI hosts which will allow
it.  A call to `malloc' or any other library function which calls `sbrk'
might sometimes change the base address of the DS selector and break this
method unless the base address is recomputed after `sbrk' call.  (The
"nearptr" functions support this recomputation by providing you with the
`__djgpp_conventional_base' variable, but it is *your* responsibility to
recompute the pointers using it.)  The same change can happen when you call
`system', and as a result of some other events external to the executing code
thread, like multitasking or debugger execution.

You should also know that the `__djgpp_nearptr_enable' function in DJGPP v2.0
didn't verify that the limit was properly set.  So if the DPMI server would
fail the call *silently*, the function won't detect it and will not return a
failure indication.  DJGPP v2.01 corrects this omission by always verifying
that the DPMI host has honored the request, and returns a failure indication
if it hasn't.

If you are aware of these limitations, and don't need your code to run under
all DPMI hosts, it might be the fix to your problems.

Confused about how exactly should you go about using this technique in your
program?  Look at the docs of the "nearptr" functions, see
__djgpp_nearptr_enable in "libc.a reference", or point your Web browser to
http://www.delorie.com/djgpp/doc/libc-2.01/libc_122.html#SEC122.

Another possibility is to use the DPMI function `0x508' that can map any
range of physical memory addresses into a block that you allocate.  Note that
this is a DPMI 1.0 functionality which is *not* supported by most DPMI 0.9
hosts (CWSDPMI does support it).  There is a helper function
`__djgpp_map_physical_memory' in the DJGPP C library that you can use to call
these services.

18.7 Accessing absolute address above 1MB
=========================================

**Q*: How can I access memory-mapped peripheral devices (or any other
absolute address) above 1 MByte mark?*

*A*:  You should use DPMI functions to allocate an LDT descriptor, and map it
to an absolute physical address.  This maps the physical address of the
memory on the device to a linear address, and returns that linear address to
you.

Here are the DPMI calls that you will have to use:

   - map selector to physical address (Int 31h/AX=0800h);

   - allocate an LDT descriptor (Int 31h/AX=0);

   - set segment base address (Int 31h/AX=7);

   - set segment limit (Int 31h/AX=8).

All of these DPMI calls have `__dpmi__XXX' wrappers in the DJGPP library.
Here's a somewhat schematic example:


      #include <dpmi.h>
      .
      .
      __dpmi_meminfo mi;
      int selector;
      .
      .
      /* Map the physical device address to linear memory.  */
      mi.address = physical_address;
      mi.size    = physical_address_size;
      __dpmi_physical_address_mapping (&mi);
      /* Now mi.address holds the linear address.  */
      .
      .
      /* Allocate an LDT descriptor and set it up to span the entire
         device on-board memory.  */
      selector = __dpmi_allocate_ldt_descriptor (1);
      __dpmi_set_segment_base_address (selector, mi.address);
      __dpmi_set_segment_limit (selector, mi.size - 1);

Note that the segment limit should be one less than the size.  Also, segments
over 1MB in length must be a multiple of 4KB, otherwise the DPMI server might
fail the call, or silently change the limit.

You can then use the functions from the `sys/farptr.h' header file to access
that device.  See accessing memory-mapped devices in Section 18.4, for more
details about accessing memory-mapped devices given their linear address.

18.8 How to make DOS/BIOS call your function
============================================

**Q*: How can I make any real-mode service call my function?  E.g., the mouse
driver has a provision (function 0Ch) to call a user-defined handler when
certain events occur, which expects a far pointer to my function in the ES:DX
register pair.*

*A*:  Those services expect a real-mode function, so you should wrap your
protected-mode function with a real-mode stub.  To this end, call either the
`_go32_dpmi_allocate_real_mode_callback_retf' or the
`_go32_dpmi_allocate_real_mode_callback_iret' library function, as required
by the real-mode service you want to hook, and pass the `segment' and
`offset' members it returns to the service you want (in the above example,
Int 33h function 0Ch) by calling `__dpmi_int.'  Here's a code fragment that
shows how to do this(1):


       #include <dpmi.h>
       #include <go32.h>
     
       static __dpmi_regs        callback_regs;
       static _go32_dpmi_seginfo callback_info;
     
       int install_mouse_handler (unsigned mask,
                                  void (*func)(__dpmi_regs *))
       {
         __dpmi_regs r;
     
         callback_info.pm_offset = (long)func;
         if (_go32_dpmi_allocate_real_mode_callback_retf(&callback_info,
                                                         &callback_regs))
           return -1;  /* failure */
     
         r.x.ax = 0xc;
         r.x.cx = mask;
         r.x.es = callback_info.rm_segment;
         r.x.dx = callback_info.rm_offset;
         __dpmi_int (0x33, &r);
         return (r.x.flags & 1) ? -1 : 0;
       }

The handler (`func' in the above example) will be called with a pointer to a
`__dpmi_regs' structure which is filled by values found in the CPU registers
when the mouse driver calls the handler.  See the docs in the library
reference Info file for further details about allocating wrapper functions.

---------- Footnotes ----------

(1) If you are using this example in your program, don't forget to disable
the handler at program's exit by calling the same function 0Ch of Int 33h
with a zero mask in the CX register, and then deallocate the callback by
calling the `_go32_dpmi_free_real_mode_callback' library function.  Also,
remember that all code and data touched by the handler must be locked,
otherwise it will crash under some DPMI servers, such as CWSDPMI.

18.9 How to hook hardware interrupts
====================================

**Q*: How do I register my DJGPP function as a hardware interrupt handler?*

*A*:  The optimal setup depends on the interrupt frequency and on the amount
of processing it requires.  Therefore, only some basic considerations and
techniques are listed below.  What combination of these is best for your
application is up to you to decide.

First, some background.  Hardware interrupts can occur when the processor is
either in real mode (like when your program calls some DOS service) or in
protected mode.  When your program runs under a DPMI host, hardware
interrupts are caught by the DPMI host and passed to protected mode first;
only if unhandled, they are then reflected to real mode.  Therefore, in DPMI
mode you can get away with installing only a protected-mode handler.
However, if the interrupts happen at a high frequency (say, more than 10
KHz), then the overhead of the interrupt reflection from real to protected
mode might be too painful, and you should consider installing a real-mode
interrupt handler in addition to the protected-mode one.  Such a real-mode
handler will be called *before* the interrupt gets to the DPMI host, and
handle the interrupt entirely in real mode, so it must be written in assembly
and located in conventional memory (below the 1MB mark).  If you need to hook
an interrupt with both PM and RM handlers, you must hook the PM interrupt
first, then the RM one (because hooking the PM interrupt modifies the RM
one).  Also, you should know that some DPMI hosts don't allow you to hook the
RM interrupt (CWSDPMI does), and some call both handlers, no matter in what
mode the interrupt arrived (CWSDPMI will only call one of them); the only way
to be sure is to try.

To install a protected-mode interrupt handler, you do this:

   * In general, your handler should be written in assembly to be
     bullet-proof.  You should lock(1) all the memory (code, data and stack)
     that could be touched by your handler during interrupt processing (this
     is virtually impossible if the handler is written in C), explicitly
     issue the `STI' instruction before `IRET', and perform all the other
     chores described in the DPMI spec (see DOS Protected Mode Interface
     Specification in DPMI Spec).  To install an assembly handler, you should
     do this:

        - Call `__dpmi_get_protected_mode_interrupt_vector' and save the
          structure it returns (to restore the previous handler address
          before your program exits).

        - Lock all the memory your handler touches and the code of the handler
          itself and any function it calls with a series of calls to
          `__dpmi_lock_linear_region'.  Failure to lock memory accessed
          during the interrupt handling will cause your program to crash.
          Alternatively, you could set the `_CRT0_FLAG_LOCK_MEMORY' bit in
          the `_crt0_startup_flags' variable, or disable virtual memory by
          using CWSDPR0.

        - Finally, call `__dpmi_set_protected_mode_interrupt_vector' and pass
          it a pointer to a `__dpmi_paddr' structure filled with the value
          returned by `_my_cs()' in the `selector' field and the address of
          your function in the `offset32' field.

   * If your handler function is written in C, you should generally call the
     `_go32_dpmi_XXX' functions instead of the bare-bones API wrappers whose
     names start with `__dpmi_.'  Specifically:

        - Call `_go32_dpmi_get_protected_mode_interrupt_vector.'  This
          function puts the selector and offset of the specified interrupt
          vector into the `pm_selector' and `pm_offset' fields of the
          structure pointed to by its second argument.  This data should be
          saved and later passed to
          `_go32_dpmi_set_protected_mode_interrupt_vector' to restore the
          vector on exit.

        - Call `_go32_dpmi_allocate_iret_wrapper,' passing it the address of
          your function in the `pm_offset' field and the value returned by
          `_my_cs()' in the `pm_selector' field.  The `pm_offset' field will
          get replaced with the address of the wrapper function which is a
          small assembler function that handles everything an interrupt
          handler should do on entry and before exit (and what the code GCC
          generates for an ordinary C function doesn't include); the effect is
          similar to using the `interrupt' or `_interrupt' keyword in some
          DOS-based compilers.

        - If you want your handler to chain to the previous handler, call
          `_go32_dpmi_chain_protected_mode_interrupt_vector.'  This will set
          up a wrapper function which, when called, will call your handler,
          then jump to the previous handler after your handler returns.  Put
          the address of your handler into the `pm_offset' field and the
          value of `_my_cs' into the `pm_selector' field of the
          `_go32_dpmi_seginfo' structure and pass a pointer to it to this
          function.

        - You then call `_go32_dpmi_set_protected_mode_interrupt_vector' with
          the address of the `_go32_dpmi_seginfo' structure you got from
          either `_go32_dpmi_allocate_iret_wrapper' or
          `_go32_dpmi_chain_protected_mode_interrupt_vector.'

     The problem with writing handlers in C as above is that the wrappers'
     code and data aren't locked, and in practice you can't lock all of
     memory the handler itself uses, either.  Thus, this approach is
     generally unsuitable for production-quality software and should be used
     only when the program is known not to page (i.e., only the physical
     memory is used).  You might consider disabling virtual memory to make
     sure your program doesn't page.  To accomplish this, either set the
     `_CRT0_FLAG_LOCK_MEMORY' bit in the `_crt0_startup_flags' variable, or
     use CWSDPR0 or PMODE/DJ as your DPMI host.  In fact, using one of these
     methods is the recommended way of debugging the first versions of a
     program that hooks hardware interrupts; only after you are sure that
     your basic machinery works should you move to testing it in a setup when
     paging might happen.

     Note that `_CRT0_FLAG_LOCK_MEMORY' is only recommended for small
     programs that run on a machine where enough physical memory is always
     available, because the startup code currently doesn't test if memory is
     indeed locked, and if there's not enough physical memory installed to
     page in all of the memory your program needs, you can end up with
     unlocked or partially unlocked memory, which will crash your program.
     If you want to make sure all memory is locked, use a DPMI server which
     disables paging.

To install a real-mode interrupt handler, you do this:

   * Call `__dpmi_get_real_mode_interrupt_vector' and save the structure it
     returns (to restore the previous handler address before your program
     exits).

   * Allocate some conventional memory with `__dpmi_allocate_dos_memory' and
     put the code of your handler there with the `dosmemput' function.  (You
     could also call one of the functions which allocate a real-mode
     call-back, but these will cause a mode switch on every interrupt, which
     you want to avoid; otherwise there is no point in installing a real-mode
     handler, right?)

   * Put the address which `__dpmi_allocate_dos_memory' returned into a
     `__dpmi_raddr' structure (the lower 4 bits into `offset16' field, the
     rest into `segment' field), then call
     `__dpmi_set_real_mode_interrupt_vector.'

Note that Windows 9X is reported to call both the RM and PM handlers if both
are installed, at least for some interrupts (CWSDPMI only invokes one of
them).  So, if you want to play safe, you will need some kind of a semaphore
variable that the two handlers could use so that only one of them actually
handles the interrupt in any given case.

The DPMI spec says that 3 *software* interrupts are special, in that they
also get reflected to a protected-mode handler.  These interrupts are: 1Ch
(the timer tick interrupt), 23h (Keyboard Break interrupt), and 24h (Critical
Error interrupt).  This means that, to catch these interrupts, you need to
install a protected-mode handler only.  Unlike hardware interrupts, it
doesn't make sense to install dual RM and PM handlers for these software
interrupts.  In particular, Windows will call both RM and PM handlers if you
install both, so you effectively wind up handling the same interrupt twice.

For examples of installing and using hardware interrupt handlers, see the
sources of the Allegro library, the sample code written by Bill Currie
<bill_currie@MAIL.TAIT.CO.NZ>, the Sound Blaster interrupt-driven functions,
the `mkkbd' package, and the `libhw' library, described under sample DJGPP
packages in Section 22.3.  Alaric B. Williams <alaric@abwillms.demon.co.uk>
has written a tutorial on interrupt handling
(http://www.abwillms.demon.co.uk/prog/djints.txt).

The file `src/libc/crt0/crt0.S' in the DJGPP library sources, `djlsrNNN.zip',
is one example of the subtleties involved with installing a real-mode
interrupt handler.

---------- Footnotes ----------

(1) Locking a region of memory means that this region should be always
present in RAM.  Usually, the virtual-memory mechanism is allowed to page
regions out of RAM when it needs to load another region that is not loaded.
This happens if the program uses more memory than what is physically
available to it.  When a program needs to access an address that isn't
currently in RAM, the operating system will look for some memory region that
wasn't accessed for quite some time, and replace it with the block that needs
to be accessed now.  Locking a region prevents that region to be paged out,
for as long as the program runs.

18.10 Should I use _go32_XXX or __dpmi_YYY functions?
=====================================================

**Q*: In v1.x I was used to the `_go32_...' functions, but now comes v2 which
also has `__dpmi_...' functions.  Are there any differences between these two
varieties?*

**Q*: Do I need to convert my old v1.x code to use the new `__dpmi_...'
functions?*

*A*: These two groups of functions have different functionality, so don't
just substitute the new ones for the older ones, because it usually won't
work!  The new `__dpmi_...' functions are just bare-bones wrappers of the
DPMI API calls (see DPMI Specification in Section 22.5), generally unsuitable
for use with handlers written in C, whereas the old `_go32_...' functions are
intelligent helper routines which only make sense if your interrupt handlers
are C functions.  They save all the registers on the stack (to be restored
before return to caller), and set up DS, SS, and ES registers as GCC assumes
in the code it produces for a C program.  If these assumptions are wrong, the
C functions called by an interrupt handler will crash miserably.

The problem with the `_go32_...' functions is that they don't lock all the
code and data they (and your handlers) use, so they can crash on memory-tight
machines and thus aren't suitable for production-quality code.  But they are
certainly useful in the initial stages of writing and debugging code that
hooks hardware interrupts, and for migrating existing v1.x code to v2.  Some
of the old names were just `#define'd to the new names where the
functionality is identical.

The bottom line is that it shouldn't be necessary to convert your code for it
to work at least as well as it did in v1.x; but if you want it to be more
stable, you should rewrite your handlers in assembly and use the new
`__dpmi_...' functions (see How to install a hardware interrupt handler in
Section 18.9).

18.11 Hardware interrupt hooking has its subtleties
===================================================

**Q*: I did all the above, but my program occasionally still hangs...*

**Q*: From time to time my program crashes with a message "Page Fault in
RMCB".  What's that?*

*A*:  Hooking interrupts in DJGPP (and in protected mode in general) has a
few subtle aspects.  In general, hardware interrupt handling in DJGPP v2.x is
rock solid *if you play by the rules*.  Unfortunately, the rules are a bit
tricky.

One cause of your problems might be that your interrupt handler or some
memory location it uses get paged out because of the virtual memory
mechanism, or because your program spawned a child program.  In that case,
the interrupt might cause a call to a non-existent service routine, with the
obvious results.  You should lock all the memory pages that your handler
accesses by calling the `__dpmi_lock_linear_region' library function.  This
also means in practice that you should write your handler in assembly, as
described in how to set an interrupt handler in Section 18.9, above.  You can
disable virtual memory, or put `_CRT0_FLAG_LOCK_MEMORY' into
`_crt0_startup_flags' to make sure nothing is paged out (but then your
program might not have enough memory to run, unless you run on
memory-abundant systems).

When CWSDPMI detects that your handler accesses memory that is not locked, it
aborts your program with a message saying "Page Fault in RMCB".  This can
happen even if your program installs a callback for some real-mode service,
like the mouse callback, as well as if you install a hardware interrupt
handler; in both of these cases you need to lock all the memory touched by
your handler or by functions it calls.  CWSDPMI aborts your program if your
program attempts to page while an interrupt handler or a real-mode callback
are active, because paging uses DOS file I/O.  Since DOS is non-reentrant, if
the hardware interrupt handler was called in a middle of another DOS call,
paging could badly damage your hard disk(1).  By refusing to page in these
cases, CWSDPMI ensures the stability of your system and integrity of your
files.  You pay for that stability by having to lock all code and data
touched by the handler.

Another problem might be that the hardware peripheral you use generates a lot
of interrupts.  Due to specifics of hardware interrupts handling in protected
mode, there is a substantial overhead involved with reflection of interrupts
between real and protected modes.  For instance, on a 486DX/33 this
reflection might consume up to 3000 clocks; on a 386SX/16, even a 1KHz clock
might eat up 1/2 of available cycles.  One user reported that a 120 MHz
Pentium will be able to service up to 45-50K interrupts per second before
exhausting its CPU resources, and a 486DX/50 is capable of about half that
number.  If your hardware fires too many interrupts, your CPU might not be
able to keep up.  A good rule of thumb is to consider 10KHz as the breaking
point, if your program needs to do something non-trivial besides servicing
interrupts.  If you are beyond that interrupt rate, consider reducing the
interrupt frequency, or move some of the processing done inside the interrupt
handler to some other place.  Use a ring-0 DPMI server such as CWSDPR0 or
PMODE/DJ (of these two, the latter is the faster one) which don't swap
interrupt stacks--this will reduce the overhead of the interrupt reflection
to some degree.  If your handler is written in C, write it in assembly and
make sure it doesn't chain.  And most important--make sure your program keeps
the processor completely in protected mode while handling high-frequency
interrupts: avoid unnecessary library calls, disk I/O, BIOS calls, and
anything else that could generate a mode switch.  For example, using BIOS
services to wait a certain period of time while interrupts come in is clearly
a bad idea.  Preventing the program from paging (by installing enough
physical RAM and using memory efficiently) will also help keeping the CPU in
protected mode, since paging is done by calling DOS in real mode.  By keeping
your processor in protected mode as much as you can, you avoid the expensive
mode switches when the interrupts are reflected to your PM handler.

If all that still doesn't help, install a real-mode handler.

Some losing memory managers, notably EMM386, were reported to induce a high
interrupt handling overhead.  In one case, a user reported an increase in the
maximum interrupt rate his program could support from 2 KHz to 6 KHz after
uninstalling EMM386.

Still another possibility is that you use a non-default `sbrk' algorithm in
your program.  Check if the header file `crt0.h' is included anywhere in the
program, and if so, if the `_CRT0_FLAG_UNIX_SBRK' bit in the
`_crt0_startup_flags' variable is set by the program.  If it is, then a
hardware interrupt which happens at the wrong time could crash your machine,
especially if you run under Windows 3.X.

You should also keep in mind that the DPMI server can decide to handle some
of the interrupts itself and not pass them to your program, although this is
rare.  For example, Windows 9X won't pass the `Ctrl-Alt-Del' combination to
your keyboard interrupt handler, but will rather act on it itself; QDPMI
sometimes processes `Ctrl-C' keypresses so that your program never sees them,
etc.  Sometimes, but not always, you can change some configuration option to
make some keys get to your handler (e.g., the Alt-TAB setting on the
Windows3.X `.PIF' file).

If the above still doesn't explain your problem, then post your code on the
DJGPP mailing list <djgpp@delorie.com> or comp.os.msdos.djgpp news group,
tell there how it fails and somebody will usually have a solution or a
work-around for you.

---------- Footnotes ----------

(1) Actually, it is possible to avoid reentrancy problems in interrupt-driven
programs: programs known as TSRs ("Terminate and Stay Resident") have been
doing that for years.  But doing so requires hooking and monitoring many DOS
and BIOS interrupts, to know when it is safe to page.  If CWSDPMI would use
these techniques, it would take much more DOS memory to load and run.  It
would also need to be updated with every new DOS release, since some of the
internal DOS structures it would need to track change their address and/or
layout with new versions of DOS.

18.12 How to read and write ports
=================================

**Q*: I need to read from and write to PC ports, and I'm accustomed to using
the `inp' and `outp' functions.  But I hear they aren't available in DJGPP?*

*A*:  They are in v2.x.  Just  `#include <pc.h>'  and you get their
prototypes.  The functions themselves are in the default library.  Note that
there are also size-specific versions for byte- word- and dword-long access
(e.g., `inportl' for reading a 32-bit dword), as well as functions to
read/write sequences of bytes and words, like `inportsb' and `outportsw';
these are DJGPP-specific.

18.13 Inline Assembly code with GCC
===================================

**Q*: I am used to writing inline assembly with Borland C, but can't figure
out the way to do it with GCC...*

**Q*: How can I reference C variables from my inline assembly code?*

*A*:  GCC has extensive inline assembly facilities.  They allow you to
specify everything other compilers let you (like the registers where GCC will
put specific results), but in a way that doesn't interfere with the
compiler's optimizations of the C code that includes inline assembly.
Because of this flexibility, the syntax of the inline assembly code is very
different from the other DOS-based compilers.  The GCC on-line docs describe
these facilities in detail; to read the relevant sections, type this from the
DOS prompt:

       info gcc "C Extensions" "Extended Asm"

(Note the quotes: they are important.)  You will, of course, need that the
stand-alone Info reader be installed on your system for the above command to
work.  If it is not already installed, get the file `v2gnu/txi312b.zip' from
the DJGPP distribution and install it.

If you read this FAQ via WWW, you can also read about the GCC inline assembly
extensions with your Web browser
(http://www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_86.html#SEC89).

Brennan Underwood <brennan@rt66.com> has written a tutorial on using inline
assembly (http://brennan.home.ml.org/djgpp/djgpp-asm.html), which is another
valuable resource on this issue.

18.14 Using DMA with DJGPP
==========================

**Q*: How do I use DMA with DJGPP programs?*

**Q*: I want to use DMA, but I don't know how to get the physical address of
the buffer I allocate for that purpose.*

*A*:  The main problem in using DMA with DJGPP is how to get the physical
address of a buffer, which is required to program the DMA controller.  In
protected-mode environment, memory addresses that your program manipulates
are actually offsets from the base address of the data segment.  You can
obtain the base address of the data segment by calling the
`__dpmi_get_segment_base_address' library function and add it to the address
of your buffer, but the resulting address is a logical address, translated
into a physical address by the memory-mapping unit which is part of the CPU.

You have two alternatives to get the physical address of your buffer:

   * Allocate the buffer in conventional memory, below the 1MB mark.  This
     memory is mapped 1:1 by all DPMI servers, so the linear address is equal
     to the physical one.  You can allocate a buffer in conventional memory
     using the library function `__dpmi_allocate_dos_memory'.

     This method has a disadvantage of using conventional memory which is at
     a premium, and is therefore generally ill-suited for large DMA buffers.

   * Use "VDS", the Virtual DMA Services API.  This is implemented by a bunch
     of functions of interrupt 4Bh; see Ralf Brown's Interrupt List for the
     details.  This method has a drawback that it needs a real memory
     manager, such as `EMM386' or `QEMM', to run, since only memory managers
     and Windows support the VDS API.  In other words, if you use VDS, your
     program won't work on a system where CWSDPMI(1) is used as the DPMI
     server, allocating memory by raw XMS calls or via HIMEM.

---------- Footnotes ----------

(1) CWSDPMI has an experimental VDS support in its sources, but the
distributed binary was compiled without it.  Contact Charles Sandmann
<sandmann@clio.rice.edu> if you want to try to enable VDS support in CWSDPMI.

19. Legal Aspects
*****************

  This chapter answers some questions about various legal aspects of writing
programs with DJGPP.

19.1 Legal (un)restrictions on DJGPP applications
=================================================

**Q*: Can you explain in plain English the legal restrictions of distributing
programs compiled with DJGPP?*

**Q*: Can I write commercial programs with DJGPP?*

*A*: In most cases, you don't have to worry about any legal restrictions when
you compile your programs with DJGPP.  You only need to include information
on how to get DJGPP in the documentation of your products.

Using the GNU C/C++ compiler doesn't make your programs subject to *any*
restrictions.  The C library which comes with DJGPP is *free* (unless you
change the library sources, see below), which means you are free to use the
stock `libc.a' in any way you like (but please try to comply with basic rules
of courtesy in Section 19.2.)

Some functions from the DJGPP C library are under the BSD copyright (their
sources were taken from the Berkeley Software Distribution of Unix).  One of
these functions is `malloc', which is by default linked into every DJGPP
program (the startup code calls it), the others are time-related functions
such as `time', `ctime', and `asctime', and also `qsort' and `random'.  The
BSD copyright requires that your binary distribution displays the following
acknowledgment somewhere in the docs, and in all ads that mention the
features and/or use of your software:

      This product includes software developed by the University of
      California, Berkeley and its contributors.

So, if you write C programs and link them with the stock version of the DJGPP
library, you only need to tell your recipients how to get the latest versions
of DJGPP, mention the BSD blurb in your docs, and have absolutely nothing
else to worry about.

The basic C++ `iostream' class library (`libiostr.a') and the Standard
Template Library (`libstdcxx.a') which come with DJGPP allow you to use them
binary-wise (i.e., without changing library sources) in your C++ programs
*without restrictions*, unless you compile your programs with a compiler
other than Gcc (which won't happen if you work with DJGPP).  So C++ programs
linked with `-lstdcxx' and/or `-liostream' switches are also free from any
restrictions.

Only the library of additional GNU C++ classes (`libgpp.a') requires that you
provide your customers with source or object code of the application, so they
could relink the application with future or modified versions of the C++
library.  However, this library is deprecated and chances are most C++
programs won't use it.  (If you intend to distribute commercial programs
linked with the `libgpp.a' library, you are strongly advised to read the GNU
Library General Public License which comes with the library, for rigorous
definition of its terms.)

Two GNU packages, `Flex' and `Bison', are also special in that using them to
produce your programs doesn't place your programs under GPL or LGPL.  In
other words, lexers produced by `Flex' and parsers produced by `Bison' do
*not* imply GPL/LGPL.

If you *do* use in your program any of the FSF sources that fall under
GPL/LGPL (like some of the GCC's sources, or the GNU `getopt' or `regex'
packages which come with many GNU programs), then you must comply with the
terms of GNU licenses when distributing your programs; in this case your
entire application becomes GPL.  If that is unacceptable to you, consider
using the versions of `regex' and `getopt' from the DJGPP C library (which
are not as powerful, but are free from any restrictions).

You may ship any of the utilities developed specifically for DJGPP (e.g., the
floating-point emulator `emu387.dxe' or the DPMI host `cwsdpmi.exe') and the
C library, *as distributed by DJ Delorie*, with your program with no other
requirement besides telling your customers how to get DJGPP for themselves.

If you do change the sources of either the C library or the utilities
distributed with the `djdev' package, they, and the programs developed with
them, immediately fall under the GPL, the GNU License.  In practice this
means that you cannot distribute any binaries made with such a patched
version of `libc.a' without offering the recipient full sources, including
your own sources.  However, if you find bugs in the library or the utilities
and submit your patches to DJ Delorie, DJ allows to freely use and
redistribute patched utilities and binaries made with the patched version of
`libc.a' (even if no official DJGPP version was released with your patches
yet).

For the precise legal terms of DJGPP distribution, see the file `copying.dj'
via the Web (http://www.delorie.com/djgpp/dl/ofc/simtel/v2/copying.dj)
(latest versions of the `djdevNNN.zip' package might also include it).

Note that the above says nothing about the legal aspects of contributed
packages, like `GRX' and others; you will need to read their docs to find out.

19.2 Legal restrictions of DJGPP utilities and libraries
========================================================

**Q*: Can I redistribute djgpp, and if so, how?*

**Q*: I run a business that sells shareware for distribution costs.  Can I
include djgpp on my CD-ROM?*

**Q*: I want to include djgpp in a product that happens to need a compiler
provided with it.  Can I do this?*

**Q*: Is DJGPP public domain software?*

**Q*: Is DJGPP shareware?*

*A*:  DJGPP is *not* public domain, neither is it shareware (you *don't* have
to pay a license fee to use DJGPP).  Parts of DJGPP (the compiler and some of
the development tools) *are* GNU software, so you must comply with GNU GPL if
you distribute those parts (usually, you won't need to distribute them,
because they are freely available to everyone).  A small part of the C
library is taken from the Berkeley BSD sources, and is therefore in public
domain.

Other parts of DJGPP, which include most of the C library, the free DPMI host
CWSDPMI, and some of the utilities, are copyrighted, but in a way that allows
you to use them freely and without restrictions.  The copyright that covers
these parts of DJGPP is GPL, the GNU License, but with a special exception:
if you distribute the utilities unmodified, or build programs with the
unmodified library, the GPL does not apply.

*Compliance with GPL is therefore all you are legally required to consider*
when you redistribute DJGPP itself (as opposed to your programs compiled with
DJGPP).  However, based on many years of experience of DJGPP distribution, DJ
Delorie requests vendors which distribute DJGPP to follow some additional
rules.  These rules are generally meant to provide a better service to the
DJGPP user community:

   * You must redistribute DJGPP as a whole, with all its parts, including
     the sources to utilities and libraries that are part of DJGPP, unless
     other arrangements are first made with DJ Delorie <dj@delorie.com>.

   * Please make a good faith effort to stay up to date with the latest DJGPP
     versions, so people don't get old versions with bugs that are long ago
     solved, or, worse still, versions that are no longer supported.

   * You *must* call it *DJGPP* and nothing else.

   * You may *not* take credit for it, and you must *not* remove any notices
     in DJGPP that give credit to those who worked on it.

   * You must tell the recipient how to get the latest version off the
     Internet, or at least how to find out what the latest version is.
     DJ Delorie gets a lot of questions from people who got old versions from
     vendors and don't realize that they're way out of date.

In addition, it would be a courtesy to inform DJ that you are including DJGPP
in your product, in case this information is obsolete.  A token sample of
your distribution would be nice also.

Note that the above are *not* legal restrictions (the latter are described in
the file `copying.dj' mentioned in the previous section), they are
*recommended guidelines* for redistributing DJGPP.  These guidelines are
based on many years of experience and are generally meant to make it easier
for your clients to use DJGPP and get support from its developers.  Vendors
who do not follow these guidelines could risk public humiliation, verbal
abuse, and boycott by the DJGPP community, but not legal action.

Note also that if you make source-level changes to DJGPP library or
utilities, the changed software falls under the GNU License, GPL, unless
these changes are made to fix bugs, and provided that you also submit all
such bug-fixes to DJ Delorie for inclusion in a future DJGPP release.

20. Getting Help
****************

  This chapter tells you how to get answers to questions you didn't find in
this FAQ, by asking them on DJGPP-related forums.

20.1 Don't post DJGPP-specific problems to GNU News groups
==========================================================

**Q*: I post my problem to gnu.gcc.help news group, but don't get any
answers...*

*A*:  Is your problem likely to be special to the DJGPP port or to the DOS
environment?  If so, don't post to GNU Usenet groups, but to
comp.os.msdos.djgpp news group or to the DJGPP mailing list
<djgpp@delorie.com>.  People who read GNU News groups usually neither know
nor care about DOS-specific problems.  Post there only if the problem seems
to be generic to one of the FSF utilities.  For most problems, this can be
deduced only after either tracing a problem in the source code or testing it
on some non-DOS platform.  As a general rule, always post to the DJGPP forums
first.

20.2 How to post to the mailing list
====================================

**Q*: How do I post to the DJGPP mailing list?*

*A*:  Send mail to the list address <djgpp@delorie.com> as if it were a
person.  Please use the mailing list only if you cannot access the DJGPP news
group, because reflecting the mail to and from the mailing lists incurs
additional load on the DJGPP server.  The DJGPP news group,
`news:comp.os.msdos.djgpp', is two-way gated to the mailing list.  This means
messages posted to either the mailing list or the news group will appear on
both (once, let's hope ;-); you can read either one and post to either one,
and everybody eventually sees everything.  So please don't post to both the
news group and the mailing list.

The gateway works on DJ's server, and has a very strict anti-spam filter
which prevents spam from getting into the news group; it also has an
additional keyword-based ant-crap filter that doesn't pass spam to the
mailing list.  The entire traffic ends up in the mail archives on the DJ's
Web server within 24 hours, and is available for searching
(http://www.delorie.com/djgpp/mail-archives/).

If you have a Usenet feed, now is the time to consider unsubscribing from the
mailing list and switch to reading the news group instead, so that the load
on the list server will get lower.

20.3 How to become a subscriber to the mailing list
===================================================

**Q*: How do I subscribe to the DJGPP mailing list?*

*A*:  Send mail to the list server <listserv@delorie.com> (NOT to djgpp@!!),
leave the subject line empty and in the body write:

      subscribe <your e-mail address> djgpp

If you only want to receive announcements of new versions and ported
software, but don't want to see any other DJGPP mail traffic, subscribe to
the `djgpp-announce' by sending message to the list server
<listserv@delorie.com> which says so:

      subscribe djgpp-announce

(Note: no email address when subscribing to the `djgpp-announce' list!)

The announcements which go to `djgpp-announce' get reflected to `djgpp', so
you don't need to subscribe to both these lists.

The DJGPP mailing list is available in the daily and weekly digest forms.  To
subscribe to one of these, send this one-line message to the above list
server:

      subscribe <your e-mail address> djgpp-digest-daily

or

      subscribe <your e-mail address> djgpp-digest-weekly

Some mailers reject messages with too large size, so you might have trouble
with the weekly digest.  If you subscribe to it and don't get the digest, try
the daily one instead, or switch to another mail software.

You can also subscribe to DJGPP-related mailing lists through DJ Delorie's
WWW server (http://www.delorie.com/mailing-lists/subscribe.html).

Note that you don't have to subscribe to the djgpp mailing list if you don't
want to get all the traffic in your mailbox (typically, about 30 messages per
day).  You can ask questions on the list even if you are not a subscriber,
because people usually answer both to your e-mail address and to the list
(well, actually, the mailer program does it automatically and most people
don't bother to change that).  If you want to be sure the mail gets to you
directly, say in your message that you don't subscribe to the list, and ask
people to answer directly.  Be sure to provide a valid return address (remove
any anti-spam, if you use one).

20.4 How to unsubscribe from the mailing list
=============================================

**Q*: Whew!  There's too much traffic on the djgpp mailing list (at least the
SysAdmin glaring over my shoulder thinks so... ;-).  How do I unsubscribe
myself?*

**Q*: I've been trying for days to unsubscribe from the djgpp mailing list.
What am I doing wrong?*

*A*:  You should send your unsubscribe messages to the list server
<listserv@delorie.com> *(not djgpp@delorie.com!)*, with the contents being
just this:

      unsubscribe <your e-mail address> djgpp

When you unsubscribe, that stops *new* messages from being sent to you.
Messages that are already in the mail queues of various mail programs between
the DJGPP list server and the machine where you receive your mail--cannot be
stopped.  Therefore, allow some time before you decide that your unsubscribe
message didn't work.  In extreme cases, when one of the machines that are
forwarding mail to you is down, you can get the messages up to 5 days after
you've unsubscribed.

If you think you have waited enough and the messages still keep coming, write
to listserv administrator <djgpp-request@delorie.com> and ask him to help you.

You can also unsubscribe yourself from any DJGPP-related mailing list through
DJ Delorie's WWW server
(http://www.delorie.com/djgpp/mailing-lists/subscribe.html).

Recently, DJ has added a mail archive browser to his Web site.  With this
tool, you can list and read the messages by year, month and day, as well as
search the last few days for something you might have missed.  This service
is available via World-Wide Web
(http://www.delorie.com/djgpp/mail-archives/browse.cgi).

21. Version 2 vs v1.x
*********************

  This chapter is for those who want to know where are the latest updates for
DJGPP software, and what's new and improved in them.  It also explains the
differences between DJGPP v1.x and v2, for those who are still using DJGPP
v1.x and want to know more about v2 while they consider switching.

21.1 New features in DJGPP v2
=============================

**Q*: What exciting new features will I find in v2 as opposed to v1.x?*

*A*:  DJGPP v2.x is a DPMI-only environment, and it includes a free DPMI host
for those who don't have another DPMI provider installed.  In addition, v2
features the following major improvements upon v1.1x:

   * much faster extender (the free DPMI host) and library functions;

   * very low memory footprint of the DPMI host below 640KB;

   * the DPMI server is loaded only once: no more problems with spawning child
     programs (e.g., almost unlimited recursive Make's);

   * ANSI- and POSIX-compliant libraries and header files, which should make
     porting Unix programs a lot easier;

   * support for signals;

   * 387 emulation under DPMI;

   * graphics which works in *any* setup, including under Windows;

   * fixes of many bugs in hardware interrupts' and mixed-mode programming
     support;

   * support of long filenames on Windows 9X;

   * ability to build all of DJGPP without commercial products (like Turbo C
     required to compile go32 in v1.x);

If you want to help in further v2 development, check out the list of features
which have yet to be done and volunteer to implement some of them.

21.2 DJGPP environment in v2.x
==============================

**Q*: There's been this talk about v2 and about `go32' going away in that
version, but I'm confused on what the new setup will be.  Could you clarify
the details of this change?*

*A*:  In v1.x of DJGPP, the `go32' extender was responsible for the following:

   * Loading and running the application in protected mode.

   * Managing protected-mode and virtual memory.

   * "Extending DOS" so that protected-mode programs could issue calls to
     real-mode DOS and BIOS services and still run.  (This is mostly done by
     switching to real mode and reissuing the interrupt, but some services
     require special handling by the extender.)

   * Handling of hardware interrupts which happen while the CPU is in
     protected mode.

   * Loading 387 emulator (if required).

   * Loading the graphics driver and working with VGA bank-switching to create
     an illusion of a linear video memory.

   * Command-line and wild-card expansion in a Unix-like fashion.

In v2.x, a minority of these functions are done by a DPMI host, which is a
memory-resident software required to run protected-mode programs under
MS-DOS.  There are a few commercial DPMI hosts (like Quarterdeck's `QDPMI',
Qualitas `386Max', MS-Windows 3.X and Windows 9X, OS/2, even Linux), but
DJGPP v2 comes with a free DPMI host called `CWSDPMI' for those who don't
have one already.  Loading the application into protected-mode memory (a
function done in v1.x by `go32') is handled by a 2KB-long real-mode stub
which runs at start-up, before the application's `main' functions is called
(the stub will also load `CWSDPMI' if no other DPMI host is detected).  All
the other custom code required to process BIOS- and DOS-related calls from
protected-mode is now built into the library functions which your program
calls, so there is no need for a special extender, because the application
just issues DPMI calls serviced by the DPMI host.

`CWSDPMI' can be loaded as a TSR, even loaded `HIGH' into the HMA/UMB, which
will make applications load much faster.

21.3 Why are new DJGPP versions released so slowly?
===================================================

**Q*: It's more than a year since DJGPP vX.Y was released.  Why won't you
guys upload a new version in all this time?*

**Q*: I've been suffering from this bug for months on end!  You know there's
a bug, 'cause I told you so ages ago.  So why in the world didn't you fix
that in a new version??*

*A*: DJGPP is developed by volunteers on their free time.  This sets both the
schedule of new DJGPP releases and the DJGPP development agenda: they are
determined by what those volunteers think is important and doable, and by the
amount of free time they can devote to DJGPP-related work.  Since the work of
the development team is given away for free, you cannot demand that they do
something they've decided not to do just yet.  The only way to influence
DJGPP development is to make your own contribution, by fixing a bug or adding
a feature, and then submit your patches to DJ Delorie <dj@delorie.com>.

You don't need to look for a large project to make your contribution.  The
best way to start being involved with DJGPP development is to fix any small
and minor problems you see, right when and where you see them.  Even bugs and
inaccuracies in the DJGPP documentation, like the `libc.inf' Info file, are a
good thing to begin with.  DJ Delorie says that if everybody would correct
every small bug they see, we would run out of bugs very fast.

When you submit a bug report or code that implements a new feature that you'd
like to add to DJGPP, be prepared to withstand some scrutiny and peer review
from the other participants of the DJGPP development team.  You might hear
various comments, from critique of your code and design decisions to
questions why your changes are at all needed, and even requests to submit the
changes in certain unified format (see instructions for submitting changes in
Section 22.2).  Please be ready for that review process and don't take it as
a rebuttal.

21.4 Where to find the best C library for DJGPP
===============================================

**Q*: There's been quite some time since the last DJGPP release.  Where can I
get all the latest stuff where the bugs are fixed?*

**Q*: I have heard rumors that there's a better C library for DJGPP available
from the net.  Where is it?*

*A*: New versions of most parts of DJGPP are released quite regularly.  For
example, DJGPP ports of most GNU packages are generally released short time
after a new version of every package becomes available from the GNU FTP
sites.  So for many DJGPP packages, a new release should usually be available
real soon, just stick around a bit.

The single most important component of DJGPP tool-chain that might suffer
from long release schedule is the `djdev' package.  This includes the C
library, `libc.a', which was written specifically for DJGPP, and some
DJGPP-specific development tools, like `redir' and `symify'.  However, the
latter are usually stable and don't need too much fixing.

A full release of `djdev' is a lot of work, so DJ Delorie decided not to make
interim releases (experience from v1.x development shows that such interim
releases also generate confusion and are hard to maintain).

In general, you are advised to constantly improve your C library by fixing
any bugs in the library sources and replacing old modules with fixed ones.
All this takes is to edit the relevant source file, compile it, and put it
into the library.  For example, assuming you have made a source-level change
in a file called foo.c, here's how you update your library:

       gcc -c -O2 foo.c
       ar rvs c:/djgpp/lib/libc.a foo.o

(This example assumes that DJGPP is installed in the `C:\DJGPP' directory; if
not, you will need to change the pathname of `libc.a' accordingly.)

Patching the library like that requires that you download the DJGPP library
sources, `djlsrNNN.zip' (where `NNN' is the version number).  That file
includes sources to all the DJGPP functions and utilities, and you can
extract them as the need to edit them arises.

Bug reports regarding the library and patches to fix them are posted from
time to time to comp.os.msdos.djgpp news group.  In addition, the DJGPP
bug-tracking system (http://www.delorie.com/djgpp/bugs/), stores many known
bugs and the patches required to solve them.  You can use these resources to
find solutions to known bugs.  Patches are applied using the `patch' utility
which is available from the DJGPP sites
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/pat25b.zip).

For those who don't want to mess with patching library sources, but still
want their library to be as bug-free as possible, a few generous DJGPP users
maintain a site where you can find those patches already applied for you and
ready to be downloaded.  The patched libc at that site includes bugfixes and
improvements that were tested by experienced DJGPP users, so they are
relatively safe.  You can either download one or more individual patches and
then put them into your library, or download the entire `libc.a' with all the
patches.  Every patch has a short description, in case you'd like to decide
whether it's for you.

The patched library was created by Tom Demmer
<Demmer@LStM.Ruhr-Uni-Bochum.De>. Nate Eldredge <nate@cartsys.com> is the
current maintainer, and the space available for FTP is courtesy of A. Sinan
Unur <sinan.unur@cornell.edu>, on his server.  The patched library is
available via WWW (http://www.cartsys.com/eldredge/djgpp-patches.html) and by
ftp (ftp://www-leedr.arme.cornell.edu/pub/djgpp-patches/).  Be sure to read
the file `ftp.message.txt' when using the FTP server above.  The file
`README' explains how the patched library can be downloaded and used.

The above site also includes two additional versions of the C library: one
compiled with the `-g' switch and the other compiled with the `-pg' switch to
GCC.  These are handy if you need to debug library functions and profile
them, respectively.

22. Miscellany
**************

  This chapter is a hodgepodge of questions which don't belong to any of the
other chapters.

22.1 Unzipping gppNNb.zip complains about g++.exe
=================================================

**Q*: When I unzip the C++ compiler distribution in gppNNb.zip, the unzip
program complains about something called `g++.exe'.  What should I do?*

*A*: If you install DJGPP on anything but Windows 9X, just ignore that error
message and use `gpp.exe' or `gxx.exe' to compile C++ programs.  `g++.exe' is
an invalid file name on DOS, but is allowed on Windows 9X.  It is included
for compatibility with Unix, where the C++ compiler is called `g++'.  All
`g++.exe' does is just to run `gxx' or `gpp'.  So you don't lose much by not
having it.

If you *are* installing DJGPP on Windows 9X, find an unzip program which
supports long file names and unzip the files again.  Make sure that the DJGPP
long file names support (a.k.a. LFN) is enabled, otherwise DJGPP programs
such as Make won't be able to invoke `g++'.  To enable LFN support, set
`LFN=y' in the environment.

22.2 How to change a DJGPP package?
===================================

**Q*: I want to change cc1.  How do I do this?*

**Q*: How do I fix a bug/add a feature to one of the DJGPP programs?*

**Q*: How should I produce patches for DJGPP programs I want to submit, and
to whom should I submit them?*

*A*:  First, get the sources.  These are called `*s.zip' in the DJGPP
distribution.  The C Library sources are in `djlsr201.zip'.  Some sources are
too big, and might be split into multiple zips, all of which must be unzipped
to get a complete source distribution, like this:

      em1934s1.zip
      em1934s2.zip
      em1934s3.zip

All sources are shipped in ready-to-build form.  Any diffs that come with the
source distribution, like the files called `DIFFS', have already been
applied, and any configuration scripts and/or batch files have been run.

Next, try to build the program without changing it.  Look for a file called
`README.dos' or `README.djgpp': it should explain the build procedure and
list any optional packages you need to install for that.

If such a `README' file is unavailable, you will have to poke around and
figure things out for yourself; here are some hints to help you out:

   - A file called `Makefile' or `makefile' probably means you could just
     type `make'.

   - Some packages will have a `CONFIGUR.BAT' file, possibly in a
     subdirectory called `djgpp/' or `pc/'; if so, run it first.

   - If there is a `MAKE.BAT' file, run it; if not, look for a file named
     `MAKEFILE.DJ' or `MAKEFILE.DJG'; sometimes these will be in a
     subdirectory called `dos/', or `msdos/', or `pc/'.  If there is such a
     file, then type, e.g., `make -f makefile.djg', if not, just say `make'
     and see what happens.

The reason for an apparent lack of a standard here is that different packages
were ported to DJGPP by different people, as best as they saw fit.

After you've successfully built the program, make your fixes and build the
program the same way you did before.

Note that generally to build these programs, you must have the GNU Make
program (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/mak377b.zip),
installed, and some makefiles require that you install additional development
utilities, like the SED editor
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/sed302b.zip).  Sometimes the
makefiles won't even run under `COMMAND.COM' (they require a smarter shell).
In that case, either get a better shell, or convert the makefile to be
runnable by `COMMAND.COM', or do the required steps manually.  If the
Makefile is too complex for you and you can't figure out what are the
necessary commands, invoke make with `-n' switch and see what it would have
done.

If your machine lacks floating-point hardware (like a 386 without a 387, or a
486SX), then you should know that current versions of GNU Sed and GNU Make
issue floating point instructions, so you will have to make provisions for
loading an emulator, see above, FP Emulation in Section 11.1.  The port of
Make 3.75 and later can be built so that it doesn't issue FP instructions,
but you will have to get the sources and recompile Make first, as the stock
version wasn't configured in that way.

If you think that you found a bug in one of the programs or libraries written
for DJGPP (e.g. the C library, CWSDPMI, symify, etc.) be sure to check the
list of known bugs (http://www.delorie.com/djgpp/bugs/).  If your bug is not
there, you can later submit it to the bug-tracking system.

Before you submit a bug report, please make every effort to verify that your
bug is not caused by incorrect usage, or by problems in your DJGPP
installation.  Reports such as "All DJGPP programs crash" or "I cannot
compile any program" are clearly not bugs, because these things work for many
hundreds of DJGPP users every day; so either your system setup is messed up
or you invoke programs incorrectly.

If you can investigate the cause of the bug and find a solution that makes it
go away, submit a bug report with all the details.  If you cannot find the
cause(s), I suggest posting your problem description to the news group and
asking people to verify that it is indeed a bug, before you submit a bug
report.  The bug-tracking system includes a list of all known bugs, many of
them with solutions or work-arounds; please check them before creating a new
bug report.

Patches to DJGPP programs and ports should be sent to the person who
maintains the relevant package.  Patches for the C library, utilities and
other software which comes with the `djdevNNN.zip' distribution should be
sent to DJ Delorie <dj@delorie.com>.  If you don't know who maintains a
particular package or port, post the patches to comp.os.msdos.djgpp news
group, since the maintainer is most probably reading that group.

To generate a patch, run the `diff' program (from GNU Diffutils,
`v2gnu/dif271b.zip') on the old and the new version of a source file.  For
example:

      diff -c src/libc/dos/dos/int86.old src/libc/dos/dos/int86.c >int86.dif

The file `int86.dif' created this way should be sent to the maintainer, with
a short description of the problem it solves.  It is a good idea to run the
patch file through `DTOU' (a utility which comes with DJGPP and converts
DOS-style CR-LF pairs into Unix-style newlines), since this makes the patch
work on Unix as well, in case the maintainer of the package in question does
that on Unix.

Observing the following guidelines when creating the patch will make your
patches easy to apply:

   * Always use the `-c' switch to `diff', and *never* use `-c' with an
     argument that is less than 3 (for example, do *not* use `-c2').

   * Invoke `diff' from the root of the DJGPP installation, i.e. from the
     directory where you keep the `DJGPP.ENV' file, and specify the files
     being compared with their pathnames relative to that directory.  This
     allows to concatenate related patches to several files, and apply the
     combined patch in a single run of the `patch' utility.

   * Always use *forward* slashes in pathnames.  Backslashes will work on
     DOS/Windows, but some packages are maintained on Unix machines, where
     `patch' doesn't understand backslashes.  In particular, DJ Delorie
     maintains DJGPP on a Unix box.

   * It is best to let the new version of the file have the exact pathname of
     the file, and rename the old to some other name like `foo.old' or
     `foo.bak'; see the example above.

   * Do *not* put together (on the same patch file) several unrelated patches
     for different problems: the maintainer might decide to apply only some
     of them, and could become confused which parts of the patch fix what
     problems.  Correct one problem at a time and then make a patch file for
     that problem alone; then correct another problem and generate a patch
     for that one; etc.

   * When you change the sources, try to preserve the programming style,
     including indentation, of the original.  In particular, DJ Delorie
     requests that the sources included in the `djlsrNNN.zip' distribution
     follow his distinct style (that style is quite obvious from the sources,
     but if you are unsure, ask DJ).

   * You should *never* use any switches that let `diff' ignore whitespace,
     like `-b' or `-w'.  In most cases, patches generated with these switches
     will fail to apply.

In addition, it would be mighty nice if every change in functionality were
accompanied by a suitable change in the relevant docs (e.g., for a patch to a
library function, edit the corresponding `.txh' file with its docs), although
you are under no obligation to do that.

22.3 Where to find sample DJGPP code or a package ported to DJGPP?
==================================================================

**Q*: Where can I find an example of XXXX / a package doing YYYY ?*

*A*: Salvador Eduardo Tropea (SET) <salvador@inti.gov.br> maintains a DJGPP
Web Ring page
(http://www.geocities.com/SiliconValley/Vista/6552/dlinks.html).  DJ Delorie
<dj@delorie.com> offers another very large collection of DJGPP-related links
(http://www.delorie.com/djgpp/dl/elsewhere.html).

Here is a list of places you might look into for examples of frequently
needed code fragments, or for packages people keep asking about:

   * Interrupt-driven support of peripheral devices and hooking hardware
     interrupts:

        - The Allegro library is an excellent place to look for code that
          install hardware interrupt handlers and handles several peripheral
          devices.

        - Alaric B. Williams <alaric@abwillms.demon.co.uk> maintains a
          library of utility functions and example handlers, useful for
          writing hardware interrupt handling code
          (http://www.abwillms.demon.co.uk/prog/index.html).

        - Bill Currie <bill@tanihwa.tssc.co.nz> wrote examples of interrupt
          handlers
          (ftp://ftp.delorie.com/pub/djgpp/contrib/sample-interrupt-handlers-v2.zip)
          which should get you off the ground if you need to write your own
          handlers.

        - Martynas Kunigelis <martynas.kunigelis@vm.ktu.lt> donated a
          tutorial and a working code that installs a handler for the
          hardware keyboard interrupt 09h
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/mkkbd3.zip) that
          can also serve as a good example of handling interrupts.

        - you can look at the latest version of Sound Blaster support library
          at Oulu
          (ftp://x2ftp.oulu.fi/pub/msdos/programming/djgpp2/sb05_dj2.zip) or
          on DJGPP server
          (ftp://ftp.delorie.com/pub/djgpp/contrib/sb05_dj2.zip); this is
          maintained by Joel Hunter <jhunter@kendaco.telebyte.net>.

        - check out the package available from SimTel.NET that hooks the
          timer interrupt
          (ftp://ftp.simtel.net/pub/simtelnet/msdos/c/pctime14.zip).

        - if you need a serial communications package, check out the SVAsync
          library (ftp://ftp.delorie.com/pub/djgpp/contrib/svasync.zip).

        - another package for serial communications, called BCSERIO, was
          written by Bill Currie <bill@tanihwa.tssc.co.nz>.  BCSERIO is
          available from Bill's home page
          (http://www.tssc.co.nz/~bcurrie/serio.zip).

        - if you need serial communications from programs that use the Allegro
          library, try DZComm, which is available from the `v2tk/allegro'
          directory on the usual DJGPP sites.

   * Network support libraries:

        - for TCP/IP, check out the WATTCP library, which is available from
          its home
          (ftp://dark.uwaterloo.ca/pub/wattcp/tcplib-dj200/tcplib-dj200.1.tar.gz),
          or from a Europe mirror
          (ftp://lab1.psy.univie.ac.at/pub/djgpp/tcplib/), it provides the
          TCP/IP sockets interface.  (I am told that you can safely ignore
          the warnings you get when compiling the package.)

        - as part of the DOS Lynx port done by DJ Delorie <dj@delorie.com>,
          he ported the WATTCP library as well; that port is available from
          DJ's server (ftp://ftp.delorie.com/pub/dj/lynx26s.zip).

        - programs which run on Windows 9X can use the Winsock services built
          into Windows to establish TCP/IP connections; a C++ interface to
          Winsock 1 was written by Dan Hedlund
          (http://triangle.dyn.ml.org/wsock/).

        - another Winsock library is `libsocket', originally developed by
          Indrek Mandre <indrek@warp.edu.ee>, currently maintained by R. Dawe
          <rd5718@bristol.ac.uk>.  The latest version (0.7.3, as of this
          writing) is available from the libsocket home page
          (http://libsocket.home.ml.org/), and via FTP from the DJGPP
          archives
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/lsck073b.zip).
          This currently doesn't support the newer Winsock2 VxD which is part
          of Windows 98.

        - yet another version of Winsock interface is available at Brennan
          Underwood's site (http://www.rt66.com/~brennan/djgpp/).

        - if you need to program an IPX interface, you can get started by
          downloading examples of IPX programming
          (http://www.rt66.com/~brennan/djgpp/jonipx.zip), and also read the
          IPX Web page (http://www.ladder.org/ddr/ipx.html).

   * Dynamically loaded code:

        - Check out the DLM (Dynamic Link Modules) environment for DJGPP,
          written by Ilya Ryzhenkov <orangy@inetlab.com>, available from the
          DLM home page (http://www.iis.nsk.su/orangy/dlm/).

        - A dynamic linker for DJGPP, called DLX, is available from the DJGPP
          sites
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/dkx291.zip).

   * X library:

        - the Xlibemu library (ftp://asterix.inescn.pt/pub/PC/X/) includes
          `Xt' and `Xmu' toolkits, a 3D version of the `AW' toolkit, a few
          demo applications (e.g. `xmine'), and can be used to compile
          `Tcl/Tk' and GNU Emacs with X support.  Xlibemu is based on X11R5
          and was originally developed by Antonio Costa
          <acc@asterix.inescn.pt> for DJGPP v1.x.  It is also available on an
          alternative site (ftp://ftp.dei.isep.ipp.pt/pub/pc/djgpp/etc/X/)
          and on the DJGPP server
          (ftp://ftp.delorie.com/pub/djgpp/contrib/xlibemu/).

        - there are also the Xlib and Xt libraries for the Quarterdeck's DV/X
          environment
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v1tk/qddvx102.zip)
          (you will also need qdlib102.zip and qdtkt102.zip from the same
          site).  This is also for DJGPP v1.x.

   * Ports of various GNU utilities not included in DJGPP:

        - Many of these are now part of DJGPP, so first look on SimTel.NET
          mirrors with rest of DJGPP
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/).

        - Marc Singer <elf@netcom.com> maintains a DJGPP port of RCS, the
          Revision Control System (ftp://ftp.netcom.com/pub/el/elf/rcsdos/).

   * GUI libraries:

        - SWORD (the System of Windows for the ORganization of the Desktop)
          is a Graphic User Interface library made with C++ objects, written
          and maintained by Eric Nicolas <nicolas@JUPITER.saclay.cea.fr>.  The
          latest version 2.50 is available from the v2tk directory
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/) as sw21_*.zip.
          SWORD is a powerful system for dedicated programmers, specifically
          designed to allow a programmer to learn GUI programming.  However,
          I'm told that its documentation might not be clear enough for
          beginners.

        - JPTUI is an object-oriented textual user interface, written by
          Jean-Pierre Delprat <jpdelprat@teaser.fr>.  It is designed for C++,
          and supports several languages besides US English.  You can get
          JPTUI from SimTel.NET or any of its mirrors
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/jptui4jd.zip).

        - the BCGUI package, written by Bill Currie
          <bill@tanihwa.tssc.co.nz>; you can get it from Bill upon request.

        - If you actually have the original Borland Turbo Vision, then you
          might want to get patches to compile Turbo Vision under DJGPP.  For
          more info on this port, visit the TVPlus site
          (http://www.zeta.org.au/~grove/tvhome.html).

        - Another port of TVision was done by Robert Hoehne
          <robert.hoehne@gmx.net>.  Due to copyright problems, that port
          cannot be distributed (at Borland's request, Robert has removed it
          from his Web page).  So you will have to get the Turbo Vision
          sources from the Borland's site, patch them using patches included
          in the RHIDE distribution, and rebuild it yourself.

        - A Turbo Vision like library for plain C, called C-Desktop, by Brett
          Porter <blp01@uow.edu.au>, is available from DJGPP sites on
          SimTel.NET mirrors
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/cdesk100.zip).

        - Another GUI library is XView-PC GUI interface, maintained by
          Antonio Carlos M. de Queiroz <acmq@coe.ufrj.br>.  XView-PC is
          available via the Web (http://www.coe.ufrj.br/~acmq/xview_pc.html)
          and also via the FTP transfer
          (ftp://coe.ufrj.br/pub/acmq/xv_pc18a.zip).

   * Game programming:

        - The best library for DOS game programming is the Allegro game
          programming library
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/alleg30.zip),
          written and maintained by Shawn Hargreaves
          <Shawn@talula.demon.co.uk>; also available from Allegro home page
          (http://www.talula.demon.co.uk/allegro/).  Allegro is ported to X
          (http://www.canvaslink.com/allegro/xwinallegro/).  A tutorial for
          game programming, called Allegro Vivace, was written by George Foot
          <george.foot@merton.oxford.ac.uk>, and is available from George's
          home page (http://www.canvaslink.com/gfoot/vivace/).

        - Also try Jlib
          (ftp://x2ftp.oulu.fi/pub/msdos/programming/djgpp2/jlib_NNN.zip)
          written by J P Griffiths <jpg@wave.co.nz>.  This library is best
          suited to multi-platform game programming, since it's portable to
          Linux, Watcom, and X11.   Visit the Jlib Web page
          (http://www.wave.co.nz/pages/jpg/jlib/), for the latest
          developments.

        - Another popular library for game development is MGL, the
          "MegaGraphics Library" by SciTech Software.  MGL provides
          transparent support for DirectX, OpenGL, Mesa, and several other
          popular graphics standards (although some of these standards
          reportedly only work when used with RSXNTDJ).  The latest version
          4.1 has full DJGPP support.  MGL is available from SciTech's FTP
          site (ftp://ftp.scitechsoft.com/devel/beta/dj20lib.zip).

        - The Mesa library itself supports DJGPP and is available from the
          Mesa home page (http://www.ssec.wisc.edu/~brianp/Mesa.html).

        - Yet another package that supports DirectX 5 for DJGPP and RSXNTDJ is
          available via the Web (http://bbs.para.co.kr/~bng/drdx/drdx.html).

        - If you need to play audio CDs, try the Brennan Underwood's CD
          playing library
          (http://brennan.home.ml.org/programming/bcd_103.zip).

   * VGA graphics:

        - Paul Fenwick <bg914@FreeNet.Carleton.CA> wrote an X-Mode package
          Xlib (ftp://ftp.delorie.com/pub/djgpp/contrib/xlibdj24.zip) or Xlib
          at Oulu
          (ftp://x2ftp.oulu.fi/pub/msdos/programming/djgpp2/xlibdj24.zip).

        - Matthew Bentley <mrb8@waikato.ac.nz> has written a C++ VGA graphics
          library for mode 13h (and is reportedly 4 times faster than Allegro
          in this mode) called EZVGA.  It is available as ezvga14.zip from
          the `v2tk' directory on DJGPP sites.

   * Multi-tasking libraries and OS kernels:

        - Pthreads (ftp://ftp.cs.fsu.edu/pub/PART/PTHREADS/pthreads.zip), a
          Posix threads library, is a portable, standard package supported on
          many platforms.

        - The LWP package is a lightweight preemptive multitasking library
          written by Josh Turpen <snarfy@goodnet.com> for DJGPP.  It has an
          extremely simple API and is very fast.  You can get LWP via the Web
          (http://www.goodnet.com/~snarfy).

        - PDMLWP is a multithreading package for DJGPP.  It is available as
          `pdmlwpNN.zip' (`NN' is a version number) from the `v2tk' directory
          on the DJGPP sites.

        - Bill Currie <billc@blackmagic.tait.co.nz> has written a COFF boot
          loader using DJGPP; you can get this COFF boot loader from Alaric
          Williams' Web site
          (http://www.abwillms.demon.co.uk/prog/kernel2.zip).

        - Palantir is a multitasking kernel for Allegro, written and
          maintained by Dim Zegebart <zager@post.comstar.ru>.  Palantir is
          available from DJGPP sites
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/allegro/plntr041.zip).

   * Development toolkits and packages:

        - MSS is a package for detecting problems with dynamic memory
          allocation, such as using uninitialized memory, overwriting the
          limits of allocated blocks, memory leaks, repeated deallocations,
          etc.  It is available from the DJGPP sites
          (ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk/mss11b.zip), and
          supports both C and C++ programs.  MSS was written and is
          maintained by Peter Palotas <blizzar@hem1.passagen.se>.

        - Cdecl is a program for translating hairy C and C++ declarations and
          type casts into human-readable English.  A DJGPP port by Nate
          Eldredge is available via FTP
          (http://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2apps/cdecl25b.zip).

        - LCLINT is a Lint clone.  Lint is a program which analyses C source
          files, identifies unsafe or potentially buggy code and prints
          error/warning messages about each such case.  `gcc -Wall' can
          identify many such cases as well, due to the superior diagnostics of
          GCC, but for those who still want Lint, you can find LCLint sources
          on the Web (http://larch-www.lcs.mit.edu:8001/larch/lclint.html).

        - VIM is a programmer's editor, mostly popular in the Unix world.  It
          features syntax highlighting for more than 60 different file
          formats, context-sensitive help, and a macro language for writing
          extensions.  The sources are available via ftp
          (ftp://ftp.fu-berlin.de/misc/editors/vim/), and should compile with
          DJGPP.  Binaries are available for Windows 9X and NT, as well as
          for DOS.

22.4 How to create symbolic links to programs
=============================================

**Q*: How do I create symbolic links?*

**Q*: I have this program that behaves differently depending on the name it's
called.  Under Unix, I just create symbolic links to achieve that, but DOS
doesn't support links.  Do I have to put several identical programs under
different names on my disk??*

*A*:  DJGPP allows you to simulate symbolic links to programs.  Generate a
stub (which is a small DOS program attached to every DJGPP program by the
`stubify.exe' program), call it by the name of the link you want, then edit
its header to run another program.  For example, let's say the real program
is `dj1.exe' and we want to make a link called `dj2.exe' that really calls
`dj1.exe.'  First, generate a stub under the name `dj2.exe.'  Next, run
`STUBEDIT' to modify the new program's stub info block and change the name of
the executable it runs.  In this case, we'd change it to `dj1':

      C:\USR\BIN> stubify -g dj2.exe
      C:\USR\BIN> stubedit dj2.exe runfile=dj1

Voila!  Now, when you run `dj2', it tells the stub to load the image of
`dj1', but pass "dj2" in `argv[0].'

If you use the DJGPP port of GNU Fileutils 3.13 or later, the `ln' program
there can do the above steps for you if you say this (like on Unix):

      ln -s dj1.exe dj2.exe

22.5 Where to find the DPMI specification?
==========================================

**Q*: What is this DPMI thing you are all talking about?*

**Q*: Where can I find the specifications for the DPMI functions?*

*A*: DPMI, the "DOS Protected-Mode Interface", is an API that allows
protected-mode programs to run on top of DOS, which is a real-mode operating
system, and still be able call real-mode DOS and BIOS services.  A special
API is required because DOS code cannot be run in protected mode: if you try,
your system will immediately crash, since the real-mode DOS and BIOS code
violates many restrictions of protected-mode programming.  See restrictions
of protected mode in Section 17.3, for more details.

The DPMI API is implemented as a set of functions of Interrupt 31h which
allow such chores as switch from real to protected mode and back (generally
done upon startup and at exit), memory allocation, calling real-mode
services, etc.  DPMI is by far the most portable way of running
protected-mode programs on MS-DOS, MS-Windows and compatible systems.

You can find the DPMI 0.9 spec by anonymous ftp to one of the following sites:

   - At the Quarterdeck ftp site
     (ftp://ftp.qdeck.com/pub/general/dpmispec.zip).

   - At Oulu (ftp://x2ftp.oulu.fi/pub/msdos/programming/specs/dpmispec.arj).

   - The DPMI 1.0 specs are available by anonymous ftp from the Intel
     anonymous ftp site
     (ftp://ftp.intel.com/pub/IAL/software_specs/dpmiv1.txt) (the file
     `dpmip1.zip' at the same location is the PostScript version of this
     spec), and also at the Oulu site
     (ftp://x2ftp.oulu.fi/pub/msdos/programming/specs/dpmi100.zip).

   - A paper copy of the DPMI specifications can be ordered from Intel as
     document number 240977-001.

   - Some information about the DPMI API is also found in the Ralf Brown's
     Interrupt List
     (ftp://ftp.simtel.net/pub/simtelnet/msdos/info/inter58c.zip).  Look at
     the functions of Interrupt 31h, or search the files for the word `DPMI'.

   - The DJGPP Web server allows you to use WWW to browse the DPMI spec
     on-line (http://www.delorie.com/djgpp/doc/dpmi/).

22.6 The DJGPP Web site.
========================

**Q*: Where is the DJGPP Web site?*

*A*:  Yes, DJGPP has its own home on the Internet, set up and maintained by
(who else?) DJ Delorie <dj@delorie.com>.  It has an HTML version of this FAQ
list with search capabilities, the entire set of DJGPP distribution files, a
searchable archive of the DJGPP mailing list and news group traffic, plus
other useful and interesting information about DJGPP.  For instance, did you
ever wonder how DJGPP got started and what DJ's original goals were?
Rejoice: the Web site includes the story of DJGPP genesis
(http://www.delorie.com/djgpp/history.html).

To visit, point your browser to the DJGPP Web site
(http://www.delorie.com/djgpp/).

22.7 Where to upload your contributions to DJGPP
================================================

**Q*: I wrote a program using DJGPP.  How can I make it available to others?*

**Q*: I found and corrected a bug in one of the programs distributed with
DJGPP.  Where should I put it?*

*A*:  If the program/patches are small enough, consider posting it to the
mailing list or the comp.os.msdos.djgpp news group.  Please do *not* post
binaries to the news group; only post source code as plain text, and only if
it is not too large.  Many people who read the news group cannot save the
MIME attachments, and don't like to be forced to download a large message;
you are requested to respect that.

If the program is larger than, say, 50K bytes, it's best to upload it to a
public site where everybody can get it.  You can upload your contribution to
a special directory on the DJ Delorie's FTP server
(ftp://ftp.delorie.com/incoming/).  This directory is write-only, and it gets
purged every couple of days, so be sure to write to DJ Delorie
<dj@delorie.com> about your upload; he will then move it to the
`/pub/djgpp/contrib' directory.

If you decide to upload, please send mail to the `djgpp-announce' list with a
brief description of your program/patch.  (The message will get reflected to
both the news group and the DJGPP mailing list, so you don't have to
cross-post there, but it also goes to people who only subscribe to
`djgpp-announce' list because they want to get such announcements and nothing
else.)

If your program is more than a patch or a beta version, you might consider
uploading it to the DJGPP archives on SimTel.NET.  If you decide to do it,
write to DJ Delorie <dj@delorie.com> and ask him for uploading instructions.
Material uploaded there gets automatically distributed to all of the
SimTel.NET mirrors throughout the world, which makes it easier to get.

DJ Delorie requests that all contributed packages uploaded to his server be
source-only distributions; don't bother to include libraries or pre-compiled
binaries, since DJ deletes them when he opens the zip archive.  This is so
there will be no danger of distributing programs infected by a virus.  Please
avoid uploading self-extracting archives because DJ extracts them on a Unix
machine which can't run DOS executables.

22.8 DJGPP as cross-compiler
============================

**Q*: I want to use DJGPP as a cross-compiler for Motorola 68K targets.  How
should I proceed about this?*

**Q*: I want to build GCC as a Unix-to-DOS cross-compiler.  What should I do?*

*A*:  If you want a cross-compiler for m68k on a DOS machine, you need DJGPP
configured as `host=i386-go32', and `target=m68k-coff.'  Such a package is
already available (ftp://ftp.lysator.liu.se/pub/msdos/gnu/gcc-dos-m68k/).
The binaries there are based on GCC 2.7.2.  This package is reportedly no
longer supported, but if you have questions about it, you can send them to
Jim Karpinski <jk55@cornell.edu>.  You can also try to contact Kai Ruottu
<karuottu@freenet.hut.fi>, who is the provider of DOS-hosed gcc-m68k.  Note
that this package has only basic support for C++: the compiler is included,
but the libraries, including `libstc++' and `libg++', and the C++ headers are
missing, so even `cin' and `cout' don't work.

A Win32-hosted gcc-m68k (http://www.calm.hw.ac.uk/davidf/coldfire.htm) is
another possibility.  It was created by David Fiddes.  The Cygwin32 port of
GCC can also be configured as a cross-compiler with m68k as the target.  See
the description of the Cygnus project in Section 3.6, for more details about
the Cygwin32 port.

DJGPP can be built and installed as a cross-compiler running on a Unix
machine and targeting DOS/Windows platforms.  Here are the necessary steps to
do that:

  1. Download the cross-compiler toolkit `v2/djcrx201.zip' from the usual
     DJGPP sites.

  2. Unpack `djcrx201.zip' on the Unix machine using `unzip -a'.

     You *must* use the `-a' switch, to force `unzip' to convert any
     DOS-style text file with CR-LF pairs at the end of each line to
     Unix-style text files.  If you don't, things will break for you.

     `unzip' is available in source form from many FTP sites.

  3. Link or move the files in the `cross' directory to the top-level
     directory, where you unzipped `djcrxNNN.zip'.

  4. Download the latest GCC and Binutils distributions from your favorite
     GNU FTP site.

     The main GNU site is at ftp.gnu.org (ftp://ftp.gnu.org/pub/gnu/).

  5. Unpack GCC and Binutils from the same directory where you unzipped
     `djcrxNNN.zip'.

  6. You might need to edit the Makefile, either to choose an installation
     directory as appropriate for your machine, or to change the names of the
     directories where the GCC and Binutils distributions are unpacked (e.g.,
     because their version numbers are different from what the Makefile says).

  7. Follow instructions in the file `cross/install' that was unpacked from
     `djcrx201.zip' to build and install the cross compiler.

The cross-compiler you build is installed as `dos-gcc', so to compile
programs with it, use `dos-gcc' rather than `cc' or `gcc', or set
`CC=dos-gcc' when invoking Make.

The file `cross/readme' has some usage info for `dos-gcc'.  It is generally
correct, except that the version numbers for the various packages might not
be up to date.  You should always use the latest releases of every package.

Another alternative is the RPM ("Redhat Package Maintenance") distribution of
the Linux to DOS cross-compiler, which is based on DJGPP v2.01 and includes
everything you need to create DJGPP binaries on Linux (without running
DOSEmu).  This package has been built by James Soutter <cgjks1@lut.ac.uk>
using the instructions above; you will need Linux and RPM 2.2.7.  The RPM
packaged cross-compiler is available from Redhat site
(ftp://ftp.redhat.com/pub/incoming/djgpp-2.1-1.i386.rpm); the sources are
also available (ftp://ftp.redhat.com/pub/incoming/djgpp-2.1-1/src.rpm).

22.9 GCC says "garbage at end of number"
========================================

**Q*: There is a severe bug in GCC: it says "garbage at end of number" for
this line:*

      i = 0xfe+0x20;

*Ain't it silly that such a great compiler would fail so miserably?*

*A*:  That's not a bug, that's a feature of the *ANSI C language definition.*
By ANSI rules, the above expression is a single "preprocessing token",
unless you place whitespace in front of the plus sign.  The reason for this
seemingly counterintuitive feature is the syntax of floating-point constants
in which letters `e' and `E' followed immediately by a sign signal a decimal
exponent.  You can use the `-traditional' compiler switch to turn this
feature off (however, it will also turn off a plethora of other ANSI
features; see the GCC docs for details).

Judging by the published draft, this is unchanged even in the forthcoming C9X
standard.

22.10 What should sizeof (struct xyzzy) return?
===============================================

**Q*: When I call `sizeof' on a struct, I sometimes get values which are
larger than the sum of the sizes of the struct members, whereas in Borland
C++ I always get the correct result.  Is it a bug in GCC?*

**Q*: I have a program that reads struct contents from a binary file.  It
works OK when compiled with BC, but reads garbage when compiled with DJGPP.
This must be a bug in DJGPP, right?*

*A*: No, it's not a bug.  GCC generates 32-bit code, and in that mode, there
is a significant penalty (in terms of run-time performance) for unaligned
accesses, like accessing a 16-bit short which isn't aligned on a word
boundary, or accessing a 32-bit int which isn't aligned on a dword boundary.
To produce faster code, GCC pads struct members so that each one can be
accessed without delays; this sometimes produces struct size which is larger
than the sum of the sizes of its members.  If you need to minimize this
padding (e.g., if your program uses large arrays of such structs, where
padding will waste a lot of memory), lay out your structures so that the
longer members are before the shorter ones.  For example, let's say that you
have a struct defined thus:

       struct my_struct {
         char name[7];
         unsigned long offset;
         double quality;
       };

To make such a struct use the least number of bytes, rearrange the members,
like this(1):

       struct my_struct {
         double quality;
         unsigned long offset;
         char name[7];
       };

If the layout of the structure cannot be changed (e.g., when it must match
some external specification, like a block of data returned by a system call),
you can use the `__attribute__((packed))' extension of GCC (see the Gcc docs
in "GNU C/C++ Manual", or point your Web browser to
http://www.delorie.com/gnu/docs/gcc-2.7.2.2/gcc_84.html#SEC86.) to prevent GCC
from padding the structure members; this will make accesses to some of the
members significantly slower.

Beginning with version 2.7.0, GCC has a command-line option `-fpack-struct'
which causes GCC to pack all members of all structs together without any
holes, just as if you used `__attribute__((packed))' on every struct
declaration in the source file you compile with that switch.  If you use this
switch, be sure that source files which you compile with it don't use *any*
of the structures defined by library functions, or you will get some members
garbled (because the library functions weren't compiled with that switch).
Alternatively, you could declare any single structure to be packed, like so:

       struct {
         char name[7];
         unsigned long offset;
         double quality;
       } __attribute__ ((packed));

However, note that the latter will only work when you compile it as a C
source; C++ doesn't allow such syntax, and you will have to fall back to
declaring each struct member with the packed attribute.  Therefore, it's best
to only use declarations such as above if you are *certain* it won't be ever
compiled as a C++ source.

The padding of struct members should be considered when you read or write
struct contents from or to a disk file.  In general, this should only be done
if the file is read and written by the same program, because the exact layout
of the struct members depends on some subtle aspects of code generation and
the compiler switches used, and these may differ between programs, even if
they were compiled by the same compiler on the same system.  If you do need
this method, be aware of the struct member padding and don't assume that the
number of the file bytes that the structure uses is equal to the sum of the
members' sizes, even if you instructed the compiler to pack structs: GCC
still can add some padding after the last member.  So always use `sizeof
struct foo' to read and write a structure.

Another problem with porting programs that read structs from binary files is
that the size of some data types might be different under different
compilers.  Specifically, an `int' is 16-bit wide in most DOS-based
compilers, but in DJGPP it's 32-bit wide.

The best, most robust and portable way to read and write structs is through a
`char' buffer, which your code then uses to move the contents into or out of
the struct members, one by one.  This way, you always know what you are doing
and your program will not break down if the padding rules change one day, or
if you port it to another OS/compiler.  The ANSI-standard `offsetof' macro
comes in handy in many such cases.

---------- Footnotes ----------

(1) Note that this still allows the struct to be padded at the end.

22.11 C++ doesn't pack structs!
===============================

**Q*: When I use `struct ffblk' from the header `dir.h' in a C++ program, I
get garbage in some members of the structure!*

*A*:  There is a known bug in GCC 2.7.2: the C++ compiler effectively ignores
the `__attribute__((packed))' directives, so the structures end up being not
packed.  DJGPP v2.01 comes with GCC 2.7.2.1 which corrected that bug, so
upgrade.  As a work-around, surround the declaration of the structure that
needs to be packed with `#pragma pack', like this:

       #ifdef __cplusplus
       #pragma pack(1)
       #endif
       .
       .
       .
       #ifdef __cplusplus
       #pragma pack()
       #endif

22.12 How to avoid "Abort, Retry, Fail" messages
================================================

**Q*: How do I write a program that accesses floppy and CD-ROM drives, but
avoids popping that "Abort, Retry, Fail?" message from DOS?*

**Q*: Other DOS compilers supply a function named `harderr' or `_harderr' to
hook the critical-error interrupt 24h, but DJGPP doesn't seem to have
these...*

*A*:  Under DPMI, Int 24h is always hooked by the DPMI server, since Int 24h
is issued by the real-mode DOS code, and it is not possible to terminate a
DPMI client (like DJGPP programs) from real mode, if you press `A' in
response to that prompt.  The default handler under most DPMI servers will
just set AL register to 3 and do an `IRET', thus silently failing the DOS
call that triggered Int 24h.  The DJGPP startup code also hooks the
protected-mode Int 24h with a handler that fails the DOS call as described
above.  So in most circumstances you won't see that DOS prompt at all; your
program will just see a failed DOS call.

However, some DPMI hosts (notably, QDPMI), will sometimes crash your program
if it generates Int 24h, for instance when you access an empty floppy drive.
In such cases, or when the default action of failing the DOS call is not good
enough, you will have to hook Int 24h with your handler.  This should be done
in exactly the same manner as hooking hardware interrupts (see how to set an
interrupt handler in Section 18.9), because Int 24h is one of the few
software interrupts that, like all hardware interrupts, are always reflected
to the protected-mode handler first.  Note that CWSDPMI currently doesn't
support hooking Int 24h; if you set an interrupt handler, it won't be called.

There are ways to avoid program crashes due to Int 24h (under those DPMI
hosts that exhibit this buggy behavior) other than to install a handler for
it.  For instance, you can test if the floppy drive is empty with a BIOS call
before accessing it with DOS functions; there are also similar ways to check
if a CD-ROM drive is empty.  The library function `getmntent' (see getmntent
in "libc.a reference", or point your Web browser to
http://www.delorie.com/djgpp/doc/libc-2.01/libc_337.html#SEC337.)  can be
used to detect all the drives that can be safely accessed by DOS; or you can
borrow some of the internal functions used by `getmntent' from the library
source distribution
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/djlsr201.zip), or from the
zip picker (http://www.delorie.com/djgpp/dl/ofc/).

22.13 What is that `go32-v2.exe' program?
=========================================

**Q*: What is go32-v2 for?*

*A*:  The `go32-v2' program does the following:

   * With no command-line arguments, it prints the available physical and
     virtual memory, much like `go32' did in v1.x.

   * It can run unstubified v2 COFF images, like this:

           go32-v2 myprog

   * If you rename it to `go32.exe' and put on your `PATH' before the v1.x
     `go32.exe', it can also run a v1 COFF images, by loading the v1.x `go32'
     and letting it do the job.  With this setup, you can run v2 programs
     from v1.x programs, because the v1.x program will load `go32-v2' (since
     it found it first on the PATH) which knows how to run v2 images, instead
     the original `go32' which cannot.

22.14 What is DXE?
==================

**Q*: What is a DXE?*

**Q*: Can I make a DLL using the DXE support?*

**Q*: Where can I find information or examples about writing/loading the DXE
files?*

**Q*: Why do I get undefined references when I run `dxegen'?*

*A*: DXE is a limited facility to dynamically load code which is rarely
needed in DJGPP.  An example is the floating-point emulator code (see the
details of DJGPP FP emulator in Section 11.1) which is only used on those few
machines that lack an FPU.  The DXE design is intentionally limited to keep
it as simple as possible, so that the code that loads a DXE could be small
(it's a few hundreds bytes).  Because of this, there are a number of
limitations in the DXE mechanism that prevent using it for full-fledged
dynamic linking (i.e., a DLL).  For instance, the DXE module cannot access
variables or functions in the main module.

A DXE cannot link in any library functions which reference static variables
(or which call other routines which reference static variables); this
effectively prohibits linking in I/O functions, allocating memory, and many
other useful things.  If you do call any of these, you'll get unresolved
externals from `dxegen'.  To work around this limitation, introduce an array
of function addresses which will be used from the DXE at run time to call the
"special" routines you cannot link in.  Then arrange for the address of this
array to be returned by `_dxe_load' when it loads the DXE, and make the init
routine fill the array with the actual addresses of those "special" functions.

Unloading a DXE is also not supported (but I'm told you can add this by
making a few simple changes in the C library).

The only place you can find some docs and examples of writing and using a DXE
is in the "tests" archive
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/djtst201.zip).  The example
there is *exceedingly* simplistic, but then so is the entire DXE mechanism...

22.15 Long Filenames Don't Work!
================================

**Q*: I cannot make Info find some of its files under Windows 9X...*

**Q*: Why does Make behave as if some of the files were not there?*

*A*: Are you running DJGPP v2.0 on Windows 9X with long filename support
enabled (LFN=y in the environment)?  If so, set LFN=n from the DOS prompt and
try again.  If the problems go away, they are probably due to known bugs in
some v2.0 programs wrt the LFN support.  Make and Info which came with DJGPP
v2.0 are two programs which are known to reveal these bugs.  Before you
decide that you are a victim of these bugs, though, make sure that all the
files that your programs need to access have been renamed to their long
names.  For example, if Make needs to find a file called `ALongFileName.cc'
(because the Makefile tells it to build `ALongFileName.o'), make sure there
indeed is such a file in the directory.  Sometimes people use archive tools
(like `PKZIP') that truncate long names, even on Windows 9X, when they open an
archive, which leaves you with names like `alongfil.cc', which is not the
same as the original name when LFN is supported.  Be sure to use archivers
that support long filenames, e.g. use `DJTAR' when you open `.tar.gz'
archives, or rename all the files to their original long names after you open
the archive.

If the problems persist even though the filenames are correct, upgrade to
DJGPP v2.01 or later, where all programs should support long filenames
properly.  If you cannot upgrade, you will have to disable LFN support (set
LFN=n from the DOS prompt, setting it in `DJGPP.ENV' does not always work in
DJGPP v2.0).

22.16 Make says "missing separator"
===================================

**Q*: When I invoke Make, it refuses to do anything and prints a cryptic
message: "makefile:10: *** missing separator.  Stop."  Now what kind of
excuse is that?*

*A*: Unlike most other DOS Make programs which accept any whitespace
character at the beginning of a command in a rule, GNU Make insists that
every such line begins with a TAB.  (Most other Unix Make programs also
require TABs, and the Posix standard requires it as well.)  Make sure that
the line whose number is printed in the error message (in this case, line 10)
begins with a TAB.

There are editors that replace TABs with spaces, so even a Makefile that used
to work can become unworkable if you edit them with such an editor.

Another, more rare, cause of the above error message is if you use static
pattern rules (with the `%' character) incorrectly.  Read the documentation
that comes with Make carefully and try to find the error.

22.17 Make says "`foo' has modification time in the future"
===========================================================

**Q*: I keep getting messages about file modification time in the future when
I compile my programs using Make...*

*A*: This happens on fast machines running Windows/NT and Windows 9X.
(However, somebody even reported such a problem on a FAT32 drive under plain
DOS.)  It is evidently due to a misfeature in the way Windows reports the
time a file was last modified.  Current versions of Windows 9X store this
time with 2-second granularity, but the file creation time is stored with a
100-nanosecond granularity.  It seems that Windows blindly adds 2 seconds to
the system clock reading when it calculates the file modification time,
apparently to prevent it from being older than the file creation time, which
could happen because of the greater accuracy used to store the creation time.
On a fast machine, this 2-second add-on can very easily make the file
modification time be ahead of the system clock when Make checks the time
stamp of a file it has just created/updated.

GNU Make reports such cases because inconsistencies in file times could
easily defeat its decisions about which files need to be rebuilt.  In
particular, if some of the files reside on a networked drive, and there's a
clock skew between the machine where Make runs and the one which exports the
drive, Make could really fail to rebuild some files.

DJGPP ports of GNU Make v3.77 and later allow for up to 3 seconds of positive
difference between the file timestamp and the system clock (that is, the file
is allowed to be up to 3 seconds into the future), before the above warning
is printed.  So upgrading to the latest version of Make should eliminate such
bogus warnings and leave you only with messages due to real clock skews.

22.18 How to Set Up a Dual DOS/Windows Installation
===================================================

**Q*: I want to be able to run DJGPP both under Windows 9X with long file
names, and when I boot into plain DOS, where long file names aren't
supported.  How can I set that up?*

*A*: Such a setup is possible, but it involves a few special actions, and
some vigilance on your part during routine operations.

First, you must set the option in the Windows registry which prevents it from
using numeric tails when it invents short 8+3 aliases for long file names.
When numeric tails are enabled, and a file with a long name is created,
Windows generates a short 8+3 alias for that long name by attaching a numeric
tail `~N' to the first 6 characters of the basename.  For example, a file
called `ALongFileName.LongExtension' will get a short alias `alongf~1.lon'.
When you then reboot into plain DOS, your programs will see this short
version only, which will almost certainly break them, since, when a program
running under DOS asks for a file with the above long name, DOS transparently
truncates it to `alongfil.lon', and such a file does not exist.  Disabling the
numeric tails forces Windows not to use numeric tails unless there is another
file in the same directory whose short alias clashes with that of the new
file.  If no such clash happens, Windows will simply truncate the long name
as DOS would, which is exactly what you want.

Here is how you disable the numeric tails on Windows 9X:

   * From the "Start" menu select "Run" and type `regedit', to start the
     Registry Editor.

   * Expand the `HKEY_LOCAL_MACHINE' branch of the registry until you see in
     the left pane an item called
     `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\FileSystem', then
     click on it.

   * The right pane now shows the list of values assigned to the `FileSystem'
     key.  If you don't see an item there called `NameNumericTail', select
     "New", "Binary Value" from the "Edit" menu, then type `NameNumericTail'
     and it will appear.  Now double-click on `NameNumericTail' and enter a
     value of 0.

   * Exit `regedit' and restart Windows 9X.

If setting `NameNumericTail' to 0 breaks some programs, you can restore its
original setting temporarily, while you run those programs.
`NameNumericTail' only affects the short names of new files being created, it
has no effect on the files that already exist.(1)

Besides the numeric tails, you need to make sure any files and directories
you create have unique 8+3 aliases which are true truncations of the long
names to 8+3 limits.  This means that you should avoid file names with
leading dots, such as `.emacs' and `.bashrc', file names with more than a
single dot, like `make-3.77.tar.gz', or file names which include characters
not allowed by DOS, like `libg++.a'.

One other problem is to avoid using programs which create numeric tails even
if they are disabled in Windows.  One such program is `pkunzip' version 2.50.
Don't use it, if you want to keep your dual DOS/Windows installation in
working order.

The most simple method of deciding at boot time which configuration (DOS or
Windows) to start is to edit the (hidden) file `MSDOS.SYS', which is a text
file in Windows 9X, and force the Windows boot process to present a menu
where one menu item, called "Command Prompt Only", allows you to start DOS 7
without the Windows GUI.  To this end, change the line of `MSDOS.SYS' that
reads "BootMenu=0" to say "BootMenu=1" instead, and reboot.

---------- Footnotes ----------

(1) For some reason, Microsoft doesn't like it when users disable numeric
tails.  Several Microsoft publications warn against doing that, and I'm told
that Windows 98 has made it harder to disable them.  I'm not sure why do they
object so much.  Presumably, some programs rely on certain directories to
have numeric tails, so that they could be found even in plain DOS mode.
Apparently, some of those programs have short aliases such as `PROGRA~1' (the
short version of the `Program Files' directory) hard-wired into them, and
Microsoft is afraid you could reinstall or move those directories when
numeric tails are disabled, and thus cause such programs not to find their
"home".  It is obvious that such programs are badly broken (e.g., the short
alias could easily be `PROGRA~2'), and you have every right to yell at the
vendor who sells them to you.  But even if you have no other way than to live
with them, my experience shows that you have nothing real to worry about.
Remember: numeric tails only have effect when files are created or renamed.
So, if you want to be on the safe side, re-enable them before installing
Windows software, especially if the programs you install need to run in DOS
mode as well (a typical example would be a disk-recovery package such as
Norton Utilities).  Then disable numeric tails again, once the installation
is over.

For what it's worth, I always run my system with numeric tails disabled, and
I have yet to see a single real problem.

22.19 What is in that `zoneinfo' directory?
===========================================

**Q*: When I installed DJGPP v2, it created a directory named `zoneinfo' with
a lot of small files that take up 3.5MB of my disk space.  What are they for?
Can I delete them?*

*A*:  These files exist so that time-related library functions can correctly
calculate the offset between the local time and the "UTC" (Universal
Coordinated Time).  This offset is required when you get files from another
time-zone, like from the Internet, or when you download an archive that was
compressed in another time-zone.

One case where the time stamps might be very important is when you need to
rebuild some package with Make.  Make uses file time stamps to decide which
files need to be rebuilt.  Another case is if you distribute some files
compressed with `Zip' and want your recipients to be able to restore the
correct time stamps of your files when they unzip them.

If you don't care about file time stamps being incorrect in such cases, you
can delete all those files and never look back.

You might wonder why we need all these zoneinfo files when the UTC offset
*is* required.  Well, the simplest way to tell programs what the UTC offset
is, is to have the user specify a single number which is the offset; but then
this number needs to be changed twice a year, to accommodate for the daylight
saving time.  Another, not-quite-so-simple way is to have the user specify
the current UTC offset and the DST rules; but this is a tedious and
error-prone process, and many users get it wrong.  Both of these methods have
the drawback that if the rules change, programs misinterpret old time-stamps,
since they treat them according to new rules.  Using a table that is read from
a file and includes the offset calculation rules for every year avoids all
these problems and requires the user to point the `TZ' environment variable
to the file that is pertinent to his/her time zone, which is easy:

      set TZ=c:/djgpp/zoneinfo/israel

*or*

      set TZ=c:/djgpp/zoneinfo/us/alaska

To find the rule suitable for your location, look into the `src' subdirectory
of `zoneinfo' and browse the file whose name is your continent/part of the
world.  If no binary file exists with the name of your zone, you can create
one with using the time-zone compiler `zic', whose source is available in the
`v2/djlsr201.zip' file, with the rest of DJGPP.

A public domain time-zone database exists, and is updated from time to time
with the latest world-wide changes to the offset calculation rules.  (The
rules change because politicians in different countries make laws that change
the local clock settings.)  The contents of the `zoneinfo' directory which
comes with DJGPP is based on this database, but if you want the latest rules,
you can download them from the net (ftp://elsie.nci.nih.gov/pub/) as
`tzdata*.tar.gz'; `tzcode*.tar.gz' in the same directory includes the
programs that can be used to generate the offset tables from their source in
`tzdata*.tar.gz', the latest implementations of POSIX library functions that
use time-zone information, and the man pages that document the rules and the
software.  The last update as of this writing was in May 1998.

On any single machine, you don't need more than a single file from that
directory, which is the file for your time zone; once you find that file, you
can safely delete the rest.  But if you distribute a program that uses the TZ
setting, you will have to include all of the files, or tell your users how to
get and install them.

22.20 The Secrets of the /dev/ Directory...
===========================================

**Q*: All DJGPP programs cannot find files in the `d:\dev' directory, but
work okay in other directories.  What is going on here??*

*A*: This is an unfortunate side-effect of the special treatment given to the
`\dev' directory on each drive.  DJGPP transparently supports Unix-style
devices such as `/dev/null' and `/dev/tty', so that programs ported from Unix
that refer to these devices will work.  Unfortunately, due to a half-hearted
way DOS and Windows support devices, the DJGPP library must treat the `\dev'
directory specially.  The net effect is that if you have a real directory by
that name, you will get erratic behavior.

A work-around is either to rename that directory to some other name, like
`\devel', or to move it down the directory hierarchy, for example make it
`d:\software\dev'.  (The special treatment is only reserved to the `\dev'
directories immediately under the root of every drive.)

22.21 How about switching to ELF as DJGPP's object file format?
===============================================================

**Q*: I hear all that stuff about the limitations of the COFF format, and I
don't understand why won't DJGPP switch to a modern standard such as ELF?*

*A*:  DJGPP uses COFF for historical reasons: at the time it was developed
ELF was not available yet.  There are several grave reasons why DJGPP didn't
switch to ELF yet:

   * Changing the binary format requires many changes to several packages
     that are central to DJGPP:

        - The Binutils should be configured for ELF, which requires that the
          parts of Binutils that deal with ELF be ported to DJGPP.  GCC also
          needs to be configured differently.

        - The DJGPP stub loader (`stub.asm' in the library sources) needs to
          be partially rewritten to be able to load an ELF executable and set
          it up for execution.  Since the stub loader is written in assembly
          and optimized for size, this is a formidable task.

        - All stub-related programs, like `go32-v2', `stubify' and
          `stubedit', need to be changed as well.

        - The DJGPP debugger support (functions in the `src/debug/' directory
          in the `djlsr' distribution) need to be changed to support ELF.

        - The ported GDB needs to be built with ELF support instead of COFF.
          Again, this means that the GDB ELF-specific code needs to be ported
          to DJGPP.

   * Since ELF requires that external symbols have the same name in C and in
     object files, the DJGPP prepending of underscores to C object names
     needs to be abandoned.  This means that any assembly code that refers to
     C symbols or calls C functions needs to be rewritten.  In particular,
     this involves rewriting some C library functions and a significant
     portion of Allegro.

   * Because of the above, switching to ELF will totally break
     back-compatibility with old libraries and object files.

None of the above is a show-stopper, so such a switch *is* possible.  But it
is a large project, and without several devoted volunteers, chances are it
will never happen.

22.22 How to produce random numbers?
====================================

**Q*: How do I produce random numbers with DJGPP?*

**Q*: I keep getting the same random numbers each time I run my program.  How
do I get a different series on every run?*

*A*: DJGPP has in its library two functions to produce series of
"pseudo-random"(1) numbers: `rand' and `random'.  The former is part of the
ANSI C Standard, and is therefore very portable to other environments.  The
latter is available on almost every Unix platform, but is generally
unsupported by DOS/Windows compilers.  On the other hand, series produced by
`random' have better qualities than those produced by `rand'.  In particular,
the least-significant bits in the numbers produced by `random' are much more
random than those you get from `rand', so if you need, say, a random number
between 0 and 4, and portability is not an issue, you will get better results
with `random () % 5'.  However, the DJGPP implementation of `rand' is quite
good, so when portability *is* important, you should use `rand'.

Both `rand' and `random' return a pseudo-random integer in the range
`[0..RAND_MAX]', where `RAND_MAX' is defined in the `stdlib.h' header.

By default, every time you restart a program, you get the same series of
pseudo-random numbers.  This is important in some applications, because it
allows to reproduce exactly the results of running a program which used
random series, and thus makes debugging easier.  But sometimes, e.g. in a
game, you will want a different series every time.  To achieve that, you need
to initialize the random series with a different "seed".  Two functions
provided for this purpose, `srand' and `srandom', will seed the series
generated, respectively, by `rand' and `random'.  You seed the series with a
single call to `srand' or `srandom', and then proceed by calling `rand' or
`random' as usual.

A popular way of getting a different seed every run is to use the current
system clock as the seed, like this:

       srand (time (NULL));

If the 1-second granularity of the values returned by `time' is not enough
for you (e.g., if you need to generate more than one series every second),
use `gettimeofday' or `uclock', or use the values returned by `rand' as an
argument to `srandom' (or vice versa).

---------- Footnotes ----------

(1) Since these series are computed using a deterministic algorithm, they are
not *really* random.  Real random numbers can only be a result of
unpredictable physical processes such as radioactive decay etc.  However, a
good algorithm for pseudo-random numbers produces a series of numbers that
pass many tests for randomality.

22.23 What are all these buzzwords I see?
=========================================

**Q*: All your FAQs and tutorials seem to take for granted that I know what
words like "compile", "link", "makefile" etc. mean.  Where can I find all
these buzzwords explained??*

*A*: The DJGPP docs use some basic computer lexicon, without which it would
be impossible to communicate.  If you find yourself completely lost in
terminology you don't understand, and this FAQ doesn't explain it, try
looking them up in the DJGPP Lexicon page
(http://www.delorie.com/djgpp/doc/lexicon/).  Another excellent resource for
computer-related terminology is the Jargon File
(http://www.ccil.org/jargon/), also available from the GNU FTP site
(ftp://ftp.gnu.org/pub/gnu/) as an Info file and in several other formats.

22.24 What should the `main' function return in a C program?
============================================================

**Q*: Why does everybody tell me that `void main' is bad?*

**Q*: If `void main' is incorrect, how come the compiler lets it compile?*

*A*: The ANSI/ISO C Standard specifies that the `main' function be declared
in one of the following two ways:

      int main (void);

or

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

In both cases the return type is an `int', and your `main' function should
therefore either return an `int' or call the library function `exit', when
the program ends.

Since the runtime environment assumes that `main' returns an `int', declaring
`main' with any other return type, including `void', invites trouble.  The
compiler might compile such a program, since the ANSI Standard doesn't
*require* it to fail, but the behavior of such a program is, in the
Standard's parlance, "undefined" (read: anything can happen).  That is why
GCC will print a warning in these cases if you use the `-Wall' switch.

To summarize, using `void main' is *unsafe* and can potentially do evil
things to your program.  It is best to avoid it.

22.25 Generating the FAQ in your favorite format
================================================

**Q*: How can I generate the FAQ list in a format I'm used to?*

*A*: First, I suggest to check whether the FAQ is already available in your
format.  The FAQ distribution
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/faq211b.zip) includes the
Info, plain-ASCII (text), and HTML (one large `.html' file) versions of the
FAQ list.  (Personally, I recommend to use the Info version, because Info
readers generally have superior search facilities.)  More formats will be
available as the tools for their generation are developed/tested.

If you prefer to read the FAQ list as hard-copy, get `faqNNNp.zip' from the
same place.  It includes the FAQ in PostScript and PCL formats; the former is
for printing on a PostScript printer, the latter is for the LaserJet series.
Be warned: the FAQ is a large document, more than 200 printed pages.
`faqNNNp.zip' also includes a `.dvi' file which you can print or view using
one of the available DVI drivers and previewers, such as Ghostscript or
`dvivga'.

If none of these formats is good enough for you, you will need to get the FAQ
sources and convert them into the format of your liking.  The sources of the
latest version of this FAQ list are on SimTel
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2/faq211s.zip).  This includes
the FAQ sources themselves (written in Texinfo), and all the auxiliary tools
required to produce all the formats in `faqNNNb.zip' and `faqNNNp.zip'.

Once you download the sources, you will need one or more of the tools listed
below to generate the FAQ list in other formats.

A program called `Makertf' can reportedly be used to convert a Texinfo
sources of this FAQ to the "Rich File Format" which can then either be
browsed by an RTF browser (such as Adobe Acrobat) or converted into a Windows
Help file with a Windows Help compiler.  The Windows Help Compiler is
available via anonymous ftp from the Microsoft ftp site
(ftp://ftp.microsoft.com/Softlib/MSLFILES/HC505.EXE).

A derivative of TeX called PDFTeX can be used to generate a PDF file from TeX
sources.  This means that a Texinfo source can also be submitted to PDFTeX,
but I didn't try that.  PDFTeX was port to DJGPP and can be downloaded from
its home site via FTP
(ftp://ftp.cstug.cz/pub/tex/local/cstug/thanh/pdftex-testing/).

There's also a program called `INFNG' that can be used to convert the Info
(*not* Texinfo) version of the FAQ to the Norton Guide format.  `INFNG' is
available from the DJGPP archives
(ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2misc/infng100.zip).

If you know about any format not mentioned above that can be generated using
widely available tools, please drop me a note so I could update this list and
consider that format or those tools for inclusion in a future release of the
FAQ.  If you develop any such tools, consider uploading them to a site where
they will be publicly available, and tell me about that site.

Note that the FAQ sources are heavy users of the Texinfo macro facility, so
any conversion program that doesn't support Texinfo macros will probably have
hard time coping with the FAQ.  When confronted with this problem, try
feeding the converter with the macro-expanded version of the FAQ (the
Makefile in the source distribution has a special target for such cases).

23. About this FAQ
******************

  Maintainer: Eli Zaretskii <eliz@is.elta.co.il>.

  Copyright (C) 1994, 1995, 1996, 1997, 1998 by Eli Zaretskii
<eliz@is.elta.co.il>.  This FAQ may be freely redistributed with the DJGPP
package or any part thereof, provided that you don't prevent anybody else
from redistributing it on the same terms, and that this copyright notice is
left intact.

  Comments about, suggestions for, or corrections to this FAQ list are welcome.
Please make sure to include in your mail the version number of the document
to which your comments apply (you can find the version at the beginning of
this FAQ list).

  Much of the info in this FAQ list was taken from the DJGPP mailing list/news
group traffic, so many of you have (unbeknownst to you) contributed to this
list.  The following people deserve special credit for reading this list in
its previous versions and providing useful feedback, comments, information
and/or suggestions:

     John M. Aldrich <fighteer@cs.net>
     Anthony Appleyard <A.APPLEYARD@fs2.mt.umist.ac.uk>
     Gurunandan R Bhat <grbhat@unigoa.ernet.in>
     John Bodfish <bodfish@austen.notis.com>
     Francois Charton <deef@pobox.oleane.com>
     Alain CULOS <Alain.Culos@bigfoot.com>
     Bill Currie <bill@tanihwa.tssc.co.nz>
     Bill Davidson <bdavidson@ra.isisnet.com>
     DJ Delorie <dj@delorie.com>
     Tom Demmer <Demmer@LStM.Ruhr-Uni-Bochum.De>
     Nate Eldredge <nate@cartsys.com>
     Juergen Erhard <jae@laden.ilk.de>
     Andy Eskilsson <x-aes@telelogic.com>
     Jeremy Filliben <prime@UDel.Edu>
     Peter Gerwinski <peter@agnes.dida.physik.uni-essen.de>
     Till Harbaum <harbaum@ibr.cs.tu-bs.de>
     James W. Haefner <Jim@anolis.bnr.usu.edu>
     Kris Heidenstrom <kheidens@actrix.gen.nz>
     Koen Van Herck <kvhk@barco.com>
     Vik Heyndrickx <Vik.Heyndrickx@rug.ac.be>
     Robert Hoehne <robert.hoehne@gmx.net>
     Gordon Hogenson <ghogenso@u.washington.edu>
     Harry Johnston <omega@es.co.nz>
     Martynas Kunigelis <martynas.kunigelis@vm.ktu.lt>
     Pieter Kunst <kunst@prl.philips.nl>
     Y. Lazarovitch <yitzg@haven.ios.com>
     Alexander Lehmann <lehmann@mathematik.th-darmstadt.de>
     Marty Leisner <leisner@sdsp.mc.xerox.com>
     Dave Love <d.love@dl.ac.uk>
     Randy Maas <randym@acm.org>
     Cameron Mallory <mallory@wcug.vwu.edu>
     Colin S. Miller <csmiller@iname.com>
     Duncan Murdoch <D.J.Murdoch@bristol.ac.uk>
     Rob Nader <naderr@topaz.cqu.edu.au>
     Eric Nicolas <nicolas@JUPITER.saclay.cea.fr>
     Adrian Oboroc <ash@cinf.usm.md>
     Jan Oonk <jan@stack.nl>
     Elliott Oti <e.oti@stud.warande.ruu.nl>
     Bob Paddock <bpaddock@execpc.com>
     Esa A E Peuha <peuha@cc.helsinki.fi>
     Walter Prins <prins@quark.cs.sun.ac.za>
     Steve Salter <salters@admin.fanshawec.on.ca>
     Charles Sandmann <sandmann@clio.rice.edu>
     Terrel Shumway <Shumw001@Cerritos.edu>
     Andrew Szymkowiak <aes@solia.gsfc.nasa.gov>
     Launey Thomas <ljt@sierrasemi.com>
     Chris Tilbury <C.J.Tilbury@estate.warwick.ac.uk>
     Ned Ulbricht <nedu@ee.washington.edu>
     Stephen Turnbull <turnbull@shako.sk.tsukuba.ac.jp>
     Santiago Vila <sanvila@pizarro.unex.es>
     Ronan Waide <waider@waider.ie>
     Morten Welinder <terra@diku.dk>
     Anthony Edward Wesley <awesley@galaxy.anutech.com.au>
     K.B. Williams <Kbwms@aol.com>
     Mark H. Wood <mwood@mhw.OIT.IUPUI.EDU>

24. Topic Index
***************

  This is an alphabetical list of all the topics covered in this FAQ.  Use it
to search for a description of your problem and follow the link to find the
answer(s).



* !proxy method of passing long command lines: Section 16.4.
* * character in command lines: Section 16.1.
* -ansi switch and C++-style comments in C programs: Section 8.3.
* -fconserve-space switch: Section 8.12.
* -lfoo, linker switch: Section 8.22.
* -lstdcx, linker cannot find: Section 8.7.
* -msoft-float switch to GCC: Section 11.4.
* -traditional switch and C++-style comments in C programs: Section 8.3.
* .lib libraries, using with GCC: Section 17.5.
* .o files from EMXAOUT can't be put into a library: Section 17.5.
* .obj object files, using with GCC: Section 17.5.
* /bin/sh in shell scripts: Section 6.11.
* /dev/ directory, problems with DJGPP programs: Section 22.20.
* 16-bit code, using with DJGPP: Section 17.6.
* 16-bit DPMI programs cannot run under DJGPP: Section 6.8.
* 68K targets, cross-compiling with DJGPP: Section 22.8.
* ? character in command lines: Section 16.1.
* @ character, how to pass it to programs: Section 16.3.
* ^Z character at end of DJGPP.ENV: Section 6.10.
* __crt0_glob_function, disable filename globbing: Section 16.2.
* __DJGPP__ pre-processor symbol: Section 8.6.
* __DJGPP_MINOR__ pre-processor symbol: Section 8.6.
* __dpmi_get_memory_information, doesn't change after free/malloc: Section 15.2.
* __dpmi_get_protected_mode_interrupt_vector: Section 18.9.
* __dpmi_get_real_mode_interrupt_vector: Section 18.9.
* __dpmi_int, calling DOS/BIOS services: Section 18.1.
* __dpmi_int, high in program's profile: Section 13.5.
* __dpmi_int, how to pass buffers: Section 18.2.
* __dpmi_int, use to invoke software interrupts: Section 18.3.
* __dpmi_simulate_real_mode_interrupt, need zero SS, SP and FLAGS: Section 18.3.
* __dpmi_YYY vs _go32_XXX, which one to use: Section 18.10.
* __EH_FRAME_BEGIN__, undefined references: Section 8.19.
* __eh_pc and __throw, undefined references: Section 8.10.
* __GO32__ pre-processor symbol: Section 8.6.
* __tb, an alias for the address of transfer buffer: Section 18.2.
* __throw and __eh_pc, undefined references: Section 8.10.
* _AX variable, porting to DJGPP: Section 17.8.
* _BP variable, porting to DJGPP: Section 17.8.
* _BX variable, porting to DJGPP: Section 17.8.
* _control87, change coprocessor setup: Section 11.5.
* _CRT0_FLAG_LOCK_MEMORY, silent failure: Section 18.9.
* _crt0_startup_flags settings and QDPMI: Section 15.3.
* _crt0_startup_flags, setting to lock memory: Section 18.11.
* _crt0_startup_flags, Unix sbrk is incompatible with HW interrupts: Section 18.11.
* _CX variable, porting to DJGPP: Section 17.8.
* _DI variable, porting to DJGPP: Section 17.8.
* _dos_ds, a selector to access conventional memory: Section 18.4.
* _DS variable, porting to DJGPP: Section 17.8.
* _DX variable, porting to DJGPP: Section 17.8.
* _ES variable, porting to DJGPP: Section 17.8.
* _go32_dpmi_allocate_iret_wrapper: Section 18.9.
* _go32_dpmi_chain_protected_mode_interrupt_vector: Section 18.9.
* _go32_remaining_physical_memory, doesn't change after free/malloc: Section 15.2.
* _go32_remaining_physical_memory, under OS/2: Section 15.2.
* _go32_XXX vs __dpmi_YYY, which one to use: Section 18.10.
* _SI variable, porting to DJGPP: Section 17.8.
* _stklen, setting stack size: Section 15.9.
* Abort! message during compilation: Section 6.6.
* Abort! message in C++ programs that use exceptions: Section 8.19.
* Accessing absolute addresses above 1MB: Section 18.7.
* Accessing absolute addresses in conventional memory: Section 18.4.
* Accessing absolute addresses with dedicated selector: Section 18.4.
* Accessing C variables from inline assembly: Section 18.13.
* Accessing VBE 2.0 linear frame buffer: Section 10.2.
* Accessing video memory: Section 10.2.
* Alignment of data by GAS can slow-down code: Section 14.3.
* Allegro library, failure to compile: Section 8.17.
* Allegro, home page and mailing list: Section 4.5.
* Alternate stub, how to use: Section 14.2.
* Announcements, mailing list: Section 20.3.
* Archives, DJGPP mailing list/News group, how to search: Section 6.15.
* Arrays, and code speed: Section 14.2.
* Asking for help: Section 6.16.
* Assembly code crashes when linked with optimized C code: Section 17.4.
* Assembly code, generating with GCC: Section 8.20.
* Assembly functions, which registers to save: Section 17.4.
* Assembly source, converting from AT&T to Intel: Section 17.2.
* Assembly source, converting to AT&T syntax: Section 17.2.
* Assembly source, converting to protected mode: Section 17.3.
* Assembly source, GCC/Gas syntax: Section 17.1.
* Assembly syntax: Section 17.1.
* Asynchronous communications packages for DJGPP: Section 22.3.
* AT&T vs Intel assembly syntax: Section 17.1.
* AT&T-style assembly, converting to Intel: Section 17.2.
* atan, inaccuracies with FP emulator: Section 11.6.
* Automated downloading from a PC: Section 4.7.
* Automated downloading from a Unix box: Section 4.7.
* Automated FTP from a Unix box: Section 4.7.
* Automatic variables, how much memory: Section 15.9.
* Bad format, profiler error message: Section 13.3.
* Binary data I/O: Section 9.3.
* Binutils 2.8.x, slower than 2.7: Section 14.2.
* BIOS service calls: Section 18.1.
* BIOS service calls which need buffers: Section 18.2.
* BIOS setup, influence on compilation speed: Section 7.1.
* Breakpoints don't work in GDB under Windows: Section 12.10.
* Browsing documentation: Section 5.1.
* Buffered I/O, effect of buffer size on I/O speed: Section 14.4.
* Bug report, how to submit: Section 22.2.
* Bug-tracking system for DJGPP: Section 22.2.
* Bugfixes, how to ensure they are done: Section 21.3.
* Bugs, how to browse a list of known DJGPP problems: Section 22.2.
* C compiler overflows its stack for large programs: Section 6.6.
* C library, legal restrictions: Section 19.2.
* C Library, the latest release: Section 21.4.
* C programs compilation, recommended system RAM: Section 3.1.
* C++ class libraries, legal restrictions: Section 19.1.
* C++ class variables under GDB: Section 12.7.
* C++ compiler crashes for large programs: Section 15.9.
* C++ compiler overflows its stack for large programs: Section 6.6.
* C++ debugging with stabs information: Section 12.7.
* C++ exceptions, support by GCC: Section 8.19.
* C++ libraries compiled with v2.8.0 don't mix with 2.8.1: Section 8.10.
* C++ method names under GDB: Section 12.7.
* C++ programs compilation, recommended system RAM: Section 3.1.
* C++ programs, large executable: Section 8.12.
* C++ programs, linking with C functions: Section 8.10.
* C++ programs, problems with packed structs: Section 22.11.
* C++ source, debugger cannot find: Section 12.6.
* C++ STL library, not in lgp271b distribution: Section 8.7.
* C++, missing header files: Section 8.2.
* C++-style comments in C programs, GCC won't compile: Section 8.3.
* Caldera OpenDOS, DPMI services crash DJGPP: Section 6.3.
* Calling 16-bit code from DJGPP: Section 17.6.
* Calling real-mode functions: Section 18.5.
* calloc fails under EMM386 or HIMEM: Section 15.7.
* calloc fails under QDPMI or Windows: Section 15.4.
* calloc fails under Windows 3.X: Section 15.5.
* calloc fails under Windows 9X: Section 15.6.
* calloc, effect on "Fat DS": Section 18.6.
* Can't find node "Top", Info message: Section 6.9.
* Cannot continue from exception message: Section 12.2.
* Cannot exec as, GCC message: Section 6.5.
* Cannot exec cpp, GCC message: Section 6.5.
* Case-sensitivity, while expanding wildcards: Section 16.1.
* CCT mirrors' list: Section 4.2.
* CD-playing library: Section 22.3.
* CD-ROM, accessed by the linker: Section 6.12.
* CD-ROM, getting DJGPP: Section 4.4.
* Chaining interrupt: Section 18.9.
* Changing GNU/DJGPP programs: Section 22.2.
* Child processes, spawning under OS/2: Section 3.2.
* Child programs, how much memory is left: Section 15.8.
* Class method name in GDB: Section 12.7.
* Class static variable name in GDB: Section 12.7.
* Code is slow due to incorrect alignment by GAS: Section 14.3.
* Code page change might prevent MSHELL from working: Section 12.5.
* Code quality, GCC: Section 14.1.
* Code speed, slower in v2.x: Section 14.2.
* Code, DJGPP-specific: Section 8.6.
* COFF output from linker, how to get: Section 12.4.
* COFF output, required for profiling: Section 13.3.
* COFF, why is DJGPP using it: Section 22.21.
* Color text cannot be printed with `printf': Section 9.4.
* Command line, * and ? characters: Section 16.1.
* Command line, disabling filename expansion/globbing: Section 16.2.
* Command line, escaping special characters: Section 16.3.
* Command line, filename expansion/globbing: Section 16.1.
* Command lines, longer than 126 characters: Section 16.4.
* Command-line arguments: Chapter 16.
* Comments, C++-style in C programs: Section 8.3.
* Commercial programs, writing with DJGPP: Section 19.1.
* Compatibility, hardware, general: Chapter 3.
* Compatibility, Linux: Section 3.1.
* Compatibility, Novell NWDOS 7: Section 3.1.
* Compatibility, operating systems, general: Chapter 3.
* Compatibility, OS/2: Section 3.1.
* Compatibility, Warp: Section 3.1.
* Compatibility, Windows 3.X: Section 3.1.
* Compatibility, Windows 9X: Section 3.1.
* Compatibility, Windows/NT: Section 3.1.
* Compilation for debugging: Section 12.1.
* Compilation messages, bogus: Section 8.4.
* Compilation progress, GCC switch: Section 6.4.
* Compilation speed: Section 7.1.
* Compile-time problems: Chapter 8.
* Compiler crashes, which subprogram of: Section 6.13.
* Compiler speed: Chapter 7.
* Compiler, non-DJGPP, crashes under Make: Section 6.8.
* Compiling GCC and CPP: Section 3.8.
* Compiling GCC and CPP, RAM disk: Section 3.9.
* Compiling large programs on DOSEmu: Section 3.4.
* Compiling large programs, disk cache settings: Section 3.8.
* Compiling large programs, RAM disk settings: Section 3.8.
* Compiling large source files: Section 3.8.
* Compiling Objective C sources: Section 8.5.
* Compiling, on machines without a co-processor: Section 6.4.
* complex.h functions, linker can't find: Section 8.10.
* Complex.h, GCC can't find: Section 8.2.
* Compressing DJGPP executables: Section 8.13.
* Configuration, for optimal performance: Section 3.9.
* Configuration, reasonable: Section 3.8.
* Configuration, the best: Section 3.7.
* Conventional memory, moving data to/from: Section 18.4.
* Conversion of the FAQ to different formats: Section 22.25.
* Converting DOS .obj/.lib files to GCC: Section 17.5.
* Converting DOS code to DJGPP: Chapter 17.
* Coprocessor setup, change with _control87: Section 11.5.
* Copyleft, effect on DJGPP: Section 19.1.
* Copyright issues: Chapter 19.
* Crash message, how to interpret: Section 12.2.
* Crash traceback, how to read: Section 9.2.
* Crash traceback, saving to a file: Section 12.2.
* Crash, DJGPP programs: Chapter 6.
* Crash, numeric exception: Section 11.5.
* Crashes, general troubleshooting: Section 6.13.
* Crashes, v2.0 programs: Section 9.1.
* Critical error handling in DJGPP: Section 22.12.
* Cross-compiling with DJGPP: Section 22.8.
* crt0.o, GCC can't find: Section 8.1.
* Ctrl-C in debugged programs: Section 12.10.
* Curses library for DJGPP: Section 4.5.
* Cygnus GCC port to Windows: Section 3.3.
* Cygnus port of GCC for Windows 9X and NT: Section 3.6.
* DEADBEEF, use to spot uninitialized memory: Section 9.1.
* Debugger cannot find C++ source: Section 12.6.
* Debugger causes programs to overflow the stack: Section 15.9.
* Debugger crashes on programs compiled for profiling: Section 12.10.
* Debugger crashes on programs which use exceptions: Section 12.10.
* Debugger crashes under QEMM/QDPMI: Section 12.3.
* Debugger doesn't know about #include'd source: Section 12.8.
* Debugger doesn't pass signals to debuggee: Section 12.10.
* Debugger GP Faults on Windows 3.X: Section 12.10.
* Debugger, usage: Section 12.1.
* Debuggers for DJGPP programs: Section 12.1.
* Debugging C++ programs: Section 12.6.
* Debugging C/C++ code generated by another program: Section 12.8.
* Debugging graphics programs: Section 12.5.
* Debugging issues: Chapter 12.
* Debugging programs which crash: Section 12.2.
* Debugging symbols, how to strip from executables: Section 8.13.
* Debugging with GDB, needs COFF output: Section 12.4.
* Debugging, library functions: Section 21.4.
* Deleting a package: Section 4.8.
* Development environments for DJGPP: Section 22.3.
* Development of DJGPP, how to contribute: Section 21.3.
* Differences between SimTel and CCT ftp sites: Section 4.1.
* Direct hardware access on Windows/NT: Section 3.3.
* Directories accessed by the linker: Section 6.12.
* DirectX programming: Section 22.3.
* Disabling globbing in filenames: Section 16.2.
* Disabling QDPMI: Section 12.3.
* Disabling virtual memory for CWSDPMI: Section 7.1.
* Disabling wildcard expansion: Section 16.2.
* Disk cache, influence on compilation speed: Section 7.1.
* Disk cache, recommended settings: Section 3.9.
* Disk cache, when compiling large programs: Section 3.8.
* Disk I/O, compared with Linux: Section 14.4.
* Disk space, required for installation: Section 3.1.
* Disk space, using less of it: Section 4.7.
* Disks, accessed by the linker: Section 6.12.
* Display or set static variables inside debugger: Section 12.9.
* Distributing DJGPP programs: Section 9.5.
* Distributing DJGPP programs, FP emulator: Section 11.1.
* DJGPP applications, legal restrictions: Section 19.1.
* DJGPP archives, how to search: Section 6.15.
* DJGPP as cross-compiler: Section 22.8.
* DJGPP distribution, list of: Section 4.5.
* DJGPP Documentation: Chapter 5.
* DJGPP documentation, in man page format: Section 5.5.
* DJGPP documentation, in PostScript format: Section 5.3.
* DJGPP documentation, look in source distributions: Section 5.4.
* DJGPP documentation, printing: Section 5.3.
* DJGPP documentation, reading as ASCII file: Section 5.2.
* DJGPP documentation, reading with a Web browser: Section 5.3.
* DJGPP documentation, see source files: Section 5.6.
* DJGPP documentation, where to find it: Section 5.1.
* DJGPP environment variable, how to set and test: Section 8.1.
* DJGPP environment variable, setting under LFN: Section 8.1.
* DJGPP mailing list, how to post: Section 20.2.
* DJGPP mailing list, how to subscribe: Section 20.3.
* DJGPP mailing list, how to unsubscribe: Section 20.4.
* DJGPP mailing list, in digest form: Section 20.3.
* DJGPP mailing list/news group, read via WWW: Section 20.4.
* DJGPP programs, problems with: Chapter 6.
* DJGPP programs, problems with DPMI host: Section 6.3.
* DJGPP programs, profiling: Section 13.1.
* DJGPP release schedule: Section 21.3.
* DJGPP software, where to upload: Section 22.7.
* DJGPP users, asking for help: Section 6.16.
* DJGPP utilities, legal restrictions: Section 19.2.
* DJGPP v2.x, alternative DPMI hosts: Section 21.2.
* DJGPP won't run, prints "No DPMI": Section 6.2.
* DJGPP, a list of packages: Section 4.5.
* DJGPP, downloading via e-mail: Section 4.4.
* DJGPP, downloading with FTP: Section 4.3.
* DJGPP, downloading with Gopher: Section 4.4.
* DJGPP, downloading with WWW: Section 4.4.
* DJGPP, history of the project: Section 22.6.
* DJGPP, how to get it: Chapter 4.
* DJGPP, sample code: Section 22.3.
* DJGPP, what it is: Chapter 2.
* DJGPP, where to download: Section 4.1.
* DJGPP-ANNOUNCE mailing list: Section 20.3.
* DJGPP-compiled programs can't find DPMI: Section 9.5.
* DJGPP-specific code: Section 8.6.
* DJGPP.ENV file causes GCC 2.8 to hang: Section 6.1.
* DJGPP.ENV syntax explained: Section 8.1.
* DJGPP.ENV, trailing junk crashes Info: Section 6.3.
* djgpp_first_ctor, unresolved by linker: Section 8.11.
* djgpp_first_dtor, unresolved by linker: Section 8.11.
* DMA, using from DJGPP programs: Section 18.14.
* Documentation, converting to plain ASCII: Section 5.2.
* Documentation, converting to PostScript format: Section 5.3.
* Documentation, in man page format: Section 5.5.
* Documentation, in PostScript format: Section 5.3.
* Documentation, inside source distribution archives: Section 5.4.
* Documentation, reading: Section 5.1.
* Documentation, the profiler: Section 13.4.
* DOS code, using with GCC: Section 17.6.
* DOS libraries, using with GCC: Section 17.5.
* DOS Mode, Windows suggests for graphics programs: Section 10.3.
* DOS object files, using with GCC: Section 17.5.
* DOS programs, converting to DJGPP: Chapter 17.
* DOS service calls: Section 18.1.
* DOS service calls which need buffers: Section 18.2.
* DOSEmu, incompatibilities with DJGPP: Section 3.4.
* DOSEmu, slow response to interactive programs: Section 3.4.
* Double Fault message, after Ctrl-C, Ctrl-BREAK: Section 12.2.
* Downloading DJGPP: Section 4.1.
* Downloading DJGPP via e-mail: Section 4.3.
* Downloading DJGPP with FTP: Section 4.3.
* Downloading DJGPP with WWW: Section 4.4.
* Downloading, individual DJGPP files: Section 4.5.
* DPMI host bugs, might crash DJGPP programs: Section 6.3.
* DPMI hosts, commercially available: Section 21.2.
* DPMI services, problems with Novell NWDOS 7: Section 3.1.
* DPMI services, required to run DJGPP: Section 3.1.
* DPMI spec, where to get it: Section 22.5.
* DPMI, required to run DJGPP programs: Section 9.5.
* DPMI, what it is: Section 22.5.
* Drives, accessed by the linker: Section 6.12.
* DXE can be debugged with EDEBUG32: Section 12.1.
* DXE description: Section 22.14.
* DXE docs and examples: Section 22.14.
* DXE, undefined references: Section 22.14.
* Dynamically loaded code for DJGPP: Section 22.3.
* E-mail, downloading DJGPP: Section 4.4.
* ELF, switching DJGPP to: Section 22.21.
* Emulation, floating-point: Chapter 11.
* Emulator library: Section 11.1.
* Emulator, floating-point inaccuracies: Section 11.6.
* Environment size affects spawning child programs: Section 16.5.
* Environment variable DJGPP is not defined message: Section 6.6.
* Environment variable DJGPP point to file which does not exist message: Section 6.6.
* Environment variable DJGPP points to a wrong or corrupt file message: Section 6.6.
* Environment variables, DJGPP: Section 3.7.
* Environment variables, linker: Section 8.9.
* Error messages, redirecting to a file: Section 6.14.
* Exceptions, C++, support by GCC: Section 8.19.
* Exceptions, with -fsjlj-exceptions: Section 8.19.
* Excessive paging, tuning CWSDPMI: Section 3.9.
* EXE compressor for DJGPP: Section 8.13.
* Executable size, how to make smaller: Section 8.13.
* Executable, bloated by static array: Section 8.12.
* Executable, how to strip off debugging symbols: Section 8.13.
* extern "C" qualifier: Section 8.10.
* FAQ, conversion to different formats: Section 22.25.
* Far pointer memory access: Section 10.2.
* far, declaration, porting to DJGPP: Section 17.7.
* FAT32 support under DOSEmu: Section 3.4.
* File format not recognized by GCC: Section 8.4.
* File handles, under Windows: Section 9.6.
* File I/O, compared with Linux: Section 14.4.
* Filename globbing: Section 16.1.
* Filename globbing, disabling: Section 16.2.
* Filename wildcards expansion: Section 16.1.
* Filename wildcards, disabling expansion: Section 16.2.
* Files, max open simultaneously: Section 9.6.
* Files, minimum set to download: Section 4.5.
* Files, missing, where to download: Section 4.5.
* Files, reading and writing: Section 9.3.
* Files, required disk space: Section 4.6.
* FILES= directive: Section 9.6.
* Flex programs, linking: Section 8.7.
* Floating Point exception message: Section 12.2.
* Floating-point emulation: Chapter 11.
* Floating-point emulation doesn't work: Section 11.1.
* Floating-point emulation under debugger: Section 12.10.
* Floating-point emulation, -msoft-float switch: Section 11.4.
* Floating-point emulation, non-DJGPP emulators: Section 11.2.
* Floating-point emulation, under OS/2: Section 11.3.
* Floating-point exception in Objective-C program: Section 11.7.
* Floating-point instructions and GNU Make: Section 3.4.
* Floating-point issues: Chapter 11.
* Floating-point math functions, standard and high-quality: Section 8.7.
* Floating-point, debugger support: Section 12.1.
* FNCASE variable and wildcard expansion: Section 16.1.
* FP_SEG and FP_OFF, porting to DJGPP: Section 17.7.
* FPU emulation slows down programs: Section 14.5.
* free doesn't change virtual memory: Section 15.2.
* fstream truncates files open for read/write: Section 9.3.
* FTP, downloading DJGPP: Section 4.3.
* FTP, downloading DJGPP in batch mode: Section 4.7.
* Functions from libm.a crash with SIGFPE: Section 11.8.
* Functions, which is in what library: Section 8.8.
* Game programming, libraries and techniques for DJGPP: Section 22.3.
* Garbage at end of number, GCC message: Section 22.9.
* GCC aborts with "Installation problem, cannot exec as": Section 6.5.
* GCC aborts with "Installation problem, cannot exec cpp": Section 6.5.
* GCC aborts with "Internal compiler error": Section 6.6.
* GCC can't recognize file format: Section 8.4.
* GCC can't recognize source language: Section 8.4.
* GCC crashes, which subprogram of: Section 6.13.
* GCC hangs/crashes under Make: Section 6.8.
* GCC says "Abort!" during compilation: Section 6.6.
* General Protection Fault message: Section 12.2.
* Getting DJGPP: Chapter 4.
* Getting DJGPP from a CD-ROM: Section 4.4.
* Getting documentation: Section 5.1.
* Getting more help: Chapter 20.
* Globbing and file name letter-case: Section 16.1.
* Globbing in filenames: Section 16.1.
* Globbing in filenames, disabling: Section 16.2.
* GNU Copyleft, effect on DJGPP: Section 19.1.
* GNU development utilities, port to DJGPP: Section 22.3.
* GNU News groups, don't post DJGPP problems: Section 20.1.
* GNU packages, how to change: Section 22.2.
* Gopher, downloading DJGPP: Section 4.4.
* gotoxy doesn't work with `printf': Section 9.4.
* GPL, effect on DJGPP: Section 19.1.
* Graphics driver setup: Section 10.1.
* Graphics issues: Chapter 10.
* Graphics print-out, using GRX: Section 4.5.
* Graphics programs, and Windows DOS Mode: Section 10.3.
* Graphics programs, debugging: Section 12.5.
* Graphics screen messed up under Windows: Section 10.3.
* Graphics, direct video access: Section 10.2.
* Graphics, limitations on Windows/NT: Section 3.3.
* GUI libraries for DJGPP: Section 22.3.
* Gurus, asking for help: Section 6.16.
* Handles, maximum available number: Section 9.6.
* Hang, all DJGPP programs: Section 6.3.
* Hang, DJGPP programs: Chapter 6.
* harderr function, emulating under DJGPP: Section 22.12.
* Hardware interrupt handler crashes: Section 18.11.
* Hardware interrupts, hooking: Section 18.9.
* Hardware interrupts, subtleties: Section 18.11.
* Hardware requirements: Chapter 3.
* Hardware requirements, minimal: Section 3.1.
* Hardware-oriented programming: Chapter 18.
* Header files, C++, GCC can't find: Section 8.2.
* Header files, GCC can't find: Section 8.1.
* Help, asking for: Section 6.16.
* History of DJGPP: Section 22.6.
* HTML format, DJGPP documentation: Section 5.3.
* huge, declaration, porting to DJGPP: Section 17.7.
* I/O speed, DJGPP programs: Section 14.4.
* i286: Section 3.5.
* i386SX: Section 3.1.
* Inaccuracies, using emulator: Section 11.6.
* Including source code, problems with debugging: Section 12.8.
* Incompatibilities, i286: Section 3.5.
* Incompatibilities, Linux DOSEmu: Section 3.4.
* Incompatibilities, OS/2: Section 3.2.
* Incompatibilities, Warp: Section 3.2.
* Incompatibilities, Windows/NT: Section 3.3.
* Info hangs for non-existent topics: Section 6.9.
* Info viewer crashes at startup: Section 6.10.
* Info waits for 15 seconds: Section 6.9.
* Info won't display a file: Section 6.9.
* Inheritance, file handles: Section 9.6.
* Inline assembly, how to write: Section 18.13.
* Inline assembly, inaccurate SYMIFY output: Section 9.2.
* Inline functions, linker won't find: Section 8.10.
* inp function: Section 18.12.
* Installation of Info docs, a utility: Section 4.5.
* Installation, dual, DOS/Windows: Section 22.18.
* Installing DJGPP on networked drives: Section 3.9.
* Int 24h crashes DJGPP programs: Section 22.12.
* int86 crashes program: Section 18.1.
* int86, problems with mouse interface: Section 18.1.
* int86/intdos, garbled results in registers: Section 18.1.
* int86/intdos, registers' width: Section 18.1.
* int86x/intdosx, how to pass a buffer: Section 18.2.
* intdos crashes program: Section 18.1.
* Intel vs AT&T assembly syntax: Section 17.1.
* Intel-style assembly code, using with DJGPP: Section 17.2.
* Interactive programs, screen I/O: Section 9.4.
* Internal compiler error, when compiling C++ programs: Section 6.6.
* Interrupt 24h handling: Section 22.12.
* Interrupt chaining: Section 18.9.
* Interrupt frequency, maximum: Section 18.11.
* Interrupt handlers, locking memory: Section 18.11.
* Interrupt reflection: Section 18.9.
* Interrupt reflection overhead: Section 18.11.
* Interrupts 1Ch, 23h, 24h: Section 18.9.
* Interrupts handlers in DJGPP: Section 18.9.
* Invalid TSS in RMCB message: Section 12.2.
* Invoking v2 programs from v1.x programs: Section 22.13.
* iostream functions, linker can't find: Section 8.10.
* iostream library, why use it: Section 8.7.
* iostream.h, GCC can't find: Section 8.2.
* iostreamP.h, GCC can't find: Section 8.2.
* Jargon, used by DJGPP documentation: Section 22.23.
* Keyboard interrupt cannot be hooked under debugger: Section 12.10.
* Keystrokes don't get to keyboard handler: Section 18.11.
* Known bugs in DJGPP, how to browse: Section 22.2.
* ldexp crashes programs with FP exception: Section 11.8.
* Legal aspects of DJGPP programming: Chapter 19.
* Legal restrictions on DJGPP apps: Section 19.1.
* Legal restrictions, DJGPP utilities: Section 19.2.
* Length of command line: Section 16.5.
* Letter case in filenames submitted to GCC: Section 8.4.
* Lexicon for DJGPP documentation: Section 22.23.
* LFN API, not supported by Windows/NT: Section 3.3.
* LFN driver for NT, alpha version: Section 3.3.
* LFN problems, in DJGPP v2.0: Section 22.15.
* LGPL, effect on DJGPP: Section 19.1.
* libc for DJGPP, patched version: Section 21.4.
* libc2.tex, missing file: Section 5.3.
* libg++ library: Section 8.7.
* libgcc.a, should be in sync with the compiler: Section 8.10.
* libgpp library: Section 8.7.
* libgpp.a, legal restrictions: Section 19.1.
* libiostream.a, legal restrictions: Section 19.1.
* Libraries, converting to DJGPP: Chapter 17.
* Libraries, creating with RHIDE: Section 8.22.
* Libraries, GCC can't find: Section 8.1.
* Libraries, object, how to create/update: Section 8.22.
* Libraries, optional, how to link: Section 8.7.
* Libraries, order on compilation/link command line: Section 8.9.
* Libraries, searching for functions: Section 8.8.
* Library compiled for debugging/profiling: Section 21.4.
* Library docs, missing libc2.tex: Section 5.3.
* Library docs, problems in generating printed version: Section 5.3.
* Library functions, C++, linker won't find: Section 8.10.
* Library functions, linker won't find: Section 8.7.
* Library functions, linker won't find in non-default directories: Section 8.9.
* Library functions, linker won't find, libraries' order: Section 8.9.
* Library, floating-point emulation: Section 11.1.
* Library, updated, where to get: Section 21.4.
* libstdc++ standard templates library: Section 8.7.
* Linear frame buffer access: Section 10.2.
* Link-time problems: Chapter 8.
* Linker can't find library functions: Section 8.7.
* Linker can't find some C++ library functions: Section 8.10.
* Linker cannot find -lstdcx: Section 8.7.
* Linker fails because of Windows 9X shortcut files: Section 8.14.
* Linker fails for a.out files in a library: Section 8.16.
* Linker fails for large libraries or object files: Section 8.16.
* Linker fails for obj files converted by EMXAOUT: Section 8.16.
* Linker fails to find crt0.o under Novell: Section 8.1.
* Linker fails to produce executable under Novell: Section 8.15.
* Linker speed: Chapter 7.
* Linker won't find djgpp_first_dtor symbol: Section 8.11.
* Linker, accesses random drives: Section 6.12.
* Linker, from RSXNTDJ, and unresolved externals: Section 3.6.
* Linking against optional libraries: Section 8.7.
* Linking C functions with C++ programs: Section 8.10.
* Linking C++ programs, use the GXX driver: Section 8.7.
* Linking Flex programs: Section 8.7.
* Linking programs, unresolved C++ library functions: Section 8.10.
* Linking programs, unresolved library functions: Section 8.7.
* Linking programs, unresolved library functions, libraries' order: Section 8.9.
* Linking speed, improve by stub-editing ld.exe: Section 7.2.
* Links, symbolic, simulation with DJGPP: Section 22.4.
* Linux-to-DOS cross-compiling with DJGPP: Section 22.8.
* List of DJGPP packages: Section 4.5.
* Listing, assembly and source code: Section 8.20.
* Load error--no DPMI: Section 6.2.
* Locking memory for hardware interrupt handlers: Section 18.9.
* Locking memory for interrupt handlers: Section 18.11.
* Locking memory, silent failure: Section 18.9.
* Long command lines: Section 16.4.
* Long command lines, from Makefile: Section 16.6.
* Long command lines, maximum length: Section 16.5.
* Long command lines, problems with RHIDE: Section 16.6.
* long filename support, bugs in DJGPP v2.0: Section 22.15.
* Long Filenames aren't supported on Windows/NT: Section 3.3.
* Long filenames in setting DJGPP env. variable: Section 8.1.
* Low-level programming issues: Chapter 18.
* Machines with low extended RAM, tuning CWSDPMI: Section 3.9.
* Makefile, first character of every command must be TAB: Section 22.16.
* Makefile, passing long command lines: Section 16.6.
* Makefiles with long command lines: Section 16.4.
* malloc doesn't change virtual memory: Section 15.2.
* malloc fails under EMM386 or HIMEM: Section 15.7.
* malloc fails under QDPMI or Windows: Section 15.4.
* malloc fails under Windows 3.X: Section 15.5.
* malloc fails under Windows 9X: Section 15.6.
* malloc in small chunks fails: Section 15.4.
* malloc, debugging: Section 22.3.
* malloc, effect on "Fat DS": Section 18.6.
* Man pages, how to read: Section 5.5.
* Mangling C++ identifiers, GNU style: Section 12.7.
* Math functions crash with SIGFPE: Section 11.8.
* Math library, default ANSI/ISO and high-quality functions: Section 8.7.
* math.h, conflicts with C++ programs: Section 8.19.
* Maximum interrupt frequency: Section 18.11.
* Maximum length of command line: Section 16.5.
* Memory allocation fails under EMM386 or HIMEM: Section 15.7.
* Memory allocation fails under QDPMI or Windows 9X: Section 15.4.
* Memory allocation fails under Windows 3.X: Section 15.5.
* Memory allocation fails under Windows 9X: Section 15.6.
* Memory allocation in small chunks fails: Section 15.4.
* Memory allocations, debugging packages: Section 22.3.
* Memory at run time: Chapter 15.
* Memory locking for hardware interrupt handlers: Section 18.9.
* Memory locking, silent failure: Section 18.9.
* Memory manager, settings for optimal performance: Section 3.9.
* Memory managers, recommended for use with DJGPP: Section 3.9.
* Memory size reported by go32-v2: Section 4.6.
* Memory, how much is left for spawned programs: Section 15.8.
* Memory, virtual, failure to allocate: Section 15.3.
* Memory, virtual, free doesn't change: Section 15.2.
* Memory, virtual, malloc doesn't change: Section 15.2.
* Memory, virtual, maximum available: Section 15.1.
* Memory, virtual, QDPMI failure: Section 15.3.
* Memory-mapped devices above 1MB: Section 18.7.
* Memory-mapped devices, accessing with dedicated selector: Section 18.4.
* Memory-mapped devices, fast access: Section 18.6.
* Memory-mapped devices, moving data to/from: Section 18.4.
* Mesa programming: Section 22.3.
* Method name in C++, how to pass to GDB: Section 12.7.
* Minimal hardware requirements: Section 3.1.
* Minimum system RAM: Section 3.1.
* Minimum system RAM, CWSDPMI: Section 3.1.
* Missing C++ header files: Section 8.2.
* Missing crt0.o: Section 8.1.
* Missing DJGPP files, downloading: Section 4.5.
* Missing header files: Section 8.1.
* Missing libraries: Section 8.1.
* Missing separator, Make error message: Section 22.16.
* Mixing v2.0 GCC with CC1PLUS from v1.x: Section 6.7.
* Mixing v2.x Make with v1.x programs hangs the machine: Section 6.8.
* MK_FP macro, porting to DJGPP: Section 17.7.
* Mode switches, effect on program speed: Section 14.1.
* Modification time in the future, message from Make: Section 22.17.
* Monochrome display and profiling: Section 13.2.
* Monochrome monitor device driver: Section 12.5.
* Monochrome monitor, redirecting screen output: Section 12.5.
* Monochrome monitor, support in RHIDE: Section 12.5.
* More help, how to get: Chapter 20.
* Motorola 68K targets, cross-compiling with DJGPP: Section 22.8.
* Mouse callback crashes with Page Fault in RMCB: Section 18.11.
* Mouse handler, how to install with DJGPP: Section 18.8.
* Mouse interface, problems with int86: Section 18.1.
* Mouse usage crashes RHIDE on DOSEmu: Section 3.4.
* movedata.h header, compilation problems: Section 8.21.
* Moving data to and from conventional memory: Section 18.4.
* Moving data to and from transfer buffer: Section 18.4.
* MS-Windows programming under DJGPP: Section 3.6.
* Multitasking packages for DJGPP: Section 22.3.
* NameNumericTail: Section 22.18.
* near, declaration, porting to DJGPP: Section 17.7.
* Nearptr functions: Section 18.6.
* nearptr method of direct memory access: Section 18.4.
* Nested programs, how much memory is left: Section 15.8.
* Network installation: Section 3.9.
* Network installation makes linking slow: Section 7.2.
* Network interface libraries for DJGPP: Section 22.3.
* New features in v2: Section 21.1.
* No DPMI error message: Section 6.2.
* No free XMS memory when NOEMS parameter is used: Section 15.8.
* Non-DJGPP floating-point emulators: Section 11.2.
* Not COFF error message from DJGPP programs: Section 6.7.
* Novell NDOS, buggy DPMI services crash DJGPP: Section 6.3.
* Novell, linker or STUBIFY don't produce executable: Section 8.15.
* NULL pointer: Section 12.2.
* Null pointer dereference crashes v2.0 programs: Section 9.1.
* NULL, redefinition in C++ header files: Section 8.18.
* Numeric exception, program crash: Section 11.5.
* Numeric tails, created by PKUNZIP v2.50: Section 22.18.
* Numeric tails, turning off: Section 22.18.
* Object libraries, creating with RHIDE: Section 8.22.
* Object libraries, how to create/update: Section 8.22.
* Objective C, compiling: Section 8.5.
* Objective-C programs crash with FP exception: Section 11.7.
* obstack package: Section 8.7.
* OpenGL programming: Section 22.3.
* Optimal performance, CWSDPMI tuning: Section 3.9.
* Optimal performance, disk cache settings: Section 3.9.
* Optimal performance, RAM disk settings: Section 3.9.
* Optimal performance, system configuration: Section 3.9.
* Optimization bugs, in PGCC with -O7 and higher: Section 14.2.
* Optimization crashes GCC: Section 6.4.
* Optimization, GCC switches: Section 14.2.
* Optimizing DJGPP programs: Section 13.1.
* OS/2 supports up to 512MB of DPMI memory: Section 3.10.
* outp function: Section 18.12.
* Overhead, interrupt reflection to protected mode: Section 18.11.
* Packages, DJGPP, list of: Section 4.5.
* Packages, ported to DJGPP: Section 22.3.
* Packages, required disk space: Section 4.6.
* Packages, which to download: Section 4.5.
* Packed structs, C++ bug: Section 22.11.
* Packing the structs: Section 22.10.
* Page fault error message from CWSDPMI: Section 9.1.
* Page Fault in RMCB message: Section 18.11.
* Page Fault message: Section 12.2.
* Paging starts before all RAM is used: Section 15.7.
* Paging, how to disable: Section 18.9.
* Patched libc, where to find: Section 21.4.
* Patches for DJGPP, how to submit: Section 22.2.
* PATH, non-DJGPP binaries can crash GCC: Section 6.8.
* Peek/poke absolute address: Section 18.4.
* Pentium-optimized code: Section 14.3.
* Performance issues: Chapter 14.
* Peripheral devices above 1MB: Section 18.7.
* Peripheral devices, fast access: Section 18.6.
* Peripheral devices, reading/writing ports: Section 18.12.
* Peripherals, moving data to/from: Section 18.4.
* PerVMFiles= directive: Section 9.6.
* Physical memory, more than 64MB: Section 3.10.
* Pi, accurate computation: Section 11.6.
* Pipe errors in shell scripts: Section 6.11.
* Platform SDK, for RSXNTDJ: Section 3.6.
* Port reading/writing: Section 18.12.
* Ported programs run much slower: Section 14.5.
* Posting problems, not to GNU News groups: Section 20.1.
* Posting to DJGPP mailing list: Section 20.2.
* PostScript documentation: Section 5.3.
* Pre-processor symbols, DJGPP-specific: Section 8.6.
* printf cannot print color text: Section 9.4.
* Printing DJGPP documentation: Section 5.3.
* Printing graphics, using GRX: Section 4.5.
* Problems with DJGPP programs: Chapter 6.
* Problems, asking for help: Section 6.16.
* Problems, searching for solution in DJGPP archives: Section 6.15.
* Profiled programs crash under debugger: Section 12.10.
* Profiler documentation: Section 13.4.
* Profiler produces no output: Section 13.6.
* Profiling DJGPP programs: Section 13.1.
* Profiling DJGPP programs, need COFF output: Section 13.3.
* Profiling issues: Chapter 13.
* Profiling programs that terminate abnormally: Section 13.6.
* Profiling, library functions: Section 21.4.
* Profiling, library routines: Section 13.5.
* Profiling, program crashes or runs slowly: Section 13.2.
* Program counter, converting to source lines: Section 9.2.
* Program crashes accessing empty floppy/CD-ROM drives: Section 22.12.
* Program crashes because of Int 24h: Section 22.12.
* Program crashes in int86/intdos: Section 18.1.
* Program crashes in v2.0, but not in v1.x: Section 9.1.
* Program crashes while allocating memory: Section 15.4.
* Programs crash when compiled for profiling: Section 13.2.
* Programs crash with SIGSEGV due to small stack size: Section 15.9.
* Programs crash, general troubleshooting: Section 6.13.
* Programs crash, numeric exception: Section 11.5.
* Programs crash, saving debugging output: Section 6.14.
* Programs crash, searching DJGPP archives: Section 6.15.
* Programs run slowly when compiled with -pg: Section 13.2.
* Programs that exit abnormally, how to profile: Section 13.6.
* Programs using nearptr fail on Windows/NT: Section 3.3.
* Protected mode and converted assembly code: Section 17.3.
* Protected-mode interrupt vector: Section 18.9.
* Pseudo-random numbers: Section 22.22.
* Pseudo-register variables, porting to DJGPP: Section 17.8.
* Quotes, how to pass them to programs: Section 16.3.
* RAM disk, influence on compilation speed: Section 7.1.
* RAM disk, recommended settings: Section 3.9.
* RAM disk, when compiling large programs: Section 3.8.
* rand and random functions, comparison: Section 22.22.
* Random numbers, how to produce: Section 22.22.
* RCS port to DJGPP: Section 22.3.
* Read DJGPP traffic via WWW: Section 20.4.
* Reading an int from a binary file: Section 22.10.
* Reading documentation: Section 5.1.
* Reading documentation with a Web browser: Section 5.2.
* Reading documentation with text editor/viewer: Section 5.2.
* Reading documentation, converting to plain ASCII: Section 5.2.
* Reading structs from disk files: Section 22.10.
* Real-mode call-back: Section 18.8.
* Real-mode functions, how to call: Section 18.5.
* Real-mode interrupt vector: Section 18.9.
* Real-mode services, calling DJGPP functions: Section 18.8.
* realloc, effect on "Fat DS": Section 18.6.
* Reboot, every DJGPP program: Section 6.3.
* Reboot, when running DJGPP programs: Chapter 6.
* Recommended system RAM, for C programs compilation: Section 3.1.
* Recommended system RAM, for C++ programs compilation: Section 3.1.
* Recompiling GCC: Section 22.2.
* Redefinition of class exception, compiler message: Section 8.19.
* Redefinition of NULL in C++ headers: Section 8.18.
* Redirecting GCC messages to a file: Section 6.14.
* Redirection in Makefile, effect on long command lines: Section 16.6.
* Redirection, using the REDIR program: Section 16.6.
* regex package from GNU: Section 8.7.
* Regex.h, GCC can't find: Section 8.2.
* Registers, which ones to save in assembly code: Section 17.4.
* Release schedule, how to influence: Section 21.3.
* Removing a package: Section 4.8.
* Required hardware, general: Chapter 3.
* Resource compiler, doesn't work in RSXNTDJ: Section 3.6.
* Response file, passing long command lines: Section 16.4.
* Run-time environment in v2.x: Section 21.2.
* Run-time performance: Chapter 14.
* Run-time problems: Chapter 9.
* Runtime speed, slower in v2.x: Section 14.2.
* sbrk algorithm and QDPMI: Section 15.3.
* sbrk, effect on "Fat DS": Section 18.6.
* sbrk, Unix-like algorithm is incompatible with HW interrupts: Section 18.11.
* Screen contents not restored under Windows: Section 10.3.
* Screen I/O: Section 9.4.
* SDK, for RSXNTDJ: Section 3.6.
* Searching DJGPP archives: Section 6.15.
* Seed for random numbers: Section 22.22.
* segread function, how to port to DJGPP: Section 18.2.
* Setting up DJGPP with EMM386: Section 3.9.
* setvbuf, effect on I/O speed: Section 14.4.
* Shell scripts, failures and crashes: Section 6.11.
* SHELL= variable in Makefile, effect on long command lines: Section 16.6.
* Shortcut files under Windows 9X fail DJGPP linker: Section 8.14.
* Signals in debugged programs: Section 12.10.
* SimTel mirrors' list: Section 4.1.
* Single-stepping doesn't work in GDB on Windows 3.X: Section 12.10.
* Single-stepping doesn't work in RHIDE on Windows 3.X: Section 12.10.
* Size of a struct under DJGPP: Section 22.10.
* sizeof, result when called on a structure: Section 22.10.
* Slow code, due to bad alignment by GAS: Section 14.3.
* Slow compilation: Section 7.1.
* Slow compilation, tuning CWSDPMI: Section 3.9.
* Slow linking, possible reasons: Section 7.2.
* Slow-down, programs ported from other compilers: Section 14.5.
* Slow-down, when resident software uses XMS: Section 14.5.
* Software interrupts, need zero SS, SP and FLAGS: Section 18.3.
* Solved problems, searching in DJGPP archives: Section 6.15.
* Sound Blaster code for DJGPP: Section 22.3.
* Source files, using as the best docs: Section 5.6.
* Source language is not recognized by GDB in C++ programs: Section 12.7.
* Source line from the EIP, using GDB: Section 9.2.
* Spawned programs, how much memory is left: Section 15.8.
* Spawning child processes, OS/2: Section 3.2.
* Spawning child programs on Windows/NT and 9X: Section 3.3.
* Spawning programs, effect of environment size: Section 16.5.
* Spawning v2 programs from v1.x programs: Section 22.13.
* Spawning v2.x programs from v1.x programs doesn't work: Section 6.8.
* Speed of array-based programs: Section 14.2.
* Speed of code, recommended GCC switches: Section 14.2.
* Speed of compilation: Section 7.1.
* Stack dump, how to read: Section 9.2.
* Stack Fault message: Section 12.2.
* Stack overflow under debugger: Section 15.9.
* Stack size under DJGPP: Section 15.9.
* Stack size, in RSXNTDJ programs: Section 3.6.
* Stack size, insufficient, causes programs to crash: Section 15.9.
* Stack, misalignment causes slow-down: Section 14.2.
* Stand-alone DJGPP programs that don't need DPMI: Section 9.5.
* Standard output/error stream, redirecting to a file: Section 6.14.
* Static array enlarges C++ executable: Section 8.12.
* Static uninitialized variables, failure debugging: Section 12.9.
* stdiostream.h, GCC can't find: Section 8.2.
* STL library, not in lgp271b distribution: Section 8.7.
* streambuf.h, GCC can't find: Section 8.2.
* String.h, GCC can't find: Section 8.2.
* Struct declaration, for real-mode services: Section 18.5.
* struct reading from a disk file: Section 22.10.
* Struct, size in bytes under DJGPP: Section 22.10.
* Structure packing, C++ bug: Section 22.11.
* Structure padding: Section 22.10.
* STUB, environment variable: Section 14.2.
* Stub, how to use non-default one: Section 14.2.
* Subscription to DJGPP mailing list: Section 20.3.
* Subsidiary programs, how much memory is left: Section 15.8.
* SVGA types supported by GRX: Section 10.1.
* Symbolic links, simulation with DJGPP: Section 22.4.
* sys/movedata.h header, compilation errors: Section 8.21.
* System configuration, the best: Section 3.7.
* system function doesn't call COMMAND.COM: Section 16.4.
* System RAM, minimum: Section 3.1.
* Systems programming issues: Chapter 18.
* TAB, must be the first character of every command: Section 22.16.
* TABs replaced with spaces by a text editor: Section 22.16.
* TCP/IP library for DJGPP: Section 22.3.
* Terminology in DJGPP: Section 22.23.
* Text-mode video memory access: Section 10.2.
* Timer interrupts code for DJGPP: Section 22.3.
* Traceback, how to read: Section 9.2.
* Tracing compilation progress with -Q: Section 6.4.
* Transfer buffer, moving data: Section 18.4.
* Transfer buffer, using to call DOS/BIOS: Section 18.2.
* Transfer buffer, what it is: Section 14.4.
* Truncation of files when using fstream: Section 9.3.
* Tuning CWSDPMI for optimal performance: Section 3.9.
* Turbo Vision, DJGPP port: Section 22.3.
* Tutorials on AT&T syntax and NASM: Section 17.1.
* TZ database updates, where to get: Section 22.19.
* TZ variable, how to set: Section 22.19.
* Undefined externals, with stdio functions and RSXNTDJ: Section 3.6.
* Undefined references to __EH_FRAME_BEGIN__: Section 8.19.
* Undefined references, and the RSXNTDJ linker: Section 3.6.
* Undefined references, in a DXE: Section 22.14.
* Undefined references, when linking Flex programs: Section 8.7.
* Uninitialized memory crashes v2.0 programs: Section 9.1.
* Uninstalling a package: Section 4.8.
* Unix-like sbrk algorithm considered harmful for HW interrupts: Section 18.11.
* Unix-to-DOS cross-compiling with DJGPP: Section 22.8.
* Unknown filetype, GCC message: Section 6.7.
* Unresolved externals: Section 8.7.
* Unresolved externals in C++ programs, use GXX: Section 8.7.
* Unresolved externals, C++: Section 8.10.
* Unresolved externals, djgpp_first_ctor: Section 8.11.
* Unsubscribing from the DJGPP mailing list: Section 20.4.
* Unsupported DOS request message: Section 18.1.
* Unsupported INT message: Section 18.1.
* Unzipping and running g++.exe produces an error message: Section 22.1.
* Uploading DJGPP software: Section 22.7.
* v2 code slower than v1.x: Section 14.2.
* V2, new features and bug fixes: Chapter 21.
* v2.0, program crashes: Section 9.1.
* v2.01 code slower than v2.0: Section 14.2.
* V2.x, new environment: Section 21.2.
* VBE 2.0 linear frame buffer access: Section 10.2.
* VBE services, struct declaration: Section 18.5.
* VDS, not supported by CWSDPMI (yet): Section 18.14.
* VESA support by GRX: Section 10.1.
* VFAT32 support under DOSEmu: Section 3.4.
* VGA Mode-X graphics for DJGPP: Section 22.3.
* Video memory, direct access: Section 10.2.
* Virtual memory: Chapter 15.
* Virtual memory exhausted, during compilation: Section 6.4.
* Virtual memory under Windows 9X: Section 15.6.
* Virtual memory, disabling with startup flags: Section 18.9.
* Virtual memory, failure to allocate: Section 15.3.
* Virtual memory, free doesn't change: Section 15.2.
* Virtual memory, how to disable it for CWSDPMI: Section 7.1.
* Virtual memory, malloc doesn't change: Section 15.2.
* Virtual memory, maximum available: Section 15.1.
* Virtual memory, QDPMI failure: Section 15.3.
* Virus infection cause "Not COFF" message: Section 6.7.
* void main, in a C program: Section 22.24.
* Watchpoints don't work in GDB under Windows: Section 12.10.
* Web site for DJGPP: Section 22.6.
* Weekly digest, problems in receiving: Section 20.3.
* Whitespace in wildcards: Section 16.3.
* Wildcards expansion: Section 16.1.
* Wildcards expansion, disabling: Section 16.2.
* Wildcards, and letter-case in file names: Section 16.1.
* Wildcards, and whitespace in file names: Section 16.3.
* Win32 programming with GCC: Section 3.6.
* Windows 9X/NT programming with Cygnus GCC port: Section 3.6.
* Windows applications with DJGPP: Section 3.6.
* Winsock interface for DJGPP: Section 22.3.
* WWW services for DJGPP: Section 22.6.
* WWW, downloading DJGPP: Section 4.4.
* X emulation for DJGPP: Section 22.3.
* Zip drive, accessed by the linker: Section 6.12.
* Zoneinfo directory: Section 22.19.

25. Program Index
*****************

  This index lists the problems and solutions by the program/package to which
they pertain.  If you know what program or package gives you the trouble,
look it up here.



* 386Max, how to ensure virtual memory: Section 15.3.
* 386Max, speeding up DJGPP start-up: Section 15.3.
* 4DOS, redirecting GCC messages to a file: Section 6.14.
* Allegro, compiling on DOSEmu: Section 3.4.
* ATT2INTL, a converter from AT&T to Intel assembly: Section 17.2.
* Bash crashes: Section 6.11.
* Bash hangs on Windows 9X: Section 6.1.
* BatchFTP, automated downloading from a Unix box: Section 4.7.
* BCCBGI (from BCC2GRX) crashes with the default stack: Section 15.9.
* BCSERIO, async communications package for DJGPP: Section 22.3.
* Binutils, incompatibilities with DJP: Section 8.13.
* Bison doesn't imply GPL/LGPL: Section 19.1.
* Bison, debugging generated code: Section 12.8.
* Boot loader for an operating system: Section 22.3.
* Cawf, using to read man pages: Section 5.5.
* CC1PLUS crashes with SIGSEGV: Section 15.9.
* CHCP DOS command might prevent MSHELL from working: Section 12.5.
* CPP, compiling, memory requirements: Section 3.8.
* CPP, compiling, RAM disk: Section 3.9.
* CWSDPMI allows ``Fat DS'': Section 18.6.
* CWSDPMI crashes programs allocating memory is small chunks: Section 15.4.
* CWSDPMI crashes programs which dereference NULL pointers: Section 9.1.
* CWSDPMI doesn't support hooking Int 24h: Section 22.12.
* CWSDPMI runs out of virtual memory: Section 6.6.
* CWSDPMI, alternative DPMI hosts: Section 21.2.
* CWSDPMI, disabling virtual memory: Section 7.1.
* CWSDPMI, legal restrictions: Section 19.2.
* CWSDPMI, maximum available virtual memory: Section 15.1.
* CWSDPMI, memory usage for nested programs: Section 15.8.
* CWSDPMI, minimum required system RAM: Section 3.1.
* CWSDPMI, pages too early under EMM386: Section 15.7.
* CWSDPMI, setting parameters for optimal performance: Section 3.9.
* CWSDPMI, should be distributed with DJGPP programs: Section 9.5.
* CWSDPR0 reduces interrupt reflection overhead: Section 18.11.
* CWSDPR0, use for testing HW interrupt handlers: Section 18.9.
* CWSPARAM, a program to tune CWSDPMI performance: Section 3.9.
* DISPLAY.SYS and EMM386, conflict with Info: Section 6.10.
* DJGPP.ENV syntax explained: Section 8.1.
* DJGPP.ENV, beware of blanks when setting: Section 8.1.
* DJGPP.ENV, compiler environment variables: Section 8.1.
* DJGPP.ENV, linker environment variables: Section 8.9.
* DJP compressor supports DLM: Section 8.13.
* DJP, an executable compressor for DJGPP: Section 8.13.
* DJP, incompatibilities with Binutils: Section 8.13.
* DLM compression, with DJP: Section 8.13.
* DLM, a facility to load code at run time: Section 22.3.
* DOSEMU doesn't allow ``Fat DS'': Section 18.6.
* DOSEmu, problems with FAT32 volumes: Section 3.4.
* DOSEmu, RHIDE conflicts with mouse support: Section 3.4.
* DXEGEN, undefined references: Section 22.14.
* EDEBUG32 can debug a DXE: Section 12.1.
* EGCS, a DJGPP port: Section 14.3.
* Emacs hangs on Windows 9X: Section 6.1.
* Emacs, reading docs: Section 5.1.
* Emacs, reading Info files: Section 5.1.
* Emacs, using to read man pages: Section 5.5.
* EMM386 and DISPLAY.SYS, conflict with Info: Section 6.10.
* EMM386, cannot use all free memory: Section 15.7.
* EMM386, conflicts with dual-monitor systems: Section 12.5.
* EMM386, effect on max interrupt frequency: Section 18.11.
* EMM386, getting the most memory: Section 3.9.
* EMM386, how to get more than 32MB of memory: Section 3.10.
* EMM386, malloc/calloc fails: Section 15.7.
* EMM386, settings for optimal performance: Section 3.9.
* emTeX, printing the docs: Section 5.3.
* emu387.dxe, distribution with DJGPP programs: Section 11.1.
* F2C, debugging generated code: Section 12.8.
* Flex doesn't imply GPL/LGPL: Section 19.1.
* Flex, debugging generated code: Section 12.8.
* Flex, undefined references: Section 8.7.
* FSDB crashes under QEMM/QDPMI: Section 12.3.
* FSDB, the full-screen debugger: Section 12.1.
* g++ compilation driver, alternative names on DOS: Section 8.9.
* g++.exe, unzip complains on DOS: Section 22.1.
* GCC aborts or crashes during compilation: Section 6.6.
* GCC can't find C++ headers: Section 8.2.
* GCC can't find crt0.o: Section 8.1.
* GCC can't find headers: Section 8.1.
* GCC can't find libraries: Section 8.1.
* GCC cannot resolve djgpp_first_ctor symbol when linking: Section 8.11.
* GCC crashes during optimization: Section 6.4.
* GCC crashes, which subprogram of: Section 6.13.
* GCC doesn't pack structs in C++ programs: Section 22.11.
* GCC doesn't recognize .lib libraries: Section 17.5.
* GCC doesn't recognize .obj object files: Section 17.5.
* GCC doesn't recognize file format: Section 8.4.
* GCC exhausts virtual memory: Section 6.4.
* GCC from v2.x crashes under v1.x Make: Section 6.8.
* GCC hangs under Make: Section 6.8.
* GCC says ``garbage at end of number'': Section 22.9.
* GCC won't compile C++-style comments in C programs: Section 8.3.
* GCC won't find inline functions without -O: Section 8.10.
* GCC, -fconserve-space switch: Section 8.12.
* GCC, -msoft-float switch: Section 11.4.
* GCC, -v switch shows the compilation passes: Section 8.4.
* GCC, assumes C++ source is .cc: Section 12.6.
* GCC, code efficiency: Section 14.1.
* GCC, compiling for debugging: Section 12.1.
* GCC, compiling, memory requirements: Section 3.8.
* GCC, compiling, RAM disk: Section 3.9.
* GCC, environment variables: Section 8.1.
* GCC, file source language recognition: Section 8.4.
* GCC, I/O speed: Section 14.4.
* GCC, inline assembly facilities: Section 18.13.
* GCC, maximum length of command line in Makefiles: Section 16.5.
* GCC, passing long command lines via Makefile: Section 16.6.
* GCC, recompiling: Section 22.2.
* GCC, redirecting messages to a file: Section 6.14.
* GCC, slow compilation: Section 7.1.
* GDB causes stack overflow in a debuggee: Section 15.9.
* GDB crashes under QEMM/QDPMI: Section 12.3.
* GDB doesn't pass command-line arguments to debuggee: Section 12.1.
* GDB doesn't recognize source language: Section 12.7.
* GDB fails to set or display static variables: Section 12.9.
* GDB GP Faults on breakpoint/watchpoint under Windows: Section 12.10.
* GDB needs COFF output: Section 12.4.
* GDB, conflicts with file redirection: Section 12.1.
* GDB, debugging DJGPP programs: Section 12.1.
* GDB, debugging graphics programs: Section 12.5.
* GDB, how is it different on MS-DOS: Section 12.1.
* GDB, how to use C++ class variables' names: Section 12.7.
* GDB, how to use C++ method names: Section 12.7.
* GDB, init file name: Section 12.1.
* GDB, name of the READLINE init file: Section 12.1.
* GDB, slow loading of symbols and sources: Section 12.1.
* go32-v2 reports the amount of memory and swap space: Section 4.6.
* go32-v2 usage: Section 22.13.
* go32-v2, use to find out how much memory is available to DJGPP: Section 15.7.
* Gprof cannot find program: Section 13.3.
* Gprof documentation: Section 13.4.
* gprof produces no output: Section 13.6.
* Gprof says ``bad format'': Section 13.3.
* Gprof, documentation: Section 5.4.
* Gprof, the GNU profiler: Section 13.1.
* Groff, port to DJGPP: Section 5.5.
* Groff, using to read man pages: Section 5.5.
* GRX, supported SVGA types: Section 10.1.
* gsymify, a substitute for SYMIFY for stabs debugging: Section 12.7.
* gxx driver, not in gcc272b distribution: Section 8.7.
* gxx driver, searches C++ libraries automatically: Section 8.7.
* HIMEM, malloc/calloc fails: Section 15.7.
* INFNG, produces the FAQ in Norton Guides format: Section 22.25.
* Info crashes due to ^Z or whitespace at end of DJGPP.ENV: Section 6.10.
* Info crashes immediately upon startup: Section 6.10.
* Info crashes under QDPMI: Section 6.3.
* Info hangs on Windows 9X: Section 6.1.
* Info won't display a file: Section 6.9.
* Info, a stand-alone docs browser: Section 5.1.
* Info, conflicts with DISPLAY.SYS, EMM386: Section 6.10.
* Info, using to read man pages: Section 5.5.
* install-info, a program to install Info docs: Section 4.5.
* Internet Explorer, downloading DJGPP: Section 4.4.
* JAS, a free assembler with Intel-like syntax: Section 17.2.
* LaTeX, printing the docs: Section 5.3.
* lcc-win32 compiler for Windows: Section 3.6.
* ld fails for a.out files in a library: Section 8.16.
* ld fails for large libraries and object files: Section 8.16.
* ld fails for obj files converted by EMXAOUT: Section 8.16.
* LD linker, linker script defines djgpp_first_ctor: Section 8.11.
* ld, how to improve linking speed: Section 7.2.
* ld.exe, from RSXNTDJ: Section 3.6.
* Less hangs on Windows 9X: Section 6.1.
* Less, using to read man pages: Section 5.5.
* Lex, debugging generated code: Section 12.8.
* libemu.a FP emulation library: Section 11.1.
* Linker can't find library functions in non-default directories: Section 8.9.
* Linker, environment variables: Section 8.9.
* Linker, how to get COFF output: Section 12.4.
* Linker, order of libraries in the command line: Section 8.9.
* Linux doesn't allow ``Fat DS'': Section 18.6.
* Linux, compatibility: Section 3.1.
* Linux, needs a patch to run nested programs: Section 3.4.
* Linux, slow response to interactive programs: Section 3.4.
* LWP multitasking for DJGPP: Section 22.3.
* Make crashes on DOSEmu: Section 3.4.
* Make crashes on OS/2: Section 3.2.
* Make error message ``missing separator'': Section 22.16.
* Make requires floating point: Section 22.2.
* Make, can be built to not issue FP instructions: Section 3.4.
* Make, GCC hangs when invoked from it: Section 6.8.
* Make, maximum length of command line to pass to GCC: Section 16.5.
* Make, passing long command lines via Makefile: Section 16.6.
* Make, warning ``file modification time in the future''.: Section 22.17.
* Makeinfo, using to convert Info files to plain ASCII: Section 5.2.
* MAKERTF, produces the FAQ in RTF format: Section 22.25.
* Man program for DJGPP docs: Section 5.5.
* MDA device driver for redirecting debug output: Section 12.5.
* Mingw32 port of GCC: Section 3.6.
* More, using to read man pages: Section 5.5.
* MSHELL fails because of TSR programs: Section 12.5.
* MSHELL, redirecting screen output: Section 12.5.
* NASM, a portable assembler with Intel syntax support: Section 17.2.
* NASM, a tutorial on usage with DJGPP: Section 17.1.
* Netscape, downloading DJGPP: Section 4.4.
* NM, printing library contents: Section 8.8.
* Novell 3.X, linker doesn't find crt0.o: Section 8.1.
* Novell NWDOS 7, buggy DPMI services: Section 3.1.
* Novell NWDOS 7, compatibility: Section 3.1.
* Novell VLM causes slow-down of DJGPP programs: Section 14.5.
* NWDOS, buggy DPMI services crash DJGPP: Section 6.3.
* OBJ2BFD converter from .obj to COFF format: Section 17.5.
* OBJ2COFF converter from .obj to COFF format: Section 17.5.
* OBJ2COFF, commercial use is prohibited: Section 17.5.
* Objective C, compilation problems: Section 8.5.
* Objective-C, cannot run on machines without FPU: Section 11.7.
* OpenDOS, bug in DPMI services crash DJGPP: Section 6.3.
* OS/2 and RHIDE: Section 3.2.
* OS/2 Warp allows ``Fat DS'': Section 18.6.
* OS/2, and _go32_remaining_physical_memory: Section 15.2.
* OS/2, compatibility: Section 3.1.
* OS/2, floating point emulation: Section 11.3.
* OS/2, incompatibilities: Section 3.2.
* PGCC: Section 14.3.
* PGCC exhausts virtual memory: Section 6.4.
* PGCC, bugs with optimization levels -O7 and higher: Section 14.2.
* PKUNZIP v2.50, creates numeric tails: Section 22.18.
* PMODE/DJ reduces interrupt reflection overhead: Section 18.11.
* PMODE/DJ, can be used to produce stand-alone programs: Section 9.5.
* POVRAY, linker fails to link the library: Section 8.16.
* Pthreads for DJGPP: Section 22.3.
* Q87, an emulator compatible with DJGPP: Section 11.2.
* QDPMI allows ``Fat DS'': Section 18.6.
* QDPMI and _crt0_startup_flags settings: Section 15.3.
* QDPMI crashes debugger: Section 12.3.
* QDPMI crashes DJGPP programs when they cause Int 24h: Section 22.12.
* QDPMI crashes Info and debuggers: Section 6.3.
* QDPMI fails to provide virtual memory: Section 15.3.
* QDPMI, how to disable: Section 12.3.
* QDPMI, malloc/calloc failure: Section 15.4.
* QDPMI, memory usage for nested programs: Section 15.8.
* QEMM crashes debugger: Section 12.3.
* QEMM, how to get more than 64MB of memory: Section 3.10.
* QEMM386, settings for optimal performance: Section 3.9.
* RCS port to DJGPP: Section 22.3.
* REDIR, redirecting GCC messages to a file: Section 6.14.
* REDIR, redirecting stack dump to a file: Section 9.2.
* REDIR, use to get redirection and long command lines: Section 16.6.
* RHGDB fails to set or display static variables: Section 12.9.
* RHIDE aborts on OS/2: Section 3.2.
* RHIDE debugger GP Faults on breakpoints under Windows: Section 12.10.
* RHIDE fails to set or display static variables: Section 12.9.
* RHIDE hangs on Windows 9X: Section 6.1.
* RHIDE, and monochrome display: Section 12.5.
* RHIDE, includes an integrated debugger: Section 12.1.
* RHIDE, long command lines: Section 16.6.
* RHIDE, mouse problems on DOSEmu: Section 3.4.
* RHIDE, reading docs: Section 5.1.
* RSXNTDJ toolkit for developing Win32 applications: Section 3.6.
* RSXNTDJ, MS Platform SDK: Section 3.6.
* RSXNTDJ, using with GCC 2.8.1 and later: Section 3.6.
* SCRIPT, redirecting GCC messages to a file: Section 6.14.
* Sed requires floating point: Section 22.2.
* Sed script to convert ASM to AT&T syntax: Section 17.2.
* Sed, documentation: Section 5.4.
* Sed, using to convert formatted man pages to plain text: Section 5.5.
* SHARE, limits available file handles: Section 9.6.
* STRIP makes executables smaller: Section 8.13.
* STUBEDIT, changing stack size: Section 15.9.
* STUBEDIT, effect on memory left to spawned programs: Section 15.8.
* STUBIFY fails to produce .EXE under Novell: Section 8.15.
* STUBIFY.EXE, infected by a virus: Section 6.7.
* SYMIFY, a program to read crash traceback: Section 9.2.
* SYMIFY, inaccurate report for inline assembly: Section 9.2.
* TA2AS, a converter from Intel to AT&T assembly syntax: Section 17.2.
* TeX, printing the docs: Section 5.3.
* TEXI2PS, converting docs to crude PostScript: Section 5.3.
* TkInfo, a Win32 tool to read Info files: Section 5.1.
* UNIVBE, software VESA 2.0 emulation: Section 10.1.
* Warp, compatibility: Section 3.1.
* Warp, incompatibilities: Section 3.2.
* Windows 3.X allows ``Fat DS'': Section 18.6.
* Windows 3.X, compatibility: Section 3.1.
* Windows 3.X, malloc/calloc fails: Section 15.5.
* Windows 9X allows ``Fat DS'': Section 18.6.
* Windows 9X doesn't allow more than 16MB virtual memory: Section 15.6.
* Windows 9X DPMI server loses selectors calling spawnXX: Section 3.3.
* Windows 9X long filenames and C++ headers: Section 8.2.
* Windows 9X, compatibility: Section 3.1.
* Windows 9X, how to get more than 64MB of DPMI memory: Section 3.10.
* Windows 9X, setting DJGPP environment variable: Section 8.1.
* Windows 9X, shortcut files conflict with ld: Section 8.14.
* Windows messes up graphics screen: Section 10.3.
* Windows, malloc/calloc failure: Section 15.4.
* Windows, memory usage for nested programs: Section 15.8.
* Windows, setting memory parameters for DJGPP: Section 3.9.
* Windows, stack size control: Section 15.9.
* Windows, wants to run graphics programs in DOS Mode: Section 10.3.
* Windows/NT doesn't allow ``Fat DS'': Section 18.6.
* Windows/NT doesn't allow port I/O: Section 3.3.
* Windows/NT DPMI server loses selectors calling spawnXX: Section 3.3.
* Windows/NT LFN driver: Section 3.3.
* Windows/NT, compatibility: Section 3.1.
* WindowsNT, setting DJGPP environment variable: Section 8.1.
* WMEMU causes undefined references when linking: Section 11.1.
* WMEMU, an alternative floating-point emulator: Section 11.1.
* WMEMU, use when debugging FP programs on non-FPU machine: Section 12.10.
* Yacc, debugging generated code: Section 12.8.

